KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_dimension.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2012 Jean-Pierre Charras, [email protected]
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2012 Wayne Stambaugh <[email protected]>
7 * Copyright (C) 2023 CERN
8 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#include <bitmaps.h>
25#include <pcb_edit_frame.h>
26#include <base_units.h>
28#include <font/font.h>
29#include <board.h>
30#include <footprint.h>
31#include <pcb_dimension.h>
32#include <pcb_painter.h>
33#include <pcb_text.h>
34#include <view/view.h>
39#include <geometry/shape_rect.h>
43#include <trigo.h>
44#include <api/api_enums.h>
45#include <api/api_utils.h>
46#include <api/board/board_types.pb.h>
47#include <properties/property.h>
50
53
54
56
57static const EDA_ANGLE s_arrowAngle( 27.5, DEGREES_T );
58
59
68static OPT_VECTOR2I segPolyIntersection( const SHAPE_POLY_SET& aPoly, const SEG& aSeg,
69 bool aStart = true )
70{
71 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
72 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
73
74 if( aPoly.Contains( start ) )
75 return std::nullopt;
76
77 for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
78 {
79 if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
80 {
81 if( ( *intersection - start ).SquaredEuclideanNorm()
82 < ( endpoint - start ).SquaredEuclideanNorm() )
83 endpoint = *intersection;
84 }
85 }
86
87 if( start == endpoint )
88 return std::nullopt;
89
90 return OPT_VECTOR2I( endpoint );
91}
92
93
94static OPT_VECTOR2I segCircleIntersection( CIRCLE& aCircle, SEG& aSeg, bool aStart = true )
95{
96 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
97 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
98
99 if( aCircle.Contains( start ) )
100 return std::nullopt;
101
102 std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
103
104 for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
105 {
106 if( ( intersection - start ).SquaredEuclideanNorm()
107 < ( endpoint - start ).SquaredEuclideanNorm() )
108 endpoint = intersection;
109 }
110
111 if( start == endpoint )
112 return std::nullopt;
113
114 return OPT_VECTOR2I( endpoint );
115}
116
117
122static void CollectKnockedOutSegments( const SHAPE_POLY_SET& aPoly, const SEG& aSeg,
123 std::vector<std::shared_ptr<SHAPE>>& aSegmentsAfterKnockout )
124{
125 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
126 const bool containsA = aPoly.Contains( aSeg.A );
127 const bool containsB = aPoly.Contains( aSeg.B );
128
129 const OPT_VECTOR2I endpointA = segPolyIntersection( aPoly, aSeg );
130 const OPT_VECTOR2I endpointB = segPolyIntersection( aPoly, aSeg, false );
131
132 if( endpointA )
133 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( aSeg.A, *endpointA ) );
134
135 if( endpointB )
136 {
137 bool can_add = true;
138
139 if( endpointA )
140 {
141 if( ( *endpointB == aSeg.A && *endpointA == aSeg.B )
142 || ( *endpointA == *endpointB && aSeg.A == aSeg.B ) )
143 can_add = false;
144 }
145
146 if( can_add )
147 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( *endpointB, aSeg.B ) );
148 }
149
150 if( !containsA && !containsB && !endpointA && !endpointB )
151 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( aSeg ) );
152}
153
154
156 PCB_TEXT( aParent, aType ),
157 m_overrideTextEnabled( false ),
159 m_autoUnits( false ),
163 m_suppressZeroes( false ),
164 m_lineThickness( pcbIUScale.mmToIU( 0.2 ) ),
165 m_arrowLength( pcbIUScale.MilsToIU( 50 ) ),
168 m_keepTextAligned( true ),
169 m_measuredValue( 0 ),
170 m_start( 0, 0 ),
171 m_end( 0, 0 ),
172 m_inClearRenderCache( false )
173{
175 m_busy = false;
176}
177
178
180{
181 if( const FOOTPRINT* fp = GetParentFootprint() )
182 return fp->GetTransform().Apply( m_start );
183
184 return m_start;
185}
186
187
189{
190 if( const FOOTPRINT* fp = GetParentFootprint() )
191 return fp->GetTransform().Apply( m_end );
192
193 return m_end;
194}
195
196
198{
199 if( const FOOTPRINT* fp = GetParentFootprint() )
200 m_start = fp->GetTransform().InverseApply( aPoint );
201 else
202 m_start = aPoint;
203}
204
205
207{
208 if( const FOOTPRINT* fp = GetParentFootprint() )
209 m_end = fp->GetTransform().InverseApply( aPoint );
210 else
211 m_end = aPoint;
212}
213
214
215void PCB_DIMENSION_BASE::OnFootprintRescaled( double /* aRatioX */, double /* aRatioY */, double /* aLinearFactor */,
216 const VECTOR2I& /* aAnchor */, const EDA_ANGLE& /* aParentRotate */ )
217{
220}
221
222
230
231
233{
234 if( Type() != aOther.Type() )
235 return false;
236
237 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
238
239 return *this == other;
240}
241
242
244{
245 if( m_textPosition != aOther.m_textPosition )
246 return false;
247
249 return false;
250
251 if( m_units != aOther.m_units )
252 return false;
253
254 if( m_autoUnits != aOther.m_autoUnits )
255 return false;
256
257 if( m_unitsFormat != aOther.m_unitsFormat )
258 return false;
259
260 if( m_precision != aOther.m_precision )
261 return false;
262
263 if( m_suppressZeroes != aOther.m_suppressZeroes )
264 return false;
265
266 if( m_lineThickness != aOther.m_lineThickness )
267 return false;
268
269 if( m_arrowLength != aOther.m_arrowLength )
270 return false;
271
273 return false;
274
275 if( m_measuredValue != aOther.m_measuredValue )
276 return false;
277
278 return EDA_TEXT::operator==( aOther );
279}
280
281
282double PCB_DIMENSION_BASE::Similarity( const BOARD_ITEM& aOther ) const
283{
284 if( m_Uuid == aOther.m_Uuid )
285 return 1.0;
286
287 if( Type() != aOther.Type() )
288 return 0.0;
289
290 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
291
292 double similarity = 1.0;
293
294 if( m_textPosition != other.m_textPosition )
295 similarity *= 0.9;
296
298 similarity *= 0.9;
299
300 if( m_units != other.m_units )
301 similarity *= 0.9;
302
303 if( m_autoUnits != other.m_autoUnits )
304 similarity *= 0.9;
305
306 if( m_unitsFormat != other.m_unitsFormat )
307 similarity *= 0.9;
308
309 if( m_precision != other.m_precision )
310 similarity *= 0.9;
311
313 similarity *= 0.9;
314
315 if( m_lineThickness != other.m_lineThickness )
316 similarity *= 0.9;
317
318 if( m_arrowLength != other.m_arrowLength )
319 similarity *= 0.9;
320
322 similarity *= 0.9;
323
324 if( m_measuredValue != other.m_measuredValue )
325 similarity *= 0.9;
326
327 similarity *= EDA_TEXT::Similarity( other );
328
329 return similarity;
330}
331
332
333void PCB_DIMENSION_BASE::Serialize( google::protobuf::Any &aContainer ) const
334{
335 using namespace kiapi::common;
336 using namespace kiapi::board::types;
337 Dimension dimension;
338
339 dimension.mutable_id()->set_value( m_Uuid.AsStdString() );
340 dimension.set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( GetLayer() ) );
341 dimension.set_locked( IsLocked() ? types::LockedState::LS_LOCKED
342 : types::LockedState::LS_UNLOCKED );
343
344 EDA_TEXT::Serialize( *dimension.mutable_text(), pcbIUScale );
345
346 types::Text* text = dimension.mutable_text();
347 text->set_text( GetValueText() );
348
349 dimension.set_override_text_enabled( m_overrideTextEnabled );
350 dimension.set_override_text( m_valueString.ToUTF8() );
351 dimension.set_prefix( m_prefix.ToUTF8() );
352 dimension.set_suffix( m_suffix.ToUTF8() );
353
355 dimension.set_unit_format(
357 dimension.set_arrow_direction(
360 dimension.set_suppress_trailing_zeroes( m_suppressZeroes );
361
362 if( FOOTPRINT* parent = GetParentFootprint() )
363 dimension.mutable_parent()->set_value( parent->m_Uuid.AsStdString() );
364 else if( const BOARD* board = GetBoard() )
365 dimension.mutable_parent()->set_value( board->m_Uuid.AsStdString() );
366
367 dimension.mutable_line_thickness()->set_value_nm( m_lineThickness );
368 dimension.mutable_arrow_length()->set_value_nm( m_arrowLength );
369 dimension.mutable_extension_offset()->set_value_nm( m_extensionOffset );
370 dimension.set_text_position(
372 dimension.set_keep_text_aligned( m_keepTextAligned );
373
374 kiapi::common::PackCustomProperties( dimension.mutable_custom_properties(), *this );
375 aContainer.PackFrom( dimension );
376}
377
378
379bool PCB_DIMENSION_BASE::Deserialize( const google::protobuf::Any &aContainer )
380{
381 using namespace kiapi::common;
382 kiapi::board::types::Dimension dimension;
383
384 if( !aContainer.UnpackTo( &dimension ) )
385 return false;
386
388 SetUuidDirect( KIID( dimension.id().value() ) );
389 SetLocked( dimension.locked() == types::LockedState::LS_LOCKED );
390
391 EDA_TEXT::Deserialize( dimension.text(), pcbIUScale );
392
393 SetOverrideTextEnabled( dimension.override_text_enabled() );
394 SetOverrideText( wxString::FromUTF8( dimension.override_text() ) );
395 SetPrefix( wxString::FromUTF8( dimension.prefix() ) );
396 SetSuffix( wxString::FromUTF8( dimension.suffix() ) );
397
398 SetUnitsMode( FromProtoEnum<DIM_UNITS_MODE>( dimension.unit() ) );
399 SetUnitsFormat( FromProtoEnum<DIM_UNITS_FORMAT>( dimension.unit_format() ) );
400 SetArrowDirection( FromProtoEnum<DIM_ARROW_DIRECTION>( dimension.arrow_direction() ) );
401 SetPrecision( FromProtoEnum<DIM_PRECISION>( dimension.precision() ) );
402 SetSuppressZeroes( dimension.suppress_trailing_zeroes() );
403
404 SetLineThickness( dimension.line_thickness().value_nm() );
405 SetArrowLength( dimension.arrow_length().value_nm() );
406 SetExtensionOffset( dimension.extension_offset().value_nm() );
407 SetTextPositionMode( FromProtoEnum<DIM_TEXT_POSITION>( dimension.text_position() ) );
408 SetKeepTextAligned( dimension.keep_text_aligned() );
409
410 kiapi::common::UnpackCustomProperties( dimension.custom_properties(), *this );
411
412 Update();
413
414 return true;
415}
416
417
418void PCB_DIMENSION_BASE::drawAnArrow( VECTOR2I startPoint, EDA_ANGLE anAngle, int aLength )
419{
420 if( aLength )
421 {
422 VECTOR2I tailEnd( aLength, 0 );
423 RotatePoint( tailEnd, -anAngle );
424 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + tailEnd ) );
425 }
426
427 VECTOR2I arrowEndPos( m_arrowLength, 0 );
428 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
429
430 RotatePoint( arrowEndPos, -anAngle + s_arrowAngle );
431 RotatePoint( arrowEndNeg, -anAngle - s_arrowAngle );
432
433 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + arrowEndPos ) );
434 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + arrowEndNeg ) );
435}
436
437
439{
441
442 switch( m_unitsFormat )
443 {
444 case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
445 break;
446
447 case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
449 break;
450
451 case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
452 text += wxT( " (" ) + EDA_UNIT_UTILS::GetText( m_units ).Trim( false ) + wxT( ")" );
453 break;
454 }
455
456 text.Prepend( m_prefix );
457 text.Append( m_suffix );
458
459 SetText( text );
460}
461
462
464{
466
467 // We use EDA_TEXT::ClearRenderCache() as a signal that the properties of the EDA_TEXT
468 // have changed and we may need to update the dimension text
469
471 {
473 Update();
474 m_inClearRenderCache = false;
475 }
476}
477
478
479template<typename ShapeType>
480void PCB_DIMENSION_BASE::addShape( const ShapeType& aShape )
481{
482 m_shapes.push_back( std::make_shared<ShapeType>( aShape ) );
483}
484
485
487{
488 struct lconv* lc = localeconv();
489 wxChar sep = lc->decimal_point[0];
490
491 int val = GetMeasuredValue();
492 int precision = static_cast<int>( m_precision );
493 wxString text;
494
495 if( precision >= 6 )
496 {
497 switch( m_units )
498 {
499 case EDA_UNITS::INCH: precision = precision - 4; break;
500 case EDA_UNITS::MILS: precision = std::max( 0, precision - 7 ); break;
501 case EDA_UNITS::MM: precision = precision - 5; break;
502 default: precision = precision - 4; break;
503 }
504 }
505
506 wxString format = wxT( "%." ) + wxString::Format( wxT( "%i" ), precision ) + wxT( "f" );
507
508 text.Printf( format, EDA_UNIT_UTILS::UI::ToUserUnit( pcbIUScale, m_units, val ) );
509
510 if( m_suppressZeroes )
511 {
512 while( text.EndsWith( '0' ) )
513 {
514 text.RemoveLast();
515
516 if( text.EndsWith( '.' ) || text.EndsWith( sep ) )
517 {
518 text.RemoveLast();
519 break;
520 }
521 }
522 }
523
524 return text;
525}
526
527
529{
530 // Read only here but shared lookup helpers require a mutable board pointer
531 BOARD* board = const_cast<BOARD*>( GetBoard() );
532
533 return DimensionValueMode( board, this );
534}
535
536
542
543
545{
546 switch( GetValueMode() )
547 {
549 {
550 PCB_CONSTRAINT* lengthConstraint =
551 FindDimensionLengthConstraint( const_cast<BOARD*>( GetBoard() ), this );
552
553 if( lengthConstraint && lengthConstraint->GetValue() )
554 {
556 *lengthConstraint->GetValue() );
557 }
558
559 return GetValueText();
560 }
561
563 return GetOverrideText();
564
566 default:
567 return GetValueText();
568 }
569}
570
571
572void PCB_DIMENSION_BASE::ChangeValueFieldText( const wxString& aText )
573{
575 {
576 SetOverrideText( aText );
577 Update();
578 }
579}
580
581
582void PCB_DIMENSION_BASE::SetPrefix( const wxString& aPrefix )
583{
584 m_prefix = aPrefix;
585}
586
587
588void PCB_DIMENSION_BASE::SetSuffix( const wxString& aSuffix )
589{
590 m_suffix = aSuffix;
591}
592
593
595{
596 m_units = aUnits;
597}
598
599
601{
602 if( m_autoUnits )
603 {
605 }
606 else
607 {
608 switch( m_units )
609 {
610 default:
614 }
615 }
616}
617
618
620{
621 switch( aMode )
622 {
624 m_autoUnits = false;
626 break;
627
629 m_autoUnits = false;
631 break;
632
634 m_autoUnits = false;
636 break;
637
639 m_autoUnits = true;
641 break;
642 }
643}
644
645
647{
648 SetTextAngleDegrees( aDegrees );
649 // Create or repair any knockouts
650 Update();
651}
652
653
655{
656 SetKeepTextAligned( aKeepAligned );
657 // Re-align the text and repair any knockouts
658 Update();
659}
660
661
663{
664 PCB_TEXT::Offset( offset );
665
666 if( const FOOTPRINT* fp = GetParentFootprint() )
667 {
668 const TRANSFORM_TRS& xform = fp->GetTransform();
669 VECTOR2I libOffset = xform.InverseApply( offset ) - xform.InverseApply( VECTOR2I( 0, 0 ) );
670 m_start += libOffset;
671 m_end += libOffset;
672 }
673 else
674 {
675 m_start += offset;
676 m_end += offset;
677 }
678
679 Update();
680}
681
682
683void PCB_DIMENSION_BASE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
684{
685 EDA_ANGLE newAngle = GetTextAngle() + aAngle;
686 newAngle.Normalize();
687 SetTextAngle( newAngle );
688
689 VECTOR2I pt = GetTextPos();
690 RotatePoint( pt, aRotCentre, aAngle );
691 SetTextPos( pt );
692
693 VECTOR2I boardStart = GetStart();
694 VECTOR2I boardEnd = GetEnd();
695 RotatePoint( boardStart, aRotCentre, aAngle );
696 RotatePoint( boardEnd, aRotCentre, aAngle );
697
698 if( const FOOTPRINT* fp = GetParentFootprint() )
699 {
700 m_start = fp->GetTransform().InverseApply( boardStart );
701 m_end = fp->GetTransform().InverseApply( boardEnd );
702 }
703 else
704 {
705 m_start = boardStart;
706 m_end = boardEnd;
707 }
708
709 Update();
710}
711
712
713void PCB_DIMENSION_BASE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
714{
715 Mirror( aCentre, aFlipDirection );
716
718}
719
720
721void PCB_DIMENSION_BASE::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
722{
723 if( const FOOTPRINT* fp = GetParentFootprint() )
724 {
725 const VECTOR2I libAxis = fp->GetTransform().InverseApply( axis_pos );
726
727 auto mirrorPt = [&]( VECTOR2I& p )
728 {
729 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
730 p.x = 2 * libAxis.x - p.x;
731 else
732 p.y = 2 * libAxis.y - p.y;
733 };
734
735 mirrorPt( m_start );
736 mirrorPt( m_end );
737
738 VECTOR2I libTextPos = EDA_TEXT::GetTextPos();
739 mirrorPt( libTextPos );
740 EDA_TEXT::SetTextPos( libTextPos );
741
742 EDA_ANGLE newLibAngle =
744 SetLibTextAngle( newLibAngle );
745
746 if( IsSideSpecific() )
748
750 Update();
751 return;
752 }
753
754 VECTOR2I newPos = GetTextPos();
755
756 MIRROR( newPos, axis_pos, aFlipDirection );
757
758 SetTextPos( newPos );
759
760 // invert angle
762
763 MIRROR( m_start, axis_pos, aFlipDirection );
764 MIRROR( m_end, axis_pos, aFlipDirection );
765
766 if( IsSideSpecific() )
768
769 Update();
770}
771
772
773void PCB_DIMENSION_BASE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
774{
775 PCB_TEXT::StyleFromSettings( settings, aCheckSide );
776
784
785 Update(); // refresh text & geometry
786
787}
788
789
791 std::vector<MSG_PANEL_ITEM>& aList )
792{
793 // for now, display only the text within the DIMENSION using class PCB_TEXT.
794 wxString msg;
795
796 wxCHECK_RET( m_parent != nullptr, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
797
798 // Don't use GetShownText(); we want to see the variable references here
799 aList.emplace_back( _( "Dimension" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
800
801 aList.emplace_back( _( "Prefix" ), GetPrefix() );
802
804 {
805 aList.emplace_back( _( "Override Text" ), GetOverrideText() );
806 }
807 else
808 {
809 aList.emplace_back( _( "Value" ), GetValueText() );
810
811 switch( GetPrecision() )
812 {
813 case DIM_PRECISION::V_VV: msg = wxT( "0.00 in / 0 mils / 0.0 mm" ); break;
814 case DIM_PRECISION::V_VVV: msg = wxT( "0.000 in / 0 mils / 0.00 mm" ); break;
815 case DIM_PRECISION::V_VVVV: msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" ); break;
816 case DIM_PRECISION::V_VVVVV: msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
817 default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
818 }
819
820 aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
821 }
822
823 aList.emplace_back( _( "Suffix" ), GetSuffix() );
824
825 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
826 // in frame's units.
827 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MM );
828 unitsProvider.SetUserUnits( GetUnits() );
829
830 aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( GetUnits() ) );
831
832 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
833 aList.emplace_back( _( "Text Thickness" ), unitsProvider.MessageTextFromValue( GetTextThickness() ) );
834 aList.emplace_back( _( "Text Width" ), unitsProvider.MessageTextFromValue( GetTextWidth() ) );
835 aList.emplace_back( _( "Text Height" ), unitsProvider.MessageTextFromValue( GetTextHeight() ) );
836
837 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
838
839 if( Type() == PCB_DIM_CENTER_T )
840 {
841 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
842 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
843 aFrame->MessageTextFromValue( startCoord.x ),
844 aFrame->MessageTextFromValue( startCoord.y ) );
845
846 aList.emplace_back( start, wxEmptyString );
847 }
848 else
849 {
850 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
851 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
852 aFrame->MessageTextFromValue( startCoord.x ),
853 aFrame->MessageTextFromValue( startCoord.y ) );
854 VECTOR2I endCoord = originTransforms.ToDisplayAbs( GetEnd() );
855 wxString end = wxString::Format( wxT( "@(%s, %s)" ),
856 aFrame->MessageTextFromValue( endCoord.x ),
857 aFrame->MessageTextFromValue( endCoord.y ) );
858
859 aList.emplace_back( start, end );
860 }
861
862 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
863 aList.emplace_back( _( "Status" ), _( "Locked" ) );
864
865 aList.emplace_back( _( "Layer" ), GetLayerName() );
866}
867
868
870{
871 std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
872
873 effectiveShape->AddShape( GetEffectiveTextShape()->Clone() );
874
875 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
876 effectiveShape->AddShape( shape->Clone() );
877
878 return effectiveShape;
879}
880
881
882bool PCB_DIMENSION_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
883{
884 if( TextHitTest( aPosition ) )
885 return true;
886
887 int dist_max = aAccuracy + ( m_lineThickness / 2 );
888
889 // Locate SEGMENTS
890
891 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
892 {
893 if( shape->Collide( aPosition, dist_max ) )
894 return true;
895 }
896
897 return false;
898}
899
900
901bool PCB_DIMENSION_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
902{
903 BOX2I arect = aRect;
904 arect.Inflate( aAccuracy );
905
906 BOX2I rect = GetBoundingBox();
907
908 if( aAccuracy )
909 rect.Inflate( aAccuracy );
910
911 if( aContained )
912 return arect.Contains( rect );
913
914 return arect.Intersects( rect );
915}
916
917
918bool PCB_DIMENSION_BASE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
919{
920 // Note: Can't use GetEffectiveShape() because we want text as BoundingBox, not as graphics.
921 SHAPE_COMPOUND effShape;
922
923 // Add shapes
924 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
925 effShape.AddShape( shape );
926
927 if( aContained )
928 return TextHitTest( aPoly, aContained ) && KIGEOM::ShapeHitTest( aPoly, effShape, aContained );
929 else
930 return TextHitTest( aPoly, aContained ) || KIGEOM::ShapeHitTest( aPoly, effShape, aContained );
931}
932
933
935{
936 BOX2I bBox;
937 int xmin, xmax, ymin, ymax;
938
939 bBox = GetTextBox( nullptr );
940 xmin = bBox.GetX();
941 xmax = bBox.GetRight();
942 ymin = bBox.GetY();
943 ymax = bBox.GetBottom();
944
945 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
946 {
947 BOX2I shapeBox = shape->BBox();
948 shapeBox.Inflate( m_lineThickness / 2 );
949
950 xmin = std::min( xmin, shapeBox.GetOrigin().x );
951 xmax = std::max( xmax, shapeBox.GetEnd().x );
952 ymin = std::min( ymin, shapeBox.GetOrigin().y );
953 ymax = std::max( ymax, shapeBox.GetEnd().y );
954 }
955
956 bBox.SetX( xmin );
957 bBox.SetY( ymin );
958 bBox.SetWidth( xmax - xmin + 1 );
959 bBox.SetHeight( ymax - ymin + 1 );
960
961 bBox.Normalize();
962
963 return bBox;
964}
965
966
967wxString PCB_DIMENSION_BASE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
968{
969 return wxString::Format( _( "Dimension '%s' on %s" ),
971 GetLayerName() );
972}
973
974
975
977{
979 VECTOR2I( GetBoundingBox().GetSize() ) );
980 dimBBox.Merge( PCB_TEXT::ViewBBox() );
981
982 return dimBBox;
983}
984
985
986std::vector<int> PCB_DIMENSION_BASE::ViewGetLayers() const
987{
988 std::vector<int> layers = PCB_TEXT::ViewGetLayers();
989
990 // Always advertised while ViewGetLOD gates the draw on actual constraint reference
991 layers.push_back( LAYER_CONSTRAINT_SHADOW );
992
993 return layers;
994}
995
996
997double PCB_DIMENSION_BASE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
998{
999 if( aLayer == LAYER_CONSTRAINT_SHADOW && aView )
1000 {
1001 KIGFX::PCB_RENDER_SETTINGS& renderSettings =
1002 *static_cast<KIGFX::PCB_PAINTER&>( *aView->GetPainter() ).GetSettings();
1003
1004 if( !renderSettings.GetConstrainedItems().count( m_Uuid ) )
1005 return LOD_HIDE;
1006
1007 if( !aView->IsLayerVisibleCached( GetLayer() ) )
1008 return LOD_HIDE;
1009
1010 if( renderSettings.GetHighContrast() && GetLayer() != renderSettings.GetPrimaryHighContrastLayer() )
1011 return LOD_HIDE;
1012
1013 return LOD_SHOW;
1014 }
1015
1016 return PCB_TEXT::ViewGetLOD( aLayer, aView );
1017}
1018
1019
1021 int aClearance, int aError, ERROR_LOC aErrorLoc,
1022 bool aIgnoreLineWidth ) const
1023{
1024 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
1025
1026 for( const std::shared_ptr<SHAPE>& shape : m_shapes )
1027 {
1028 const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
1029 const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
1030
1031 if( circle )
1032 {
1033 TransformCircleToPolygon( aBuffer, circle->GetCenter(),
1034 circle->GetRadius() + m_lineThickness / 2 + aClearance,
1035 aError, aErrorLoc );
1036 }
1037 else if( seg )
1038 {
1039 TransformOvalToPolygon( aBuffer, seg->GetSeg().A, seg->GetSeg().B,
1040 m_lineThickness + 2 * aClearance, aError, aErrorLoc );
1041 }
1042 else
1043 {
1044 wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeToPolygon unknown shape type." ) );
1045 }
1046 }
1047}
1048
1049
1051 PCB_DIMENSION_BASE( aParent, aType ),
1052 m_height( 0 )
1053{
1054 // To preserve look of old dimensions, initialize extension height based on default arrow length
1055 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
1056}
1057
1058
1060{
1061 return new PCB_DIM_ALIGNED( *this );
1062}
1063
1064
1066{
1067 wxCHECK( aOther && aOther->Type() == PCB_DIM_ALIGNED_T, /* void */ );
1068 *this = *static_cast<const PCB_DIM_ALIGNED*>( aOther );
1069}
1070
1071void PCB_DIM_ALIGNED::Serialize( google::protobuf::Any &aContainer ) const
1072{
1073 using namespace kiapi::common;
1074 kiapi::board::types::Dimension dimension;
1075
1076 PCB_DIMENSION_BASE::Serialize( aContainer );
1077 aContainer.UnpackTo( &dimension );
1078
1079 PackVector2( *dimension.mutable_aligned()->mutable_start(), GetStart() );
1080 PackVector2( *dimension.mutable_aligned()->mutable_end(), GetEnd() );
1081 dimension.mutable_aligned()->mutable_height()->set_value_nm( m_height );
1082 dimension.mutable_aligned()->mutable_extension_height()->set_value_nm( m_extensionHeight );
1083
1084 aContainer.PackFrom( dimension );
1085}
1086
1087
1088bool PCB_DIM_ALIGNED::Deserialize( const google::protobuf::Any &aContainer )
1089{
1090 using namespace kiapi::common;
1091
1092 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1093 return false;
1094
1095 kiapi::board::types::Dimension dimension;
1096 aContainer.UnpackTo( &dimension );
1097
1098 if( !dimension.has_aligned() )
1099 return false;
1100
1101 SetStart( UnpackVector2( dimension.aligned().start() ) );
1102 SetEnd( UnpackVector2( dimension.aligned().end() ) );
1103 SetHeight( dimension.aligned().height().value_nm());
1104 SetExtensionHeight( dimension.aligned().extension_height().value_nm() );
1105
1106 Update();
1107
1108 return true;
1109}
1110
1111
1113{
1114 wxASSERT( aImage->Type() == Type() );
1115
1116 m_shapes.clear();
1117 static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
1118
1119 std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
1120
1121 Update();
1122}
1123
1124
1125void PCB_DIM_ALIGNED::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
1126{
1127 m_height = -m_height;
1128 // Call this last for the Update()
1129 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
1130}
1131
1132
1137
1138
1139void PCB_DIM_ALIGNED::UpdateHeight( const VECTOR2I& aCrossbarStart, const VECTOR2I& aCrossbarEnd )
1140{
1141 VECTOR2D height( aCrossbarStart - GetStart() );
1142 VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
1143
1144 if( height.Cross( crossBar ) > 0 )
1145 m_height = -height.EuclideanNorm();
1146 else
1147 m_height = height.EuclideanNorm();
1148
1149 Update();
1150}
1151
1152
1154{
1155 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1156 return;
1157
1158 m_busy = true;
1159
1160 m_shapes.clear();
1161
1162 const VECTOR2I start = GetStart();
1163 const VECTOR2I end = GetEnd();
1164 VECTOR2I dimension( end - start );
1165
1166 m_measuredValue = KiROUND( dimension.EuclideanNorm() );
1167
1168 VECTOR2I extension;
1169
1170 if( m_height > 0 )
1171 extension = VECTOR2I( -dimension.y, dimension.x );
1172 else
1173 extension = VECTOR2I( dimension.y, -dimension.x );
1174
1175 // Add extension lines
1176 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
1177
1178 VECTOR2I extStart( start );
1179 extStart += extension.Resize( m_extensionOffset );
1180
1181 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1182
1183 extStart = VECTOR2I( end );
1184 extStart += extension.Resize( m_extensionOffset );
1185
1186 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1187
1188 // Add crossbar
1189 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
1190 m_crossBarStart = start + crossBarDistance;
1191 m_crossBarEnd = end + crossBarDistance;
1192
1193 // Update text after calculating crossbar position but before adding crossbar lines
1194 updateText();
1195
1196 // Now that we have the text updated, we can determine how to draw the crossbar.
1197 // First we need to create an appropriate bounding polygon to collide with
1198 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, - GetEffectiveTextPenWidth() );
1199
1200 SHAPE_POLY_SET polyBox;
1201 polyBox.NewOutline();
1202 polyBox.Append( textBox.GetOrigin() );
1203 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1204 polyBox.Append( textBox.GetEnd() );
1205 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1206 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1207
1208 // The ideal crossbar, if the text doesn't collide
1209 SEG crossbar( m_crossBarStart, m_crossBarEnd );
1210
1211 CollectKnockedOutSegments( polyBox, crossbar, m_shapes );
1212
1214 {
1215 drawAnArrow( m_crossBarStart, EDA_ANGLE( dimension ) + EDA_ANGLE( 180 ),
1217 drawAnArrow( m_crossBarEnd, EDA_ANGLE( dimension ),
1219 }
1220 else
1221 {
1222 drawAnArrow( m_crossBarStart, EDA_ANGLE( dimension ), 0 );
1223 drawAnArrow( m_crossBarEnd, EDA_ANGLE( dimension ) + EDA_ANGLE( 180 ), 0 );
1224 }
1225
1226 m_busy = false;
1227}
1228
1229
1231{
1232 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
1233
1235 {
1236 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
1237 EDA_ANGLE rotation;
1238
1239 if( crossbarCenter.x == 0 )
1240 rotation = ANGLE_90 * sign( -crossbarCenter.y );
1241 else if( crossbarCenter.x < 0 )
1242 rotation = -ANGLE_90;
1243 else
1244 rotation = ANGLE_90;
1245
1246 VECTOR2I textOffset = crossbarCenter;
1247 RotatePoint( textOffset, rotation );
1248 textOffset = crossbarCenter + textOffset.Resize( textOffsetDistance );
1249
1250 SetTextPos( m_crossBarStart + textOffset );
1251 }
1253 {
1254 SetTextPos( m_crossBarStart + crossbarCenter );
1255 }
1256
1257 if( m_keepTextAligned )
1258 {
1259 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( crossbarCenter );
1260 textAngle.Normalize();
1261
1262 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1263 textAngle -= ANGLE_180;
1264
1265 SetTextAngle( textAngle );
1266 }
1267
1269}
1270
1271
1272void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1273{
1274 PCB_DIMENSION_BASE::GetMsgPanelInfo( aFrame, aList );
1275
1276 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
1277 // in frame's units.
1278 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MM );
1279 unitsProvider.SetUserUnits( GetUnits() );
1280
1281 aList.emplace_back( _( "Height" ), unitsProvider.MessageTextFromValue( m_height ) );
1282}
1283
1284
1287{
1288 // To preserve look of old dimensions, initialize extension height based on default arrow length
1289 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
1291}
1292
1293
1295{
1296 return new PCB_DIM_ORTHOGONAL( *this );
1297}
1298
1299
1301{
1302 wxCHECK( aOther && aOther->Type() == PCB_DIM_ORTHOGONAL_T, /* void */ );
1303 *this = *static_cast<const PCB_DIM_ORTHOGONAL*>( aOther );
1304}
1305
1306void PCB_DIM_ORTHOGONAL::Serialize( google::protobuf::Any &aContainer ) const
1307{
1308 using namespace kiapi::common;
1309 kiapi::board::types::Dimension dimension;
1310
1311 PCB_DIMENSION_BASE::Serialize( aContainer );
1312 aContainer.UnpackTo( &dimension );
1313
1314 PackVector2( *dimension.mutable_orthogonal()->mutable_start(), GetStart() );
1315 PackVector2( *dimension.mutable_orthogonal()->mutable_end(), GetEnd() );
1316 dimension.mutable_orthogonal()->mutable_height()->set_value_nm( m_height );
1317 dimension.mutable_orthogonal()->mutable_extension_height()->set_value_nm( m_extensionHeight );
1318
1319 dimension.mutable_orthogonal()->set_alignment( m_orientation == DIR::VERTICAL
1320 ? types::AxisAlignment::AA_Y_AXIS
1321 : types::AxisAlignment::AA_X_AXIS );
1322 aContainer.PackFrom( dimension );
1323}
1324
1325
1326bool PCB_DIM_ORTHOGONAL::Deserialize( const google::protobuf::Any &aContainer )
1327{
1328 using namespace kiapi::common;
1329
1330 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1331 return false;
1332
1333 kiapi::board::types::Dimension dimension;
1334 aContainer.UnpackTo( &dimension );
1335
1336 if( !dimension.has_orthogonal() )
1337 return false;
1338
1339 SetStart( UnpackVector2( dimension.orthogonal().start() ) );
1340 SetEnd( UnpackVector2( dimension.orthogonal().end() ) );
1341 SetHeight( dimension.orthogonal().height().value_nm());
1342 SetExtensionHeight( dimension.orthogonal().extension_height().value_nm() );
1343 SetOrientation( dimension.orthogonal().alignment() == types::AxisAlignment::AA_Y_AXIS
1345 : DIR::HORIZONTAL );
1346
1347 Update();
1348
1349 return true;
1350}
1351
1352
1354{
1355 wxASSERT( aImage->Type() == Type() );
1356
1357 m_shapes.clear();
1358 static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
1359
1360 std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
1361 *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
1362
1363 Update();
1364}
1365
1366
1367void PCB_DIM_ORTHOGONAL::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
1368{
1369 // Only reverse the height if the height is aligned with the flip
1370 if( m_orientation == DIR::HORIZONTAL && aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
1371 m_height = -m_height;
1372 else if( m_orientation == DIR::VERTICAL && aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
1373 m_height = -m_height;
1374
1375 // Call this last, as we need the Update()
1376 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
1377}
1378
1379
1384
1385
1387{
1388 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1389 return;
1390
1391 m_busy = true;
1392 m_shapes.clear();
1393
1394 const VECTOR2I start = GetStart();
1395 const VECTOR2I end = GetEnd();
1396
1397 int measurement = ( m_orientation == DIR::HORIZONTAL ? end.x - start.x : end.y - start.y );
1399
1400 VECTOR2I extension;
1401
1403 extension = VECTOR2I( 0, m_height );
1404 else
1405 extension = VECTOR2I( m_height, 0 );
1406
1407 // Add first extension line
1408 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
1409
1410 VECTOR2I extStart( start );
1411 extStart += extension.Resize( m_extensionOffset );
1412
1413 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1414
1415 // Add crossbar
1416 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
1417 m_crossBarStart = start + crossBarDistance;
1418
1421 else
1423
1424 // Add second extension line (end to crossbar end)
1426 extension = VECTOR2I( 0, end.y - m_crossBarEnd.y );
1427 else
1428 extension = VECTOR2I( end.x - m_crossBarEnd.x, 0 );
1429
1430 extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
1431
1432 extStart = VECTOR2I( m_crossBarEnd );
1433 extStart -= extension.Resize( m_extensionHeight );
1434
1435 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1436
1437 // Update text after calculating crossbar position but before adding crossbar lines
1438 updateText();
1439
1440 // Now that we have the text updated, we can determine how to draw the crossbar.
1441 // First we need to create an appropriate bounding polygon to collide with
1442 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() );
1443
1444 SHAPE_POLY_SET polyBox;
1445 polyBox.NewOutline();
1446 polyBox.Append( textBox.GetOrigin() );
1447 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1448 polyBox.Append( textBox.GetEnd() );
1449 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1450 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1451
1452 // The ideal crossbar, if the text doesn't collide
1453 SEG crossbar( m_crossBarStart, m_crossBarEnd );
1454
1455 CollectKnockedOutSegments( polyBox, crossbar, m_shapes );
1456
1457 EDA_ANGLE crossBarAngle( m_crossBarEnd - m_crossBarStart );
1458
1460 {
1461 // Arrows with fixed length.
1462 drawAnArrow( m_crossBarStart, crossBarAngle + EDA_ANGLE( 180 ),
1465 }
1466 else
1467 {
1468 drawAnArrow( m_crossBarStart, crossBarAngle, 0 );
1469 drawAnArrow( m_crossBarEnd, crossBarAngle + EDA_ANGLE( 180 ), 0 );
1470 }
1471
1472 m_busy = false;
1473}
1474
1475
1477{
1478 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
1479
1481 {
1482 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
1483
1484 VECTOR2I textOffset;
1485
1487 textOffset.y = -textOffsetDistance;
1488 else
1489 textOffset.x = -textOffsetDistance;
1490
1491 textOffset += crossbarCenter;
1492
1493 SetTextPos( m_crossBarStart + textOffset );
1494 }
1496 {
1497 SetTextPos( m_crossBarStart + crossbarCenter );
1498 }
1499
1500 if( m_keepTextAligned )
1501 {
1502 if( abs( crossbarCenter.x ) > abs( crossbarCenter.y ) )
1504 else
1506 }
1507
1509}
1510
1511
1512void PCB_DIM_ORTHOGONAL::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1513{
1514 EDA_ANGLE angle( aAngle );
1515
1516 // restrict angle to -179.9 to 180.0 degrees
1517 angle.Normalize180();
1518
1519 // adjust orientation and height to new angle
1520 // we can only handle the cases of -90, 0, 90, 180 degrees exactly;
1521 // in the other cases we will use the nearest 90 degree angle to
1522 // choose at least an approximate axis for the target orientation
1523 // In case of exactly 45 or 135 degrees, we will round towards zero for consistency
1524 if( angle > ANGLE_45 && angle <= ANGLE_135 )
1525 {
1526 // about 90 degree
1528 {
1530 }
1531 else
1532 {
1534 m_height = -m_height;
1535 }
1536 }
1537 else if( angle < -ANGLE_45 && angle >= -ANGLE_135 )
1538 {
1539 // about -90 degree
1541 {
1543 m_height = -m_height;
1544 }
1545 else
1546 {
1548 }
1549 }
1550 else if( angle > ANGLE_135 || angle < -ANGLE_135 )
1551 {
1552 // about 180 degree
1553 m_height = -m_height;
1554 }
1555
1556 // this will update m_crossBarStart and m_crossbarEnd
1557 PCB_DIMENSION_BASE::Rotate( aRotCentre, angle );
1558}
1559
1560
1571
1572
1574{
1575 wxCHECK( aOther && aOther->Type() == PCB_DIM_LEADER_T, /* void */ );
1576 *this = *static_cast<const PCB_DIM_LEADER*>( aOther );
1577}
1578
1579void PCB_DIM_LEADER::Serialize( google::protobuf::Any &aContainer ) const
1580{
1581 using namespace kiapi::common;
1582 kiapi::board::types::Dimension dimension;
1583
1584 PCB_DIMENSION_BASE::Serialize( aContainer );
1585 aContainer.UnpackTo( &dimension );
1586
1587 PackVector2( *dimension.mutable_leader()->mutable_start(), GetStart() );
1588 PackVector2( *dimension.mutable_leader()->mutable_end(), GetEnd() );
1589 dimension.mutable_leader()->set_border_style(
1591 m_textBorder ) );
1592
1593 aContainer.PackFrom( dimension );
1594}
1595
1596
1597bool PCB_DIM_LEADER::Deserialize( const google::protobuf::Any &aContainer )
1598{
1599 using namespace kiapi::common;
1600
1601 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1602 return false;
1603
1604 kiapi::board::types::Dimension dimension;
1605 aContainer.UnpackTo( &dimension );
1606
1607 if( !dimension.has_leader() )
1608 return false;
1609
1610 SetStart( UnpackVector2( dimension.leader().start() ) );
1611 SetEnd( UnpackVector2( dimension.leader().end() ) );
1612 SetTextBorder( FromProtoEnum<DIM_TEXT_BORDER>( dimension.leader().border_style() ) );
1613
1614 Update();
1615
1616 return true;
1617}
1618
1619
1621{
1622 return new PCB_DIM_LEADER( *this );
1623}
1624
1625
1627{
1628 wxASSERT( aImage->Type() == Type() );
1629
1630 m_shapes.clear();
1631 static_cast<PCB_DIM_LEADER*>( aImage )->m_shapes.clear();
1632
1633 std::swap( *static_cast<PCB_DIM_LEADER*>( this ), *static_cast<PCB_DIM_LEADER*>( aImage ) );
1634
1635 Update();
1636}
1637
1638
1643
1644
1646{
1647 // Our geometry is dependent on the size of the text, so just update the whole shebang
1649}
1650
1651
1653{
1654 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1655 return;
1656
1657 m_busy = true;
1658
1659 m_shapes.clear();
1660
1662
1663 // Now that we have the text updated, we can determine how to draw the second line
1664 // First we need to create an appropriate bounding polygon to collide with
1665 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() * 2 );
1666
1667 SHAPE_POLY_SET polyBox;
1668 polyBox.NewOutline();
1669 polyBox.Append( textBox.GetOrigin() );
1670 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1671 polyBox.Append( textBox.GetEnd() );
1672 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1673 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1674
1675 const VECTOR2I boardStart = GetStart();
1676 const VECTOR2I boardEnd = GetEnd();
1677
1678 VECTOR2I firstLine( boardEnd - boardStart );
1679 VECTOR2I start( boardStart );
1680 start += firstLine.Resize( m_extensionOffset );
1681
1682 SEG arrowSeg( boardStart, boardEnd );
1683 SEG textSeg( boardEnd, GetTextPos() );
1684 OPT_VECTOR2I arrowSegEnd;
1685 OPT_VECTOR2I textSegEnd;
1686
1688 {
1689 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1690 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1691 CIRCLE circle( textBox.GetCenter(), radius );
1692
1693 arrowSegEnd = segCircleIntersection( circle, arrowSeg );
1694 textSegEnd = segCircleIntersection( circle, textSeg );
1695 }
1696 else
1697 {
1698 arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1699 textSegEnd = segPolyIntersection( polyBox, textSeg );
1700 }
1701
1702 if( !arrowSegEnd )
1703 arrowSegEnd = boardEnd;
1704
1705 m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
1706
1707 drawAnArrow( start, EDA_ANGLE( firstLine ), 0 );
1708
1709 if( !GetText().IsEmpty() )
1710 {
1711 switch( m_textBorder )
1712 {
1714 {
1715 for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
1716 m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
1717
1718 break;
1719 }
1720
1722 {
1723 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1724 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1725 m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
1726
1727 break;
1728 }
1729
1730 default:
1731 break;
1732 }
1733 }
1734
1735 if( textSegEnd && *arrowSegEnd == boardEnd )
1736 m_shapes.emplace_back( new SHAPE_SEGMENT( boardEnd, *textSegEnd ) );
1737
1738 m_busy = false;
1739}
1740
1741
1742void PCB_DIM_LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1743{
1744 // Don't use GetShownText(); we want to see the variable references here
1745 aList.emplace_back( _( "Leader" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
1746
1747 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
1748
1749 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
1750 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
1751 aFrame->MessageTextFromValue( startCoord.x ),
1752 aFrame->MessageTextFromValue( startCoord.y ) );
1753
1754 aList.emplace_back( start, wxEmptyString );
1755
1756 aList.emplace_back( _( "Layer" ), GetLayerName() );
1757}
1758
1759
1769
1771{
1772 wxCHECK( aOther && aOther->Type() == PCB_DIM_RADIAL_T, /* void */ );
1773 *this = *static_cast<const PCB_DIM_RADIAL*>( aOther );
1774}
1775
1776void PCB_DIM_RADIAL::Serialize( google::protobuf::Any &aContainer ) const
1777{
1778 using namespace kiapi::common;
1779 kiapi::board::types::Dimension dimension;
1780
1781 PCB_DIMENSION_BASE::Serialize( aContainer );
1782 aContainer.UnpackTo( &dimension );
1783
1784 PackVector2( *dimension.mutable_radial()->mutable_center(), GetStart() );
1785 PackVector2( *dimension.mutable_radial()->mutable_radius_point(), GetEnd() );
1786 dimension.mutable_radial()->mutable_leader_length()->set_value_nm( m_leaderLength );
1787
1788 aContainer.PackFrom( dimension );
1789}
1790
1791
1792bool PCB_DIM_RADIAL::Deserialize( const google::protobuf::Any &aContainer )
1793{
1794 using namespace kiapi::common;
1795
1796 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1797 return false;
1798
1799 kiapi::board::types::Dimension dimension;
1800 aContainer.UnpackTo( &dimension );
1801
1802 if( !dimension.has_radial() )
1803 return false;
1804
1805 SetStart( UnpackVector2( dimension.radial().center() ) );
1806 SetEnd( UnpackVector2( dimension.radial().radius_point() ) );
1807 SetLeaderLength( dimension.radial().leader_length().value_nm() );
1808
1809 Update();
1810
1811 return true;
1812}
1813
1814
1816{
1817 return new PCB_DIM_RADIAL( *this );
1818}
1819
1820
1822{
1823 wxASSERT( aImage->Type() == Type() );
1824
1825 m_shapes.clear();
1826 static_cast<PCB_DIM_RADIAL*>( aImage )->m_shapes.clear();
1827
1828 std::swap( *static_cast<PCB_DIM_RADIAL*>( this ), *static_cast<PCB_DIM_RADIAL*>( aImage ) );
1829
1830 Update();
1831}
1832
1833
1838
1839
1841{
1842 const VECTOR2I end = GetEnd();
1843 VECTOR2I radial( end - GetStart() );
1844
1845 return end + radial.Resize( m_leaderLength );
1846}
1847
1848
1850{
1851 if( m_keepTextAligned )
1852 {
1853 VECTOR2I textLine( GetTextPos() - GetKnee() );
1854 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( textLine );
1855
1856 textAngle.Normalize();
1857
1858 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1859 textAngle -= ANGLE_180;
1860
1861 // Round to nearest degree
1862 textAngle = EDA_ANGLE( KiROUND( textAngle.AsDegrees() ), DEGREES_T );
1863
1864 SetTextAngle( textAngle );
1865 }
1866
1868}
1869
1870
1872{
1873 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1874 return;
1875
1876 m_busy = true;
1877
1878 m_shapes.clear();
1879
1880 const VECTOR2I boardStart = GetStart();
1881 const VECTOR2I boardEnd = GetEnd();
1882
1883 VECTOR2I center( boardStart );
1884 VECTOR2I centerArm( 0, m_arrowLength );
1885
1886 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1887
1888 RotatePoint( centerArm, -ANGLE_90 );
1889
1890 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1891
1892 VECTOR2I radius( boardEnd - boardStart );
1893
1894 m_measuredValue = KiROUND( radius.EuclideanNorm() );
1895
1896 updateText();
1897
1898 // Now that we have the text updated, we can determine how to draw the second line
1899 // First we need to create an appropriate bounding polygon to collide with
1900 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() );
1901
1902 SHAPE_POLY_SET polyBox;
1903 polyBox.NewOutline();
1904 polyBox.Append( textBox.GetOrigin() );
1905 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1906 polyBox.Append( textBox.GetEnd() );
1907 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1908 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1909
1910 VECTOR2I radial( boardEnd - boardStart );
1911 radial = radial.Resize( m_leaderLength );
1912
1913 SEG arrowSeg( boardEnd, boardEnd + radial );
1914 SEG textSeg( arrowSeg.B, GetTextPos() );
1915
1916 CollectKnockedOutSegments( polyBox, arrowSeg, m_shapes );
1917 CollectKnockedOutSegments( polyBox, textSeg, m_shapes );
1918
1919 drawAnArrow( boardEnd, EDA_ANGLE( radial ), 0 );
1920
1921 m_busy = false;
1922}
1923
1924
1931
1933{
1934 wxCHECK( aOther && aOther->Type() == PCB_DIM_CENTER_T, /* void */ );
1935 *this = *static_cast<const PCB_DIM_CENTER*>( aOther );
1936}
1937
1938void PCB_DIM_CENTER::Serialize( google::protobuf::Any &aContainer ) const
1939{
1940 using namespace kiapi::common;
1941 kiapi::board::types::Dimension dimension;
1942
1943 PCB_DIMENSION_BASE::Serialize( aContainer );
1944 aContainer.UnpackTo( &dimension );
1945
1946 PackVector2( *dimension.mutable_center()->mutable_center(), GetStart() );
1947 PackVector2( *dimension.mutable_center()->mutable_end(), GetEnd() );
1948
1949 aContainer.PackFrom( dimension );
1950}
1951
1952
1953bool PCB_DIM_CENTER::Deserialize( const google::protobuf::Any &aContainer )
1954{
1955 using namespace kiapi::common;
1956
1957 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1958 return false;
1959
1960 kiapi::board::types::Dimension dimension;
1961 aContainer.UnpackTo( &dimension );
1962
1963 if( !dimension.has_center() )
1964 return false;
1965
1966 SetStart( UnpackVector2( dimension.center().center() ) );
1967 SetEnd( UnpackVector2( dimension.center().end() ) );
1968
1969 Update();
1970
1971 return true;
1972}
1973
1974
1976{
1977 return new PCB_DIM_CENTER( *this );
1978}
1979
1980
1982{
1983 wxASSERT( aImage->Type() == Type() );
1984
1985 std::swap( *static_cast<PCB_DIM_CENTER*>( this ), *static_cast<PCB_DIM_CENTER*>( aImage ) );
1986}
1987
1988
1993
1994
1996{
1997 BOX2I bBox;
1998 int xmin, xmax, ymin, ymax;
1999
2000 const VECTOR2I start = GetStart();
2001 xmin = start.x;
2002 xmax = start.x;
2003 ymin = start.y;
2004 ymax = start.y;
2005
2006 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
2007 {
2008 BOX2I shapeBox = shape->BBox();
2009 shapeBox.Inflate( m_lineThickness / 2 );
2010
2011 xmin = std::min( xmin, shapeBox.GetOrigin().x );
2012 xmax = std::max( xmax, shapeBox.GetEnd().x );
2013 ymin = std::min( ymin, shapeBox.GetOrigin().y );
2014 ymax = std::max( ymax, shapeBox.GetEnd().y );
2015 }
2016
2017 bBox.SetX( xmin );
2018 bBox.SetY( ymin );
2019 bBox.SetWidth( xmax - xmin + 1 );
2020 bBox.SetHeight( ymax - ymin + 1 );
2021
2022 bBox.Normalize();
2023
2024 return bBox;
2025}
2026
2027
2029{
2030 return GetBoundingBox();
2031}
2032
2033
2035{
2036 // Even if PCB_DIM_CENTER has no text, we still need to update its text position
2037 // so GetTextPos() users get a valid value. Required at least for lasso hit-testing.
2038 SetTextPos( GetStart() );
2039
2041}
2042
2043
2045{
2046 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
2047 return;
2048
2049 m_busy = true;
2050
2051 m_shapes.clear();
2052
2053 const VECTOR2I boardStart = GetStart();
2054 const VECTOR2I boardEnd = GetEnd();
2055 VECTOR2I center( boardStart );
2056 VECTOR2I arm( boardEnd - boardStart );
2057
2058 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
2059
2060 RotatePoint( arm, -ANGLE_90 );
2061
2062 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
2063
2064 updateText();
2065
2066 m_busy = false;
2067}
2068
2069
2070static struct DIMENSION_DESC
2071{
2073 {
2075 .Map( DIM_PRECISION::X, _HKI( "0" ) )
2076 .Map( DIM_PRECISION::X_X, _HKI( "0.0" ) )
2077 .Map( DIM_PRECISION::X_XX, _HKI( "0.00" ) )
2078 .Map( DIM_PRECISION::X_XXX, _HKI( "0.000" ) )
2079 .Map( DIM_PRECISION::X_XXXX, _HKI( "0.0000" ) )
2080 .Map( DIM_PRECISION::X_XXXXX, _HKI( "0.00000" ) )
2081 .Map( DIM_PRECISION::V_VV, _HKI( "0.00 in / 0 mils / 0.0 mm" ) )
2082 .Map( DIM_PRECISION::V_VVV, _HKI( "0.000 / 0 / 0.00" ) )
2083 .Map( DIM_PRECISION::V_VVVV, _HKI( "0.0000 / 0.0 / 0.000" ) )
2084 .Map( DIM_PRECISION::V_VVVVV, _HKI( "0.00000 / 0.00 / 0.0000" ) );
2085
2087 .Map( DIM_UNITS_FORMAT::NO_SUFFIX, _HKI( "1234.0" ) )
2088 .Map( DIM_UNITS_FORMAT::BARE_SUFFIX, _HKI( "1234.0 mm" ) )
2089 .Map( DIM_UNITS_FORMAT::PAREN_SUFFIX, _HKI( "1234.0 (mm)" ) );
2090
2092 .Map( DIM_UNITS_MODE::INCH, _HKI( "Inches" ) )
2093 .Map( DIM_UNITS_MODE::MILS, _HKI( "Mils" ) )
2094 .Map( DIM_UNITS_MODE::MM, _HKI( "Millimeters" ) )
2095 .Map( DIM_UNITS_MODE::AUTOMATIC, _HKI( "Automatic" ) );
2096
2098 .Map( DIM_ARROW_DIRECTION::INWARD, _HKI( "Inward" ) )
2099 .Map( DIM_ARROW_DIRECTION::OUTWARD, _HKI( "Outward" ) );
2100
2102 .Map( DIM_VALUE_MODE::DRIVEN, _HKI( "Driven" ) )
2103 .Map( DIM_VALUE_MODE::DRIVING, _HKI( "Driving" ) )
2104 .Map( DIM_VALUE_MODE::ARBITRARY, _HKI( "Arbitrary" ) );
2105
2114
2115 propMgr.Mask( TYPE_HASH( PCB_DIMENSION_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
2116
2117 const wxString groupDimension = _HKI( "Dimension Properties" );
2118
2119 auto isLeader =
2120 []( INSPECTABLE* aItem ) -> bool
2121 {
2122 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) != nullptr;
2123 };
2124
2125 auto isNotLeader =
2126 []( INSPECTABLE* aItem ) -> bool
2127 {
2128 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) == nullptr;
2129 };
2130
2131 auto isMultiArrowDirection =
2132 []( INSPECTABLE* aItem ) -> bool
2133 {
2134 return dynamic_cast<PCB_DIM_ALIGNED*>( aItem ) != nullptr;
2135 };
2136
2139 groupDimension )
2140 .SetAvailableFunc( isNotLeader );
2143 groupDimension )
2144 .SetAvailableFunc( isNotLeader );
2145
2146 auto hasValueMode =
2147 []( INSPECTABLE* aItem ) -> bool
2148 {
2149 return DimensionHasValueMode( dynamic_cast<PCB_DIMENSION_BASE*>( aItem ) );
2150 };
2151
2152 // Value bearing dims use Value row instead while leaders keep Text below
2153 // Override Text left for centre mark only
2154 auto usesOverrideText =
2155 [isLeader, hasValueMode]( INSPECTABLE* aItem ) -> bool
2156 {
2157 return aItem && !isLeader( aItem ) && !hasValueMode( aItem );
2158 };
2159
2160 // Driving needs both endpoints bound to movable geometry
2161 // Dropdown always offers it so gate the transition here
2162 auto valueModeValidator =
2163 []( const wxAny&& aValue, EDA_ITEM* aItem ) -> VALIDATOR_RESULT
2164 {
2165 PCB_DIMENSION_BASE* dim = dynamic_cast<PCB_DIMENSION_BASE*>( aItem );
2166
2167 if( !dim )
2168 return std::nullopt;
2169
2170 int mode = 0;
2171
2172 if( aValue.CheckType<DIM_VALUE_MODE>() )
2173 mode = static_cast<int>( aValue.As<DIM_VALUE_MODE>() );
2174 else if( !aValue.GetAs( &mode ) )
2175 return std::nullopt;
2176
2177 if( mode == static_cast<int>( DIM_VALUE_MODE::DRIVING )
2178 && !DimensionCanDrive( dim->GetBoard(), dim ) )
2179 {
2180 return std::make_unique<VALIDATION_ERROR_MSG>(
2181 _( "Driving requires both dimension endpoints bound to objects" ) );
2182 }
2183
2184 return std::nullopt;
2185 };
2186
2187 // Driving edits length constraint which must stay positive
2188 // Catches zero and negative and stale exprs parsing to zero
2189 auto drivingValueValidator =
2190 []( const wxAny&& aValue, EDA_ITEM* aItem ) -> VALIDATOR_RESULT
2191 {
2192 PCB_DIMENSION_BASE* dim = dynamic_cast<PCB_DIMENSION_BASE*>( aItem );
2193
2194 if( !dim || dim->GetValueMode() != DIM_VALUE_MODE::DRIVING )
2195 return std::nullopt;
2196
2197 wxString text;
2198
2199 if( !aValue.GetAs( &text ) )
2200 return std::nullopt;
2201
2203
2204 if( !( iu > 0.0 ) )
2205 {
2206 return std::make_unique<VALIDATION_ERROR_MSG>(
2207 _( "Enter a positive length for a driving dimension" ) );
2208 }
2209
2210 return std::nullopt;
2211 };
2212
2213 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, wxString>( _HKI( "Override Text" ),
2215 groupDimension )
2216 .SetAvailableFunc( usesOverrideText );
2217
2220 groupDimension )
2221 .SetAvailableFunc( hasValueMode )
2222 .SetValidator( std::move( valueModeValidator ) );
2223
2226 groupDimension )
2227 .SetAvailableFunc( hasValueMode )
2229 []( INSPECTABLE* aItem ) -> bool
2230 {
2231 // Driven mirrors measured geometry so grey it out since edit would not stick
2232 PCB_DIMENSION_BASE* dim = dynamic_cast<PCB_DIMENSION_BASE*>( aItem );
2233 return dim && dim->GetValueMode() != DIM_VALUE_MODE::DRIVEN;
2234 } )
2235 .SetValidator( std::move( drivingValueValidator ) );
2236
2239 groupDimension )
2240 .SetAvailableFunc( isLeader );
2241
2244 groupDimension )
2245 .SetAvailableFunc( isNotLeader ).SetIsCopyable();
2248 groupDimension )
2249 .SetAvailableFunc( isNotLeader ).SetIsCopyable();
2252 groupDimension )
2253 .SetAvailableFunc( isNotLeader ).SetIsCopyable();
2254 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Suppress Trailing Zeroes" ),
2256 groupDimension )
2257 .SetAvailableFunc( isNotLeader ).SetIsCopyable();
2258
2261 groupDimension )
2262 .SetAvailableFunc( isMultiArrowDirection ).SetIsCopyable();
2263
2264 const wxString groupText = _HKI( "Text Properties" );
2265
2266 const auto isTextOrientationWriteable =
2267 []( INSPECTABLE* aItem ) -> bool
2268 {
2269 return !static_cast<PCB_DIMENSION_BASE*>( aItem )->GetKeepTextAligned();
2270 };
2271
2272 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Keep Aligned with Dimension" ),
2275 groupText );
2276
2277 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, double>( _HKI( "Orientation" ),
2281 groupText )
2282 .SetWriteableFunc( isTextOrientationWriteable );
2283 }
2285
2291
2292
2294{
2296 {
2307
2308 const wxString groupDimension = _HKI( "Dimension Properties" );
2309
2310 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Crossbar Height" ),
2313 groupDimension );
2314 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Extension Line Overshoot" ),
2317 groupDimension );
2318
2320 _HKI( "Text" ),
2321 []( INSPECTABLE* aItem ) { return false; } );
2323 _HKI( "Vertical Justification" ),
2324 []( INSPECTABLE* aItem ) { return false; } );
2326 _HKI( "Hyperlink" ),
2327 []( INSPECTABLE* aItem ) { return false; } );
2329 _HKI( "Knockout" ),
2330 []( INSPECTABLE* aItem ) { return false; } );
2331 }
2333
2334
2336{
2338 {
2351
2353 _HKI( "Text" ),
2354 []( INSPECTABLE* aItem ) { return false; } );
2356 _HKI( "Vertical Justification" ),
2357 []( INSPECTABLE* aItem ) { return false; } );
2359 _HKI( "Hyperlink" ),
2360 []( INSPECTABLE* aItem ) { return false; } );
2362 _HKI( "Knockout" ),
2363 []( INSPECTABLE* aItem ) { return false; } );
2364 }
2366
2367
2369{
2371 {
2382
2383 const wxString groupDimension = _HKI( "Dimension Properties" );
2384
2385 propMgr.AddProperty( new PROPERTY<PCB_DIM_RADIAL, int>( _HKI( "Leader Length" ),
2388 groupDimension );
2389
2391 _HKI( "Text" ),
2392 []( INSPECTABLE* aItem ) { return false; } );
2394 _HKI( "Vertical Justification" ),
2395 []( INSPECTABLE* aItem ) { return false; } );
2397 _HKI( "Hyperlink" ),
2398 []( INSPECTABLE* aItem ) { return false; } );
2400 _HKI( "Knockout" ),
2401 []( INSPECTABLE* aItem ) { return false; } );
2402 }
2404
2405
2407{
2409 {
2411 .Map( DIM_TEXT_BORDER::NONE, _HKI( "None" ) )
2412 .Map( DIM_TEXT_BORDER::RECTANGLE, _HKI( "Rectangle" ) )
2413 .Map( DIM_TEXT_BORDER::CIRCLE, _HKI( "Circle" ) );
2414
2425
2426 const wxString groupDimension = _HKI( "Dimension Properties" );
2427
2430 groupDimension );
2431
2433 _HKI( "Text" ),
2434 []( INSPECTABLE* aItem ) { return false; } );
2436 _HKI( "Vertical Justification" ),
2437 []( INSPECTABLE* aItem ) { return false; } );
2439 _HKI( "Hyperlink" ),
2440 []( INSPECTABLE* aItem ) { return false; } );
2442 _HKI( "Knockout" ),
2443 []( INSPECTABLE* aItem ) { return false; } );
2444 }
2446
2448
2449
2451{
2453 {
2464
2465
2467 _HKI( "Text" ),
2468 []( INSPECTABLE* aItem ) { return false; } );
2470 _HKI( "Vertical Justification" ),
2471 []( INSPECTABLE* aItem ) { return false; } );
2473 _HKI( "Hyperlink" ),
2474 []( INSPECTABLE* aItem ) { return false; } );
2476 _HKI( "Knockout" ),
2477 []( INSPECTABLE* aItem ) { return false; } );
2478 }
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
BITMAPS
A list of all bitmap identifiers.
@ add_radial_dimension
@ add_aligned_dimension
@ add_center_dimension
@ add_orthogonal_dimension
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
Container for design settings for a BOARD object.
DIM_PRECISION m_DimensionPrecision
Number of digits after the decimal.
DIM_UNITS_FORMAT m_DimensionUnitsFormat
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
DIM_TEXT_POSITION m_DimensionTextPosition
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:86
friend class BOARD
Definition board_item.h:578
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
Definition board_item.h:417
PCB_LAYER_ID m_layer
Definition board_item.h:571
bool IsLocked() const override
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:374
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
bool IsSideSpecific() const
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
EDA_UNITS GetUserUnits()
Definition board.h:1022
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr void SetHeight(size_type val)
Definition box2.h:289
constexpr const Vec GetEnd() const
Definition box2.h:209
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:143
constexpr coord_type GetY() const
Definition box2.h:205
constexpr size_type GetWidth() const
Definition box2.h:211
constexpr coord_type GetX() const
Definition box2.h:204
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:653
constexpr const Vec GetCenter() const
Definition box2.h:227
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
constexpr void SetWidth(size_type val)
Definition box2.h:284
constexpr void SetX(coord_type val)
Definition box2.h:274
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr void SetY(coord_type val)
Definition box2.h:279
constexpr coord_type GetRight() const
Definition box2.h:214
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
constexpr coord_type GetBottom() const
Definition box2.h:219
Represent basic circle geometry with utility geometry functions.
Definition circle.h:33
std::vector< VECTOR2I > Intersect(const CIRCLE &aCircle) const
Compute the intersection points between this circle and aCircle.
Definition circle.cpp:243
bool Contains(const VECTOR2I &aP) const
Return true if aP is on the circumference of this circle.
Definition circle.cpp:188
EDA_ANGLE Normalize()
Definition eda_angle.h:229
double AsDegrees() const
Definition eda_angle.h:116
EDA_ANGLE Normalize180()
Definition eda_angle.h:268
ORIGIN_TRANSFORMS & GetOriginTransforms() override
Return a reference to the default ORIGIN_TRANSFORMS object.
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
const KIID m_Uuid
Definition eda_item.h:597
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:607
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition eda_text.cpp:165
virtual VECTOR2I GetTextPos() const
Definition eda_text.h:313
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:539
virtual int GetTextHeight() const
Definition eda_text.h:307
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition eda_text.cpp:195
KIFONT::FONT * GetFont() const
Definition eda_text.h:286
void SetMirrored(bool isMirrored)
Definition eda_text.cpp:349
BOX2I GetTextBox(const RENDER_SETTINGS *aSettings, int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition eda_text.cpp:737
virtual int GetTextWidth() const
Definition eda_text.h:304
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:658
double Similarity(const EDA_TEXT &aOther) const
virtual void ClearRenderCache()
Definition eda_text.cpp:652
bool IsMirrored() const
Definition eda_text.h:229
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:422
std::shared_ptr< SHAPE_COMPOUND > GetEffectiveTextShape(bool aTriangulate=true, const BOX2I &aBBox=BOX2I(), const EDA_ANGLE &aAngle=ANGLE_0) const
build a list of segments (SHAPE_SEGMENT) to describe a text shape.
void SetTextAngleDegrees(double aOrientation)
Definition eda_text.h:181
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:231
bool operator==(const EDA_TEXT &aRhs) const
Definition eda_text.h:438
static ENUM_MAP< T > & Instance()
Definition property.h:770
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
Contains methods for drawing PCB-specific items.
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition pcb_painter.h:84
const std::unordered_set< KIID > & GetConstrainedItems() const
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:176
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:181
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
bool IsLayerVisibleCached(int aLayer) const
Definition view.h:439
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition view.h:225
Definition kiid.h:46
A class to perform either relative or absolute display origin transforms for a single axis of a point...
T ToDisplayAbs(const T &aValue) const
A geometric constraint between board items (issue #2329).
std::optional< double > GetValue() const
Abstract dimension API.
EDA_UNITS GetUnits() const
bool m_autoUnits
If true, follow the currently selected UI units.
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
void Update()
Update the dimension's cached text and geometry.
void ChangeSuffix(const wxString &aSuffix)
void OnFootprintRescaled(double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I &aAnchor, const EDA_ANGLE &aParentRotate) override
Apply a parent footprint scale to this item.
wxString GetOverrideText() const
wxString GetSuffix() const
std::vector< std::shared_ptr< SHAPE > > m_shapes
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void ClearRenderCache() override
int m_lineThickness
Thickness used for all graphics in the dimension.
virtual void SetEnd(const VECTOR2I &aPoint)
void Move(const VECTOR2I &offset) override
Move this object.
void SetUnitsFormat(const DIM_UNITS_FORMAT aFormat)
bool m_suppressZeroes
Suppress trailing zeroes.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
void SetUnits(EDA_UNITS aUnits)
VECTOR2I m_start
Start, FP-relative when in a footprint, board absolute otherwise.
DIM_PRECISION m_precision
Number of digits to display after decimal.
virtual void SetStart(const VECTOR2I &aPoint)
void addShape(const ShapeType &aShape)
void SetPrefix(const wxString &aPrefix)
wxString m_suffix
String appended to the value.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void ChangeOverrideText(const wxString &aValue)
void SetExtensionOffset(int aOffset)
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
void SetSuppressZeroes(bool aSuppress)
bool m_inClearRenderCache
re-entrancy guard
PCB_DIMENSION_BASE(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIMENSION_T)
int m_extensionOffset
Distance from feature points to extension line start.
void ChangeArrowDirection(const DIM_ARROW_DIRECTION &aDirection)
bool GetKeepTextAligned() const
void OnFootprintTransformed() override
Hook for items inside a footprint to refresh after the FP transform changes (translate,...
void ChangeTextAngleDegrees(double aDegrees)
bool m_keepTextAligned
Calculate text orientation to match dimension.
DIM_PRECISION GetPrecision() const
wxString GetPrefix() const
void SetOverrideTextEnabled(bool aOverride)
void SetSuffix(const wxString &aSuffix)
bool operator==(const PCB_DIMENSION_BASE &aOther) const
void ChangeValueMode(DIM_VALUE_MODE aMode)
Property panel setter for value mode override text flag lives on dimension length constraint is board...
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
DIM_UNITS_MODE GetUnitsMode() const
void drawAnArrow(VECTOR2I aStartPoint, EDA_ANGLE anAngle, int aLength)
Draws an arrow and updates the shape container.
void SetTextPositionMode(DIM_TEXT_POSITION aMode)
virtual void updateText()
Update the text field value from the current geometry (called by updateGeometry normally).
bool HitTest(const VECTOR2I &aPosition, int aAccuracy) const override
Test if aPosition is inside or on the boundary of this item.
EDA_UNITS m_units
0 = inches, 1 = mm
int m_measuredValue
value of PCB dimensions
DIM_VALUE_MODE GetValueMode() const
Value mode from board state via DimensionValueMode.
DIM_UNITS_FORMAT GetUnitsFormat() const
void SetLineThickness(int aWidth)
void SetArrowLength(int aLength)
DIM_ARROW_DIRECTION GetArrowDirection() const
wxString m_valueString
Displayed value when m_overrideValue = true.
virtual VECTOR2I GetEnd() const
void ChangePrecision(DIM_PRECISION aPrecision)
void SetPrecision(DIM_PRECISION aPrecision)
bool m_overrideTextEnabled
Manually specify the displayed measurement value.
DIM_UNITS_FORMAT m_unitsFormat
How to render the units suffix.
int GetMeasuredValue() const
bool GetSuppressZeroes() const
void SetArrowDirection(const DIM_ARROW_DIRECTION &aDirection)
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
DIM_TEXT_POSITION m_textPosition
How to position the text.
void SetOverrideText(const wxString &aValue)
wxString GetValueText() const
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
void ChangePrefix(const wxString &aPrefix)
wxString m_prefix
String prepended to the value.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
virtual VECTOR2I GetStart() const
The dimension's origin is the first feature point for the dimension.
DIM_ARROW_DIRECTION m_arrowDirection
direction of dimension arrow.
void ChangeKeepTextAligned(bool aKeepAligned)
void ChangeUnitsFormat(const DIM_UNITS_FORMAT aFormat)
wxString GetValueFieldText() const
Mode aware value for panel driving shows constraint length arbitrary shows override text otherwise sh...
void ChangeSuppressZeroes(bool aSuppress)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
void ChangeValueFieldText(const wxString &aText)
Property panel setter for value arbitrary text owned by dimension driving edits board level constrain...
double GetTextAngleDegreesProp() const
bool GetOverrideTextEnabled() const
void SetUnitsMode(DIM_UNITS_MODE aMode)
int m_arrowLength
Length of arrow shapes.
virtual void Mirror(const VECTOR2I &axis_pos, FLIP_DIRECTION aFlipDirection) override
Mirror the dimension relative to a given horizontal axis.
VECTOR2I m_end
End, FP-relative when in a footprint, board absolute otherwise.
void ChangeUnitsMode(DIM_UNITS_MODE aMode)
void SetKeepTextAligned(bool aKeepAligned)
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
VECTOR2I GetPosition() const override
For better understanding of the points that make a dimension:
int GetHeight() const
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
int m_height
Perpendicular distance from features to crossbar.
void ChangeExtensionHeight(int aHeight)
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
void SetExtensionHeight(int aHeight)
VECTOR2I m_crossBarStart
Crossbar start control point.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void Mirror(const VECTOR2I &axis_pos, FLIP_DIRECTION aFlipDirection) override
Mirror the dimension relative to a given horizontal axis.
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
virtual void swapData(BOARD_ITEM *aImage) override
int m_extensionHeight
Length of extension lines past the crossbar.
void CopyFrom(const BOARD_ITEM *aOther) override
void SetHeight(int aHeight)
Set the distance from the feature points to the crossbar line.
VECTOR2I m_crossBarEnd
Crossbar end control point.
PCB_DIM_ALIGNED(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIM_ALIGNED_T)
void ChangeHeight(int aHeight)
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
int GetExtensionHeight() const
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Mark the center of a circle or arc with a cross shape.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void CopyFrom(const BOARD_ITEM *aOther) override
virtual void swapData(BOARD_ITEM *aImage) override
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
PCB_DIM_CENTER(BOARD_ITEM *aParent)
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
A leader is a dimension-like object pointing to a specific point.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
DIM_TEXT_BORDER m_textBorder
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
DIM_TEXT_BORDER GetTextBorder() const
void CopyFrom(const BOARD_ITEM *aOther) override
virtual void swapData(BOARD_ITEM *aImage) override
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
void SetTextBorder(DIM_TEXT_BORDER aBorder)
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
PCB_DIM_LEADER(BOARD_ITEM *aParent)
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void ChangeTextBorder(DIM_TEXT_BORDER aBorder)
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
void swapData(BOARD_ITEM *aImage) override
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
void CopyFrom(const BOARD_ITEM *aOther) override
void SetOrientation(DIR aOrientation)
Set the orientation of the dimension line (so, perpendicular to the feature lines).
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
DIR m_orientation
What axis to lock the dimension line to.
void Mirror(const VECTOR2I &axis_pos, FLIP_DIRECTION aFlipDirection) override
Mirror the dimension relative to a given horizontal axis.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
PCB_DIM_ORTHOGONAL(BOARD_ITEM *aParent)
A radial dimension indicates either the radius or diameter of an arc or circle.
int GetLeaderLength() const
PCB_DIM_RADIAL(BOARD_ITEM *aParent)
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
virtual void swapData(BOARD_ITEM *aImage) override
void SetLeaderLength(int aLength)
void CopyFrom(const BOARD_ITEM *aOther) override
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void ChangeLeaderLength(int aLength)
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
VECTOR2I GetKnee() const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
Definition pcb_text.cpp:371
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition pcb_text.cpp:242
EDA_ANGLE GetTextAngle() const override
Definition pcb_text.cpp:560
void Offset(const VECTOR2I &aOffset) override
Definition pcb_text.cpp:525
void SetLibTextAngle(const EDA_ANGLE &aAngle)
Definition pcb_text.h:129
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition pcb_text.cpp:257
VECTOR2I GetTextPos() const override
Definition pcb_text.cpp:461
PCB_TEXT(BOARD_ITEM *parent, KICAD_T idtype=PCB_TEXT_T)
Definition pcb_text.cpp:49
void OnFootprintRescaled(double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I &aAnchor, const EDA_ANGLE &aParentRotate) override
Apply a parent footprint scale to this item.
Definition pcb_text.cpp:614
std::vector< int > ViewGetLayers() const override
Definition pcb_text.cpp:248
bool TextHitTest(const VECTOR2I &aPoint, int aAccuracy=0) const override
Test if aPoint is within the bounds of this object.
Definition pcb_text.cpp:426
const EDA_ANGLE & GetLibTextAngle() const
Text angle in the parent footprint's lib frame, or absolute when not in a footprint.
Definition pcb_text.h:127
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition pcb_text.cpp:694
int GetTextThickness() const override
Definition pcb_text.cpp:497
void SetTextAngle(const EDA_ANGLE &aAngle) override
Definition pcb_text.cpp:569
wxString GetShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition pcb_text.cpp:178
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:263
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition property.h:293
PROPERTY_BASE & SetValidator(PROPERTY_VALIDATOR_FN &&aValidator)
Definition property.h:368
PROPERTY_BASE & SetIsCopyable(bool aIsCopyable=true)
Definition property.h:359
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
void AddShape(SHAPE *aShape)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
SEGMENT_ITERATOR IterateSegments(int aFirst, int aLast, bool aIterateHoles=false)
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
SEGMENT_ITERATOR_TEMPLATE< SEG > SEGMENT_ITERATOR
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
SEGMENT_ITERATOR_TEMPLATE< const SEG > CONST_SEGMENT_ITERATOR
const SEG & GetSeg() const
VECTOR2I InverseApply(const VECTOR2I &aPoint) const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition vector2d.h:534
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition vector2d.h:279
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition vector2d.h:381
@ FOR_GUI
Definition common.h:89
DIM_VALUE_MODE DimensionValueMode(BOARD *aBoard, const PCB_DIMENSION_BASE *aDimension)
The value mode aDimension is in, derived from state: a self driving length means Driving,...
bool DimensionHasValueMode(const PCB_DIMENSION_BASE *aDimension)
True for dimension types with a measured value aligned orthogonal or radial offering the Driven Drivi...
PCB_CONSTRAINT * FindDimensionLengthConstraint(BOARD *aBoard, const PCB_DIMENSION_BASE *aDimension)
Self FIXED_LENGTH constraint whose members are exactly aDimension START and END or nullptr the drivin...
bool DimensionCanDrive(BOARD *aBoard, const PCB_DIMENSION_BASE *aDimension)
True when Driving mode may be offered for aDimension needs both endpoints bound via DimensionEndpoint...
DIM_VALUE_MODE
Mode a value bearing dimension value is in Driven mirrors measured geometry Driving forces geometry t...
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
DRC_CONSTRAINT_T
Definition drc_rule.h:49
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:422
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:424
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:419
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:418
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:423
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:427
static constexpr EDA_ANGLE FULL_CIRCLE
Definition eda_angle.h:420
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:426
static constexpr EDA_ANGLE ANGLE_135
Definition eda_angle.h:425
#define PCB_EDIT_FRAME_NAME
EDA_UNITS
Definition eda_units.h:44
a few functions useful in geometry calculations.
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition layer_id.cpp:179
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:180
@ LAYER_CONSTRAINT_SHADOW
Shadow layer for items bound to a constraint.
Definition layer_ids.h:320
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ Dwgs_User
Definition layer_ids.h:103
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:41
FLIP_DIRECTION
Definition mirror.h:23
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:24
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:25
KICOMMON_API wxString StringFromValue(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, double aValue, bool aAddUnitsText=false, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Return the string from aValue according to aUnits (inch, mm ...) for display.
KICOMMON_API double DoubleValueFromString(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnits, const wxString &aTextValue, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Convert aTextValue to a double.
KICOMMON_API double ToUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Convert aValue in internal units to the appropriate user units defined by aUnit.
KICOMMON_API wxString GetText(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
bool ShapeHitTest(const SHAPE_LINE_CHAIN &aHitter, const SHAPE &aHittee, bool aHitteeContained)
Perform a shape-to-shape hit test.
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
KICOMMON_API void PackCustomProperties(google::protobuf::RepeatedPtrField< types::CustomProperty > *aOutput, const EDA_ITEM &aItem)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void UnpackCustomProperties(const google::protobuf::RepeatedPtrField< types::CustomProperty > &aInput, EDA_ITEM &aItem)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
#define _HKI(x)
Definition page_info.cpp:40
static const int INWARD_ARROW_LENGTH_TO_HEAD_RATIO
static const EDA_ANGLE s_arrowAngle(27.5, DEGREES_T)
static struct DIMENSION_DESC _DIMENSION_DESC
static OPT_VECTOR2I segPolyIntersection(const SHAPE_POLY_SET &aPoly, const SEG &aSeg, bool aStart=true)
Find the intersection between a given segment and polygon outline.
static OPT_VECTOR2I segCircleIntersection(CIRCLE &aCircle, SEG &aSeg, bool aStart=true)
static void CollectKnockedOutSegments(const SHAPE_POLY_SET &aPoly, const SEG &aSeg, std::vector< std::shared_ptr< SHAPE > > &aSegmentsAfterKnockout)
Knockout a polygon from a segment.
DIM_TEXT_POSITION
Where to place the text on a dimension.
@ OUTSIDE
Text appears outside the dimension line (default)
@ INLINE
Text appears in line with the dimension line.
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
DIM_ARROW_DIRECTION
Used for dimension's arrow.
DIM_TEXT_BORDER
Frame to show around dimension text.
DIM_PRECISION
#define TYPE_HASH(x)
Definition property.h:74
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition property.h:877
@ PT_DEGREE
Angle expressed in degrees.
Definition property.h:66
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
std::optional< std::unique_ptr< VALIDATION_ERROR > > VALIDATOR_RESULT
Null optional means validation succeeded.
std::optional< VECTOR2I > OPT_VECTOR2I
Definition seg.h:35
VECTOR2I center
int radius
VECTOR2I end
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:98
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:95
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:96
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:94
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:97
constexpr int sign(T val)
Definition util.h:141
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682