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_text.h>
37#include <geometry/shape_rect.h>
41#include <trigo.h>
42#include <api/api_enums.h>
43#include <api/api_utils.h>
44#include <api/board/board_types.pb.h>
45#include <properties/property.h>
47
48
50
51static const EDA_ANGLE s_arrowAngle( 27.5, DEGREES_T );
52
53
62static OPT_VECTOR2I segPolyIntersection( const SHAPE_POLY_SET& aPoly, const SEG& aSeg,
63 bool aStart = true )
64{
65 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
66 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
67
68 if( aPoly.Contains( start ) )
69 return std::nullopt;
70
71 for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
72 {
73 if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
74 {
75 if( ( *intersection - start ).SquaredEuclideanNorm()
76 < ( endpoint - start ).SquaredEuclideanNorm() )
77 endpoint = *intersection;
78 }
79 }
80
81 if( start == endpoint )
82 return std::nullopt;
83
84 return OPT_VECTOR2I( endpoint );
85}
86
87
88static OPT_VECTOR2I segCircleIntersection( CIRCLE& aCircle, SEG& aSeg, bool aStart = true )
89{
90 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
91 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
92
93 if( aCircle.Contains( start ) )
94 return std::nullopt;
95
96 std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
97
98 for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
99 {
100 if( ( intersection - start ).SquaredEuclideanNorm()
101 < ( endpoint - start ).SquaredEuclideanNorm() )
102 endpoint = intersection;
103 }
104
105 if( start == endpoint )
106 return std::nullopt;
107
108 return OPT_VECTOR2I( endpoint );
109}
110
111
116static void CollectKnockedOutSegments( const SHAPE_POLY_SET& aPoly, const SEG& aSeg,
117 std::vector<std::shared_ptr<SHAPE>>& aSegmentsAfterKnockout )
118{
119 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
120 const bool containsA = aPoly.Contains( aSeg.A );
121 const bool containsB = aPoly.Contains( aSeg.B );
122
123 const OPT_VECTOR2I endpointA = segPolyIntersection( aPoly, aSeg );
124 const OPT_VECTOR2I endpointB = segPolyIntersection( aPoly, aSeg, false );
125
126 if( endpointA )
127 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( aSeg.A, *endpointA ) );
128
129 if( endpointB )
130 {
131 bool can_add = true;
132
133 if( endpointA )
134 {
135 if( ( *endpointB == aSeg.A && *endpointA == aSeg.B )
136 || ( *endpointA == *endpointB && aSeg.A == aSeg.B ) )
137 can_add = false;
138 }
139
140 if( can_add )
141 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( *endpointB, aSeg.B ) );
142 }
143
144 if( !containsA && !containsB && !endpointA && !endpointB )
145 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( aSeg ) );
146}
147
148
150 PCB_TEXT( aParent, aType ),
151 m_overrideTextEnabled( false ),
153 m_autoUnits( false ),
157 m_suppressZeroes( false ),
158 m_lineThickness( pcbIUScale.mmToIU( 0.2 ) ),
159 m_arrowLength( pcbIUScale.MilsToIU( 50 ) ),
162 m_keepTextAligned( true ),
163 m_measuredValue( 0 ),
164 m_start( 0, 0 ),
165 m_end( 0, 0 ),
166 m_inClearRenderCache( false )
167{
169 m_busy = false;
170}
171
172
174{
175 if( const FOOTPRINT* fp = GetParentFootprint() )
176 return fp->GetTransform().Apply( m_start );
177
178 return m_start;
179}
180
181
183{
184 if( const FOOTPRINT* fp = GetParentFootprint() )
185 return fp->GetTransform().Apply( m_end );
186
187 return m_end;
188}
189
190
192{
193 if( const FOOTPRINT* fp = GetParentFootprint() )
194 m_start = fp->GetTransform().InverseApply( aPoint );
195 else
196 m_start = aPoint;
197}
198
199
201{
202 if( const FOOTPRINT* fp = GetParentFootprint() )
203 m_end = fp->GetTransform().InverseApply( aPoint );
204 else
205 m_end = aPoint;
206}
207
208
209void PCB_DIMENSION_BASE::OnFootprintRescaled( double /* aRatioX */, double /* aRatioY */, double /* aLinearFactor */,
210 const VECTOR2I& /* aAnchor */, const EDA_ANGLE& /* aParentRotate */ )
211{
214}
215
216
224
225
227{
228 if( Type() != aOther.Type() )
229 return false;
230
231 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
232
233 return *this == other;
234}
235
236
238{
239 if( m_textPosition != aOther.m_textPosition )
240 return false;
241
243 return false;
244
245 if( m_units != aOther.m_units )
246 return false;
247
248 if( m_autoUnits != aOther.m_autoUnits )
249 return false;
250
251 if( m_unitsFormat != aOther.m_unitsFormat )
252 return false;
253
254 if( m_precision != aOther.m_precision )
255 return false;
256
257 if( m_suppressZeroes != aOther.m_suppressZeroes )
258 return false;
259
260 if( m_lineThickness != aOther.m_lineThickness )
261 return false;
262
263 if( m_arrowLength != aOther.m_arrowLength )
264 return false;
265
267 return false;
268
269 if( m_measuredValue != aOther.m_measuredValue )
270 return false;
271
272 return EDA_TEXT::operator==( aOther );
273}
274
275
276double PCB_DIMENSION_BASE::Similarity( const BOARD_ITEM& aOther ) const
277{
278 if( m_Uuid == aOther.m_Uuid )
279 return 1.0;
280
281 if( Type() != aOther.Type() )
282 return 0.0;
283
284 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
285
286 double similarity = 1.0;
287
288 if( m_textPosition != other.m_textPosition )
289 similarity *= 0.9;
290
292 similarity *= 0.9;
293
294 if( m_units != other.m_units )
295 similarity *= 0.9;
296
297 if( m_autoUnits != other.m_autoUnits )
298 similarity *= 0.9;
299
300 if( m_unitsFormat != other.m_unitsFormat )
301 similarity *= 0.9;
302
303 if( m_precision != other.m_precision )
304 similarity *= 0.9;
305
307 similarity *= 0.9;
308
309 if( m_lineThickness != other.m_lineThickness )
310 similarity *= 0.9;
311
312 if( m_arrowLength != other.m_arrowLength )
313 similarity *= 0.9;
314
316 similarity *= 0.9;
317
318 if( m_measuredValue != other.m_measuredValue )
319 similarity *= 0.9;
320
321 similarity *= EDA_TEXT::Similarity( other );
322
323 return similarity;
324}
325
326
327void PCB_DIMENSION_BASE::Serialize( google::protobuf::Any &aContainer ) const
328{
329 using namespace kiapi::common;
330 using namespace kiapi::board::types;
331 Dimension dimension;
332
333 dimension.mutable_id()->set_value( m_Uuid.AsStdString() );
334 dimension.set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( GetLayer() ) );
335 dimension.set_locked( IsLocked() ? types::LockedState::LS_LOCKED
336 : types::LockedState::LS_UNLOCKED );
337
338 google::protobuf::Any any;
340 any.UnpackTo( dimension.mutable_text() );
341
342 types::Text* text = dimension.mutable_text();
343 text->set_text( GetValueText() );
344
345 dimension.set_override_text_enabled( m_overrideTextEnabled );
346 dimension.set_override_text( m_valueString.ToUTF8() );
347 dimension.set_prefix( m_prefix.ToUTF8() );
348 dimension.set_suffix( m_suffix.ToUTF8() );
349
351 dimension.set_unit_format(
353 dimension.set_arrow_direction(
356 dimension.set_suppress_trailing_zeroes( m_suppressZeroes );
357
358 dimension.mutable_line_thickness()->set_value_nm( m_lineThickness );
359 dimension.mutable_arrow_length()->set_value_nm( m_arrowLength );
360 dimension.mutable_extension_offset()->set_value_nm( m_extensionOffset );
361 dimension.set_text_position(
363 dimension.set_keep_text_aligned( m_keepTextAligned );
364
365 aContainer.PackFrom( dimension );
366}
367
368
369bool PCB_DIMENSION_BASE::Deserialize( const google::protobuf::Any &aContainer )
370{
371 using namespace kiapi::common;
372 kiapi::board::types::Dimension dimension;
373
374 if( !aContainer.UnpackTo( &dimension ) )
375 return false;
376
378 SetUuidDirect( KIID( dimension.id().value() ) );
379 SetLocked( dimension.locked() == types::LockedState::LS_LOCKED );
380
381 google::protobuf::Any any;
382 any.PackFrom( dimension.text() );
384
385 SetOverrideTextEnabled( dimension.override_text_enabled() );
386 SetOverrideText( wxString::FromUTF8( dimension.override_text() ) );
387 SetPrefix( wxString::FromUTF8( dimension.prefix() ) );
388 SetSuffix( wxString::FromUTF8( dimension.suffix() ) );
389
390 SetUnitsMode( FromProtoEnum<DIM_UNITS_MODE>( dimension.unit() ) );
391 SetUnitsFormat( FromProtoEnum<DIM_UNITS_FORMAT>( dimension.unit_format() ) );
392 SetArrowDirection( FromProtoEnum<DIM_ARROW_DIRECTION>( dimension.arrow_direction() ) );
393 SetPrecision( FromProtoEnum<DIM_PRECISION>( dimension.precision() ) );
394 SetSuppressZeroes( dimension.suppress_trailing_zeroes() );
395
396 SetLineThickness( dimension.line_thickness().value_nm() );
397 SetArrowLength( dimension.arrow_length().value_nm() );
398 SetExtensionOffset( dimension.extension_offset().value_nm() );
399 SetTextPositionMode( FromProtoEnum<DIM_TEXT_POSITION>( dimension.text_position() ) );
400 SetKeepTextAligned( dimension.keep_text_aligned() );
401
402 Update();
403
404 return true;
405}
406
407
408void PCB_DIMENSION_BASE::drawAnArrow( VECTOR2I startPoint, EDA_ANGLE anAngle, int aLength )
409{
410 if( aLength )
411 {
412 VECTOR2I tailEnd( aLength, 0 );
413 RotatePoint( tailEnd, -anAngle );
414 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + tailEnd ) );
415 }
416
417 VECTOR2I arrowEndPos( m_arrowLength, 0 );
418 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
419
420 RotatePoint( arrowEndPos, -anAngle + s_arrowAngle );
421 RotatePoint( arrowEndNeg, -anAngle - s_arrowAngle );
422
423 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + arrowEndPos ) );
424 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + arrowEndNeg ) );
425}
426
427
429{
431
432 switch( m_unitsFormat )
433 {
434 case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
435 break;
436
437 case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
439 break;
440
441 case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
442 text += wxT( " (" ) + EDA_UNIT_UTILS::GetText( m_units ).Trim( false ) + wxT( ")" );
443 break;
444 }
445
446 text.Prepend( m_prefix );
447 text.Append( m_suffix );
448
449 SetText( text );
450}
451
452
454{
456
457 // We use EDA_TEXT::ClearRenderCache() as a signal that the properties of the EDA_TEXT
458 // have changed and we may need to update the dimension text
459
461 {
463 Update();
464 m_inClearRenderCache = false;
465 }
466}
467
468
469template<typename ShapeType>
470void PCB_DIMENSION_BASE::addShape( const ShapeType& aShape )
471{
472 m_shapes.push_back( std::make_shared<ShapeType>( aShape ) );
473}
474
475
477{
478 struct lconv* lc = localeconv();
479 wxChar sep = lc->decimal_point[0];
480
481 int val = GetMeasuredValue();
482 int precision = static_cast<int>( m_precision );
483 wxString text;
484
485 if( precision >= 6 )
486 {
487 switch( m_units )
488 {
489 case EDA_UNITS::INCH: precision = precision - 4; break;
490 case EDA_UNITS::MILS: precision = std::max( 0, precision - 7 ); break;
491 case EDA_UNITS::MM: precision = precision - 5; break;
492 default: precision = precision - 4; break;
493 }
494 }
495
496 wxString format = wxT( "%." ) + wxString::Format( wxT( "%i" ), precision ) + wxT( "f" );
497
498 text.Printf( format, EDA_UNIT_UTILS::UI::ToUserUnit( pcbIUScale, m_units, val ) );
499
500 if( m_suppressZeroes )
501 {
502 while( text.EndsWith( '0' ) )
503 {
504 text.RemoveLast();
505
506 if( text.EndsWith( '.' ) || text.EndsWith( sep ) )
507 {
508 text.RemoveLast();
509 break;
510 }
511 }
512 }
513
514 return text;
515}
516
517
518void PCB_DIMENSION_BASE::SetPrefix( const wxString& aPrefix )
519{
520 m_prefix = aPrefix;
521}
522
523
524void PCB_DIMENSION_BASE::SetSuffix( const wxString& aSuffix )
525{
526 m_suffix = aSuffix;
527}
528
529
531{
532 m_units = aUnits;
533}
534
535
537{
538 if( m_autoUnits )
539 {
541 }
542 else
543 {
544 switch( m_units )
545 {
546 default:
550 }
551 }
552}
553
554
556{
557 switch( aMode )
558 {
560 m_autoUnits = false;
562 break;
563
565 m_autoUnits = false;
567 break;
568
570 m_autoUnits = false;
572 break;
573
575 m_autoUnits = true;
577 break;
578 }
579}
580
581
583{
584 SetTextAngleDegrees( aDegrees );
585 // Create or repair any knockouts
586 Update();
587}
588
589
591{
592 SetKeepTextAligned( aKeepAligned );
593 // Re-align the text and repair any knockouts
594 Update();
595}
596
597
599{
600 PCB_TEXT::Offset( offset );
601
602 if( const FOOTPRINT* fp = GetParentFootprint() )
603 {
604 const TRANSFORM_TRS& xform = fp->GetTransform();
605 VECTOR2I libOffset = xform.InverseApply( offset ) - xform.InverseApply( VECTOR2I( 0, 0 ) );
606 m_start += libOffset;
607 m_end += libOffset;
608 }
609 else
610 {
611 m_start += offset;
612 m_end += offset;
613 }
614
615 Update();
616}
617
618
619void PCB_DIMENSION_BASE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
620{
621 EDA_ANGLE newAngle = GetTextAngle() + aAngle;
622 newAngle.Normalize();
623 SetTextAngle( newAngle );
624
625 VECTOR2I pt = GetTextPos();
626 RotatePoint( pt, aRotCentre, aAngle );
627 SetTextPos( pt );
628
629 VECTOR2I boardStart = GetStart();
630 VECTOR2I boardEnd = GetEnd();
631 RotatePoint( boardStart, aRotCentre, aAngle );
632 RotatePoint( boardEnd, aRotCentre, aAngle );
633
634 if( const FOOTPRINT* fp = GetParentFootprint() )
635 {
636 m_start = fp->GetTransform().InverseApply( boardStart );
637 m_end = fp->GetTransform().InverseApply( boardEnd );
638 }
639 else
640 {
641 m_start = boardStart;
642 m_end = boardEnd;
643 }
644
645 Update();
646}
647
648
649void PCB_DIMENSION_BASE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
650{
651 Mirror( aCentre, aFlipDirection );
652
654}
655
656
657void PCB_DIMENSION_BASE::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
658{
659 if( const FOOTPRINT* fp = GetParentFootprint() )
660 {
661 const VECTOR2I libAxis = fp->GetTransform().InverseApply( axis_pos );
662
663 auto mirrorPt = [&]( VECTOR2I& p )
664 {
665 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
666 p.x = 2 * libAxis.x - p.x;
667 else
668 p.y = 2 * libAxis.y - p.y;
669 };
670
671 mirrorPt( m_start );
672 mirrorPt( m_end );
673
674 VECTOR2I libTextPos = EDA_TEXT::GetTextPos();
675 mirrorPt( libTextPos );
676 EDA_TEXT::SetTextPos( libTextPos );
677
678 EDA_ANGLE newLibAngle =
680 SetLibTextAngle( newLibAngle );
681
682 if( IsSideSpecific() )
684
686 Update();
687 return;
688 }
689
690 VECTOR2I newPos = GetTextPos();
691
692 MIRROR( newPos, axis_pos, aFlipDirection );
693
694 SetTextPos( newPos );
695
696 // invert angle
698
699 MIRROR( m_start, axis_pos, aFlipDirection );
700 MIRROR( m_end, axis_pos, aFlipDirection );
701
702 if( IsSideSpecific() )
704
705 Update();
706}
707
708
709void PCB_DIMENSION_BASE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
710{
711 PCB_TEXT::StyleFromSettings( settings, aCheckSide );
712
720
721 Update(); // refresh text & geometry
722
723}
724
725
727 std::vector<MSG_PANEL_ITEM>& aList )
728{
729 // for now, display only the text within the DIMENSION using class PCB_TEXT.
730 wxString msg;
731
732 wxCHECK_RET( m_parent != nullptr, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
733
734 // Don't use GetShownText(); we want to see the variable references here
735 aList.emplace_back( _( "Dimension" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
736
737 aList.emplace_back( _( "Prefix" ), GetPrefix() );
738
740 {
741 aList.emplace_back( _( "Override Text" ), GetOverrideText() );
742 }
743 else
744 {
745 aList.emplace_back( _( "Value" ), GetValueText() );
746
747 switch( GetPrecision() )
748 {
749 case DIM_PRECISION::V_VV: msg = wxT( "0.00 in / 0 mils / 0.0 mm" ); break;
750 case DIM_PRECISION::V_VVV: msg = wxT( "0.000 in / 0 mils / 0.00 mm" ); break;
751 case DIM_PRECISION::V_VVVV: msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" ); break;
752 case DIM_PRECISION::V_VVVVV: msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
753 default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
754 }
755
756 aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
757 }
758
759 aList.emplace_back( _( "Suffix" ), GetSuffix() );
760
761 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
762 // in frame's units.
763 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MM );
764 unitsProvider.SetUserUnits( GetUnits() );
765
766 aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( GetUnits() ) );
767
768 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
769 aList.emplace_back( _( "Text Thickness" ), unitsProvider.MessageTextFromValue( GetTextThickness() ) );
770 aList.emplace_back( _( "Text Width" ), unitsProvider.MessageTextFromValue( GetTextWidth() ) );
771 aList.emplace_back( _( "Text Height" ), unitsProvider.MessageTextFromValue( GetTextHeight() ) );
772
773 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
774
775 if( Type() == PCB_DIM_CENTER_T )
776 {
777 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
778 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
779 aFrame->MessageTextFromValue( startCoord.x ),
780 aFrame->MessageTextFromValue( startCoord.y ) );
781
782 aList.emplace_back( start, wxEmptyString );
783 }
784 else
785 {
786 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
787 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
788 aFrame->MessageTextFromValue( startCoord.x ),
789 aFrame->MessageTextFromValue( startCoord.y ) );
790 VECTOR2I endCoord = originTransforms.ToDisplayAbs( GetEnd() );
791 wxString end = wxString::Format( wxT( "@(%s, %s)" ),
792 aFrame->MessageTextFromValue( endCoord.x ),
793 aFrame->MessageTextFromValue( endCoord.y ) );
794
795 aList.emplace_back( start, end );
796 }
797
798 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
799 aList.emplace_back( _( "Status" ), _( "Locked" ) );
800
801 aList.emplace_back( _( "Layer" ), GetLayerName() );
802}
803
804
805std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
806{
807 std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
808
809 effectiveShape->AddShape( GetEffectiveTextShape()->Clone() );
810
811 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
812 effectiveShape->AddShape( shape->Clone() );
813
814 return effectiveShape;
815}
816
817
818bool PCB_DIMENSION_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
819{
820 if( TextHitTest( aPosition ) )
821 return true;
822
823 int dist_max = aAccuracy + ( m_lineThickness / 2 );
824
825 // Locate SEGMENTS
826
827 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
828 {
829 if( shape->Collide( aPosition, dist_max ) )
830 return true;
831 }
832
833 return false;
834}
835
836
837bool PCB_DIMENSION_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
838{
839 BOX2I arect = aRect;
840 arect.Inflate( aAccuracy );
841
842 BOX2I rect = GetBoundingBox();
843
844 if( aAccuracy )
845 rect.Inflate( aAccuracy );
846
847 if( aContained )
848 return arect.Contains( rect );
849
850 return arect.Intersects( rect );
851}
852
853
854bool PCB_DIMENSION_BASE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
855{
856 // Note: Can't use GetEffectiveShape() because we want text as BoundingBox, not as graphics.
857 SHAPE_COMPOUND effShape;
858
859 // Add shapes
860 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
861 effShape.AddShape( shape );
862
863 if( aContained )
864 return TextHitTest( aPoly, aContained ) && KIGEOM::ShapeHitTest( aPoly, effShape, aContained );
865 else
866 return TextHitTest( aPoly, aContained ) || KIGEOM::ShapeHitTest( aPoly, effShape, aContained );
867}
868
869
871{
872 BOX2I bBox;
873 int xmin, xmax, ymin, ymax;
874
875 bBox = GetTextBox( nullptr );
876 xmin = bBox.GetX();
877 xmax = bBox.GetRight();
878 ymin = bBox.GetY();
879 ymax = bBox.GetBottom();
880
881 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
882 {
883 BOX2I shapeBox = shape->BBox();
884 shapeBox.Inflate( m_lineThickness / 2 );
885
886 xmin = std::min( xmin, shapeBox.GetOrigin().x );
887 xmax = std::max( xmax, shapeBox.GetEnd().x );
888 ymin = std::min( ymin, shapeBox.GetOrigin().y );
889 ymax = std::max( ymax, shapeBox.GetEnd().y );
890 }
891
892 bBox.SetX( xmin );
893 bBox.SetY( ymin );
894 bBox.SetWidth( xmax - xmin + 1 );
895 bBox.SetHeight( ymax - ymin + 1 );
896
897 bBox.Normalize();
898
899 return bBox;
900}
901
902
903wxString PCB_DIMENSION_BASE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
904{
905 return wxString::Format( _( "Dimension '%s' on %s" ),
906 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ),
907 GetLayerName() );
908}
909
910
911
913{
915 VECTOR2I( GetBoundingBox().GetSize() ) );
916 dimBBox.Merge( PCB_TEXT::ViewBBox() );
917
918 return dimBBox;
919}
920
921
923 int aClearance, int aError, ERROR_LOC aErrorLoc,
924 bool aIgnoreLineWidth ) const
925{
926 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
927
928 for( const std::shared_ptr<SHAPE>& shape : m_shapes )
929 {
930 const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
931 const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
932
933 if( circle )
934 {
935 TransformCircleToPolygon( aBuffer, circle->GetCenter(),
936 circle->GetRadius() + m_lineThickness / 2 + aClearance,
937 aError, aErrorLoc );
938 }
939 else if( seg )
940 {
941 TransformOvalToPolygon( aBuffer, seg->GetSeg().A, seg->GetSeg().B,
942 m_lineThickness + 2 * aClearance, aError, aErrorLoc );
943 }
944 else
945 {
946 wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeToPolygon unknown shape type." ) );
947 }
948 }
949}
950
951
953 PCB_DIMENSION_BASE( aParent, aType ),
954 m_height( 0 )
955{
956 // To preserve look of old dimensions, initialize extension height based on default arrow length
957 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
958}
959
960
962{
963 return new PCB_DIM_ALIGNED( *this );
964}
965
966
968{
969 wxCHECK( aOther && aOther->Type() == PCB_DIM_ALIGNED_T, /* void */ );
970 *this = *static_cast<const PCB_DIM_ALIGNED*>( aOther );
971}
972
973void PCB_DIM_ALIGNED::Serialize( google::protobuf::Any &aContainer ) const
974{
975 using namespace kiapi::common;
976 kiapi::board::types::Dimension dimension;
977
978 PCB_DIMENSION_BASE::Serialize( aContainer );
979 aContainer.UnpackTo( &dimension );
980
981 PackVector2( *dimension.mutable_aligned()->mutable_start(), GetStart() );
982 PackVector2( *dimension.mutable_aligned()->mutable_end(), GetEnd() );
983 dimension.mutable_aligned()->mutable_height()->set_value_nm( m_height );
984 dimension.mutable_aligned()->mutable_extension_height()->set_value_nm( m_extensionHeight );
985
986 aContainer.PackFrom( dimension );
987}
988
989
990bool PCB_DIM_ALIGNED::Deserialize( const google::protobuf::Any &aContainer )
991{
992 using namespace kiapi::common;
993
994 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
995 return false;
996
997 kiapi::board::types::Dimension dimension;
998 aContainer.UnpackTo( &dimension );
999
1000 if( !dimension.has_aligned() )
1001 return false;
1002
1003 SetStart( UnpackVector2( dimension.aligned().start() ) );
1004 SetEnd( UnpackVector2( dimension.aligned().end() ) );
1005 SetHeight( dimension.aligned().height().value_nm());
1006 SetExtensionHeight( dimension.aligned().extension_height().value_nm() );
1007
1008 Update();
1009
1010 return true;
1011}
1012
1013
1015{
1016 wxASSERT( aImage->Type() == Type() );
1017
1018 m_shapes.clear();
1019 static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
1020
1021 std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
1022
1023 Update();
1024}
1025
1026
1027void PCB_DIM_ALIGNED::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
1028{
1029 m_height = -m_height;
1030 // Call this last for the Update()
1031 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
1032}
1033
1034
1039
1040
1041void PCB_DIM_ALIGNED::UpdateHeight( const VECTOR2I& aCrossbarStart, const VECTOR2I& aCrossbarEnd )
1042{
1043 VECTOR2D height( aCrossbarStart - GetStart() );
1044 VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
1045
1046 if( height.Cross( crossBar ) > 0 )
1047 m_height = -height.EuclideanNorm();
1048 else
1049 m_height = height.EuclideanNorm();
1050
1051 Update();
1052}
1053
1054
1056{
1057 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1058 return;
1059
1060 m_busy = true;
1061
1062 m_shapes.clear();
1063
1064 const VECTOR2I start = GetStart();
1065 const VECTOR2I end = GetEnd();
1066 VECTOR2I dimension( end - start );
1067
1068 m_measuredValue = KiROUND( dimension.EuclideanNorm() );
1069
1070 VECTOR2I extension;
1071
1072 if( m_height > 0 )
1073 extension = VECTOR2I( -dimension.y, dimension.x );
1074 else
1075 extension = VECTOR2I( dimension.y, -dimension.x );
1076
1077 // Add extension lines
1078 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
1079
1080 VECTOR2I extStart( start );
1081 extStart += extension.Resize( m_extensionOffset );
1082
1083 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1084
1085 extStart = VECTOR2I( end );
1086 extStart += extension.Resize( m_extensionOffset );
1087
1088 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1089
1090 // Add crossbar
1091 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
1092 m_crossBarStart = start + crossBarDistance;
1093 m_crossBarEnd = end + crossBarDistance;
1094
1095 // Update text after calculating crossbar position but before adding crossbar lines
1096 updateText();
1097
1098 // Now that we have the text updated, we can determine how to draw the crossbar.
1099 // First we need to create an appropriate bounding polygon to collide with
1100 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, - GetEffectiveTextPenWidth() );
1101
1102 SHAPE_POLY_SET polyBox;
1103 polyBox.NewOutline();
1104 polyBox.Append( textBox.GetOrigin() );
1105 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1106 polyBox.Append( textBox.GetEnd() );
1107 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1108 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1109
1110 // The ideal crossbar, if the text doesn't collide
1111 SEG crossbar( m_crossBarStart, m_crossBarEnd );
1112
1113 CollectKnockedOutSegments( polyBox, crossbar, m_shapes );
1114
1116 {
1117 drawAnArrow( m_crossBarStart, EDA_ANGLE( dimension ) + EDA_ANGLE( 180 ),
1119 drawAnArrow( m_crossBarEnd, EDA_ANGLE( dimension ),
1121 }
1122 else
1123 {
1124 drawAnArrow( m_crossBarStart, EDA_ANGLE( dimension ), 0 );
1125 drawAnArrow( m_crossBarEnd, EDA_ANGLE( dimension ) + EDA_ANGLE( 180 ), 0 );
1126 }
1127
1128 m_busy = false;
1129}
1130
1131
1133{
1134 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
1135
1137 {
1138 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
1139 EDA_ANGLE rotation;
1140
1141 if( crossbarCenter.x == 0 )
1142 rotation = ANGLE_90 * sign( -crossbarCenter.y );
1143 else if( crossbarCenter.x < 0 )
1144 rotation = -ANGLE_90;
1145 else
1146 rotation = ANGLE_90;
1147
1148 VECTOR2I textOffset = crossbarCenter;
1149 RotatePoint( textOffset, rotation );
1150 textOffset = crossbarCenter + textOffset.Resize( textOffsetDistance );
1151
1152 SetTextPos( m_crossBarStart + textOffset );
1153 }
1155 {
1156 SetTextPos( m_crossBarStart + crossbarCenter );
1157 }
1158
1159 if( m_keepTextAligned )
1160 {
1161 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( crossbarCenter );
1162 textAngle.Normalize();
1163
1164 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1165 textAngle -= ANGLE_180;
1166
1167 SetTextAngle( textAngle );
1168 }
1169
1171}
1172
1173
1174void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1175{
1176 PCB_DIMENSION_BASE::GetMsgPanelInfo( aFrame, aList );
1177
1178 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
1179 // in frame's units.
1180 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MM );
1181 unitsProvider.SetUserUnits( GetUnits() );
1182
1183 aList.emplace_back( _( "Height" ), unitsProvider.MessageTextFromValue( m_height ) );
1184}
1185
1186
1189{
1190 // To preserve look of old dimensions, initialize extension height based on default arrow length
1191 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
1193}
1194
1195
1197{
1198 return new PCB_DIM_ORTHOGONAL( *this );
1199}
1200
1201
1203{
1204 wxCHECK( aOther && aOther->Type() == PCB_DIM_ORTHOGONAL_T, /* void */ );
1205 *this = *static_cast<const PCB_DIM_ORTHOGONAL*>( aOther );
1206}
1207
1208void PCB_DIM_ORTHOGONAL::Serialize( google::protobuf::Any &aContainer ) const
1209{
1210 using namespace kiapi::common;
1211 kiapi::board::types::Dimension dimension;
1212
1213 PCB_DIMENSION_BASE::Serialize( aContainer );
1214 aContainer.UnpackTo( &dimension );
1215
1216 PackVector2( *dimension.mutable_orthogonal()->mutable_start(), GetStart() );
1217 PackVector2( *dimension.mutable_orthogonal()->mutable_end(), GetEnd() );
1218 dimension.mutable_orthogonal()->mutable_height()->set_value_nm( m_height );
1219 dimension.mutable_orthogonal()->mutable_extension_height()->set_value_nm( m_extensionHeight );
1220
1221 dimension.mutable_orthogonal()->set_alignment( m_orientation == DIR::VERTICAL
1222 ? types::AxisAlignment::AA_Y_AXIS
1223 : types::AxisAlignment::AA_X_AXIS );
1224 aContainer.PackFrom( dimension );
1225}
1226
1227
1228bool PCB_DIM_ORTHOGONAL::Deserialize( const google::protobuf::Any &aContainer )
1229{
1230 using namespace kiapi::common;
1231
1232 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1233 return false;
1234
1235 kiapi::board::types::Dimension dimension;
1236 aContainer.UnpackTo( &dimension );
1237
1238 if( !dimension.has_orthogonal() )
1239 return false;
1240
1241 SetStart( UnpackVector2( dimension.orthogonal().start() ) );
1242 SetEnd( UnpackVector2( dimension.orthogonal().end() ) );
1243 SetHeight( dimension.orthogonal().height().value_nm());
1244 SetExtensionHeight( dimension.orthogonal().extension_height().value_nm() );
1245 SetOrientation( dimension.orthogonal().alignment() == types::AxisAlignment::AA_Y_AXIS
1247 : DIR::HORIZONTAL );
1248
1249 Update();
1250
1251 return true;
1252}
1253
1254
1256{
1257 wxASSERT( aImage->Type() == Type() );
1258
1259 m_shapes.clear();
1260 static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
1261
1262 std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
1263 *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
1264
1265 Update();
1266}
1267
1268
1269void PCB_DIM_ORTHOGONAL::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
1270{
1271 // Only reverse the height if the height is aligned with the flip
1272 if( m_orientation == DIR::HORIZONTAL && aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
1273 m_height = -m_height;
1274 else if( m_orientation == DIR::VERTICAL && aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
1275 m_height = -m_height;
1276
1277 // Call this last, as we need the Update()
1278 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
1279}
1280
1281
1286
1287
1289{
1290 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1291 return;
1292
1293 m_busy = true;
1294 m_shapes.clear();
1295
1296 const VECTOR2I start = GetStart();
1297 const VECTOR2I end = GetEnd();
1298
1299 int measurement = ( m_orientation == DIR::HORIZONTAL ? end.x - start.x : end.y - start.y );
1301
1302 VECTOR2I extension;
1303
1305 extension = VECTOR2I( 0, m_height );
1306 else
1307 extension = VECTOR2I( m_height, 0 );
1308
1309 // Add first extension line
1310 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
1311
1312 VECTOR2I extStart( start );
1313 extStart += extension.Resize( m_extensionOffset );
1314
1315 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1316
1317 // Add crossbar
1318 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
1319 m_crossBarStart = start + crossBarDistance;
1320
1323 else
1325
1326 // Add second extension line (end to crossbar end)
1328 extension = VECTOR2I( 0, end.y - m_crossBarEnd.y );
1329 else
1330 extension = VECTOR2I( end.x - m_crossBarEnd.x, 0 );
1331
1332 extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
1333
1334 extStart = VECTOR2I( m_crossBarEnd );
1335 extStart -= extension.Resize( m_extensionHeight );
1336
1337 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
1338
1339 // Update text after calculating crossbar position but before adding crossbar lines
1340 updateText();
1341
1342 // Now that we have the text updated, we can determine how to draw the crossbar.
1343 // First we need to create an appropriate bounding polygon to collide with
1344 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() );
1345
1346 SHAPE_POLY_SET polyBox;
1347 polyBox.NewOutline();
1348 polyBox.Append( textBox.GetOrigin() );
1349 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1350 polyBox.Append( textBox.GetEnd() );
1351 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1352 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1353
1354 // The ideal crossbar, if the text doesn't collide
1355 SEG crossbar( m_crossBarStart, m_crossBarEnd );
1356
1357 CollectKnockedOutSegments( polyBox, crossbar, m_shapes );
1358
1359 EDA_ANGLE crossBarAngle( m_crossBarEnd - m_crossBarStart );
1360
1362 {
1363 // Arrows with fixed length.
1364 drawAnArrow( m_crossBarStart, crossBarAngle + EDA_ANGLE( 180 ),
1367 }
1368 else
1369 {
1370 drawAnArrow( m_crossBarStart, crossBarAngle, 0 );
1371 drawAnArrow( m_crossBarEnd, crossBarAngle + EDA_ANGLE( 180 ), 0 );
1372 }
1373
1374 m_busy = false;
1375}
1376
1377
1379{
1380 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
1381
1383 {
1384 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
1385
1386 VECTOR2I textOffset;
1387
1389 textOffset.y = -textOffsetDistance;
1390 else
1391 textOffset.x = -textOffsetDistance;
1392
1393 textOffset += crossbarCenter;
1394
1395 SetTextPos( m_crossBarStart + textOffset );
1396 }
1398 {
1399 SetTextPos( m_crossBarStart + crossbarCenter );
1400 }
1401
1402 if( m_keepTextAligned )
1403 {
1404 if( abs( crossbarCenter.x ) > abs( crossbarCenter.y ) )
1406 else
1408 }
1409
1411}
1412
1413
1414void PCB_DIM_ORTHOGONAL::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1415{
1416 EDA_ANGLE angle( aAngle );
1417
1418 // restrict angle to -179.9 to 180.0 degrees
1419 angle.Normalize180();
1420
1421 // adjust orientation and height to new angle
1422 // we can only handle the cases of -90, 0, 90, 180 degrees exactly;
1423 // in the other cases we will use the nearest 90 degree angle to
1424 // choose at least an approximate axis for the target orientation
1425 // In case of exactly 45 or 135 degrees, we will round towards zero for consistency
1426 if( angle > ANGLE_45 && angle <= ANGLE_135 )
1427 {
1428 // about 90 degree
1430 {
1432 }
1433 else
1434 {
1436 m_height = -m_height;
1437 }
1438 }
1439 else if( angle < -ANGLE_45 && angle >= -ANGLE_135 )
1440 {
1441 // about -90 degree
1443 {
1445 m_height = -m_height;
1446 }
1447 else
1448 {
1450 }
1451 }
1452 else if( angle > ANGLE_135 || angle < -ANGLE_135 )
1453 {
1454 // about 180 degree
1455 m_height = -m_height;
1456 }
1457
1458 // this will update m_crossBarStart and m_crossbarEnd
1459 PCB_DIMENSION_BASE::Rotate( aRotCentre, angle );
1460}
1461
1462
1473
1474
1476{
1477 wxCHECK( aOther && aOther->Type() == PCB_DIM_LEADER_T, /* void */ );
1478 *this = *static_cast<const PCB_DIM_LEADER*>( aOther );
1479}
1480
1481void PCB_DIM_LEADER::Serialize( google::protobuf::Any &aContainer ) const
1482{
1483 using namespace kiapi::common;
1484 kiapi::board::types::Dimension dimension;
1485
1486 PCB_DIMENSION_BASE::Serialize( aContainer );
1487 aContainer.UnpackTo( &dimension );
1488
1489 PackVector2( *dimension.mutable_leader()->mutable_start(), GetStart() );
1490 PackVector2( *dimension.mutable_leader()->mutable_end(), GetEnd() );
1491 dimension.mutable_leader()->set_border_style(
1493 m_textBorder ) );
1494
1495 aContainer.PackFrom( dimension );
1496}
1497
1498
1499bool PCB_DIM_LEADER::Deserialize( const google::protobuf::Any &aContainer )
1500{
1501 using namespace kiapi::common;
1502
1503 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1504 return false;
1505
1506 kiapi::board::types::Dimension dimension;
1507 aContainer.UnpackTo( &dimension );
1508
1509 if( !dimension.has_leader() )
1510 return false;
1511
1512 SetStart( UnpackVector2( dimension.leader().start() ) );
1513 SetEnd( UnpackVector2( dimension.leader().end() ) );
1514 SetTextBorder( FromProtoEnum<DIM_TEXT_BORDER>( dimension.leader().border_style() ) );
1515
1516 Update();
1517
1518 return true;
1519}
1520
1521
1523{
1524 return new PCB_DIM_LEADER( *this );
1525}
1526
1527
1529{
1530 wxASSERT( aImage->Type() == Type() );
1531
1532 m_shapes.clear();
1533 static_cast<PCB_DIM_LEADER*>( aImage )->m_shapes.clear();
1534
1535 std::swap( *static_cast<PCB_DIM_LEADER*>( this ), *static_cast<PCB_DIM_LEADER*>( aImage ) );
1536
1537 Update();
1538}
1539
1540
1545
1546
1548{
1549 // Our geometry is dependent on the size of the text, so just update the whole shebang
1551}
1552
1553
1555{
1556 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1557 return;
1558
1559 m_busy = true;
1560
1561 m_shapes.clear();
1562
1564
1565 // Now that we have the text updated, we can determine how to draw the second line
1566 // First we need to create an appropriate bounding polygon to collide with
1567 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() * 2 );
1568
1569 SHAPE_POLY_SET polyBox;
1570 polyBox.NewOutline();
1571 polyBox.Append( textBox.GetOrigin() );
1572 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1573 polyBox.Append( textBox.GetEnd() );
1574 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1575 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1576
1577 const VECTOR2I boardStart = GetStart();
1578 const VECTOR2I boardEnd = GetEnd();
1579
1580 VECTOR2I firstLine( boardEnd - boardStart );
1581 VECTOR2I start( boardStart );
1582 start += firstLine.Resize( m_extensionOffset );
1583
1584 SEG arrowSeg( boardStart, boardEnd );
1585 SEG textSeg( boardEnd, GetTextPos() );
1586 OPT_VECTOR2I arrowSegEnd;
1587 OPT_VECTOR2I textSegEnd;
1588
1590 {
1591 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1592 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1593 CIRCLE circle( textBox.GetCenter(), radius );
1594
1595 arrowSegEnd = segCircleIntersection( circle, arrowSeg );
1596 textSegEnd = segCircleIntersection( circle, textSeg );
1597 }
1598 else
1599 {
1600 arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1601 textSegEnd = segPolyIntersection( polyBox, textSeg );
1602 }
1603
1604 if( !arrowSegEnd )
1605 arrowSegEnd = boardEnd;
1606
1607 m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
1608
1609 drawAnArrow( start, EDA_ANGLE( firstLine ), 0 );
1610
1611 if( !GetText().IsEmpty() )
1612 {
1613 switch( m_textBorder )
1614 {
1616 {
1617 for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
1618 m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
1619
1620 break;
1621 }
1622
1624 {
1625 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1626 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1627 m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
1628
1629 break;
1630 }
1631
1632 default:
1633 break;
1634 }
1635 }
1636
1637 if( textSegEnd && *arrowSegEnd == boardEnd )
1638 m_shapes.emplace_back( new SHAPE_SEGMENT( boardEnd, *textSegEnd ) );
1639
1640 m_busy = false;
1641}
1642
1643
1644void PCB_DIM_LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1645{
1646 // Don't use GetShownText(); we want to see the variable references here
1647 aList.emplace_back( _( "Leader" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
1648
1649 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
1650
1651 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
1652 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
1653 aFrame->MessageTextFromValue( startCoord.x ),
1654 aFrame->MessageTextFromValue( startCoord.y ) );
1655
1656 aList.emplace_back( start, wxEmptyString );
1657
1658 aList.emplace_back( _( "Layer" ), GetLayerName() );
1659}
1660
1661
1671
1673{
1674 wxCHECK( aOther && aOther->Type() == PCB_DIM_RADIAL_T, /* void */ );
1675 *this = *static_cast<const PCB_DIM_RADIAL*>( aOther );
1676}
1677
1678void PCB_DIM_RADIAL::Serialize( google::protobuf::Any &aContainer ) const
1679{
1680 using namespace kiapi::common;
1681 kiapi::board::types::Dimension dimension;
1682
1683 PCB_DIMENSION_BASE::Serialize( aContainer );
1684 aContainer.UnpackTo( &dimension );
1685
1686 PackVector2( *dimension.mutable_radial()->mutable_center(), GetStart() );
1687 PackVector2( *dimension.mutable_radial()->mutable_radius_point(), GetEnd() );
1688 dimension.mutable_radial()->mutable_leader_length()->set_value_nm( m_leaderLength );
1689
1690 aContainer.PackFrom( dimension );
1691}
1692
1693
1694bool PCB_DIM_RADIAL::Deserialize( const google::protobuf::Any &aContainer )
1695{
1696 using namespace kiapi::common;
1697
1698 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1699 return false;
1700
1701 kiapi::board::types::Dimension dimension;
1702 aContainer.UnpackTo( &dimension );
1703
1704 if( !dimension.has_radial() )
1705 return false;
1706
1707 SetStart( UnpackVector2( dimension.radial().center() ) );
1708 SetEnd( UnpackVector2( dimension.radial().radius_point() ) );
1709 SetLeaderLength( dimension.radial().leader_length().value_nm() );
1710
1711 Update();
1712
1713 return true;
1714}
1715
1716
1718{
1719 return new PCB_DIM_RADIAL( *this );
1720}
1721
1722
1724{
1725 wxASSERT( aImage->Type() == Type() );
1726
1727 m_shapes.clear();
1728 static_cast<PCB_DIM_RADIAL*>( aImage )->m_shapes.clear();
1729
1730 std::swap( *static_cast<PCB_DIM_RADIAL*>( this ), *static_cast<PCB_DIM_RADIAL*>( aImage ) );
1731
1732 Update();
1733}
1734
1735
1740
1741
1743{
1744 const VECTOR2I end = GetEnd();
1745 VECTOR2I radial( end - GetStart() );
1746
1747 return end + radial.Resize( m_leaderLength );
1748}
1749
1750
1752{
1753 if( m_keepTextAligned )
1754 {
1755 VECTOR2I textLine( GetTextPos() - GetKnee() );
1756 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( textLine );
1757
1758 textAngle.Normalize();
1759
1760 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1761 textAngle -= ANGLE_180;
1762
1763 // Round to nearest degree
1764 textAngle = EDA_ANGLE( KiROUND( textAngle.AsDegrees() ), DEGREES_T );
1765
1766 SetTextAngle( textAngle );
1767 }
1768
1770}
1771
1772
1774{
1775 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1776 return;
1777
1778 m_busy = true;
1779
1780 m_shapes.clear();
1781
1782 const VECTOR2I boardStart = GetStart();
1783 const VECTOR2I boardEnd = GetEnd();
1784
1785 VECTOR2I center( boardStart );
1786 VECTOR2I centerArm( 0, m_arrowLength );
1787
1788 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1789
1790 RotatePoint( centerArm, -ANGLE_90 );
1791
1792 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1793
1794 VECTOR2I radius( boardEnd - boardStart );
1795
1796 m_measuredValue = KiROUND( radius.EuclideanNorm() );
1797
1798 updateText();
1799
1800 // Now that we have the text updated, we can determine how to draw the second line
1801 // First we need to create an appropriate bounding polygon to collide with
1802 BOX2I textBox = GetTextBox( nullptr ).Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() );
1803
1804 SHAPE_POLY_SET polyBox;
1805 polyBox.NewOutline();
1806 polyBox.Append( textBox.GetOrigin() );
1807 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1808 polyBox.Append( textBox.GetEnd() );
1809 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1810 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1811
1812 VECTOR2I radial( boardEnd - boardStart );
1813 radial = radial.Resize( m_leaderLength );
1814
1815 SEG arrowSeg( boardEnd, boardEnd + radial );
1816 SEG textSeg( arrowSeg.B, GetTextPos() );
1817
1818 CollectKnockedOutSegments( polyBox, arrowSeg, m_shapes );
1819 CollectKnockedOutSegments( polyBox, textSeg, m_shapes );
1820
1821 drawAnArrow( boardEnd, EDA_ANGLE( radial ), 0 );
1822
1823 m_busy = false;
1824}
1825
1826
1833
1835{
1836 wxCHECK( aOther && aOther->Type() == PCB_DIM_CENTER_T, /* void */ );
1837 *this = *static_cast<const PCB_DIM_CENTER*>( aOther );
1838}
1839
1840void PCB_DIM_CENTER::Serialize( google::protobuf::Any &aContainer ) const
1841{
1842 using namespace kiapi::common;
1843 kiapi::board::types::Dimension dimension;
1844
1845 PCB_DIMENSION_BASE::Serialize( aContainer );
1846 aContainer.UnpackTo( &dimension );
1847
1848 PackVector2( *dimension.mutable_center()->mutable_center(), GetStart() );
1849 PackVector2( *dimension.mutable_center()->mutable_end(), GetEnd() );
1850
1851 aContainer.PackFrom( dimension );
1852}
1853
1854
1855bool PCB_DIM_CENTER::Deserialize( const google::protobuf::Any &aContainer )
1856{
1857 using namespace kiapi::common;
1858
1859 if( !PCB_DIMENSION_BASE::Deserialize( aContainer ) )
1860 return false;
1861
1862 kiapi::board::types::Dimension dimension;
1863 aContainer.UnpackTo( &dimension );
1864
1865 if( !dimension.has_center() )
1866 return false;
1867
1868 SetStart( UnpackVector2( dimension.center().center() ) );
1869 SetEnd( UnpackVector2( dimension.center().end() ) );
1870
1871 Update();
1872
1873 return true;
1874}
1875
1876
1878{
1879 return new PCB_DIM_CENTER( *this );
1880}
1881
1882
1884{
1885 wxASSERT( aImage->Type() == Type() );
1886
1887 std::swap( *static_cast<PCB_DIM_CENTER*>( this ), *static_cast<PCB_DIM_CENTER*>( aImage ) );
1888}
1889
1890
1895
1896
1898{
1899 BOX2I bBox;
1900 int xmin, xmax, ymin, ymax;
1901
1902 const VECTOR2I start = GetStart();
1903 xmin = start.x;
1904 xmax = start.x;
1905 ymin = start.y;
1906 ymax = start.y;
1907
1908 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
1909 {
1910 BOX2I shapeBox = shape->BBox();
1911 shapeBox.Inflate( m_lineThickness / 2 );
1912
1913 xmin = std::min( xmin, shapeBox.GetOrigin().x );
1914 xmax = std::max( xmax, shapeBox.GetEnd().x );
1915 ymin = std::min( ymin, shapeBox.GetOrigin().y );
1916 ymax = std::max( ymax, shapeBox.GetEnd().y );
1917 }
1918
1919 bBox.SetX( xmin );
1920 bBox.SetY( ymin );
1921 bBox.SetWidth( xmax - xmin + 1 );
1922 bBox.SetHeight( ymax - ymin + 1 );
1923
1924 bBox.Normalize();
1925
1926 return bBox;
1927}
1928
1929
1931{
1932 return GetBoundingBox();
1933}
1934
1935
1937{
1938 // Even if PCB_DIM_CENTER has no text, we still need to update its text position
1939 // so GetTextPos() users get a valid value. Required at least for lasso hit-testing.
1940 SetTextPos( GetStart() );
1941
1943}
1944
1945
1947{
1948 if( m_busy ) // Skeep reentrance that happens sometimes after calling updateText()
1949 return;
1950
1951 m_busy = true;
1952
1953 m_shapes.clear();
1954
1955 const VECTOR2I boardStart = GetStart();
1956 const VECTOR2I boardEnd = GetEnd();
1957 VECTOR2I center( boardStart );
1958 VECTOR2I arm( boardEnd - boardStart );
1959
1960 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1961
1962 RotatePoint( arm, -ANGLE_90 );
1963
1964 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1965
1966 updateText();
1967
1968 m_busy = false;
1969}
1970
1971
1972static struct DIMENSION_DESC
1973{
1975 {
1977 .Map( DIM_PRECISION::X, _HKI( "0" ) )
1978 .Map( DIM_PRECISION::X_X, _HKI( "0.0" ) )
1979 .Map( DIM_PRECISION::X_XX, _HKI( "0.00" ) )
1980 .Map( DIM_PRECISION::X_XXX, _HKI( "0.000" ) )
1981 .Map( DIM_PRECISION::X_XXXX, _HKI( "0.0000" ) )
1982 .Map( DIM_PRECISION::X_XXXXX, _HKI( "0.00000" ) )
1983 .Map( DIM_PRECISION::V_VV, _HKI( "0.00 in / 0 mils / 0.0 mm" ) )
1984 .Map( DIM_PRECISION::V_VVV, _HKI( "0.000 / 0 / 0.00" ) )
1985 .Map( DIM_PRECISION::V_VVVV, _HKI( "0.0000 / 0.0 / 0.000" ) )
1986 .Map( DIM_PRECISION::V_VVVVV, _HKI( "0.00000 / 0.00 / 0.0000" ) );
1987
1989 .Map( DIM_UNITS_FORMAT::NO_SUFFIX, _HKI( "1234.0" ) )
1990 .Map( DIM_UNITS_FORMAT::BARE_SUFFIX, _HKI( "1234.0 mm" ) )
1991 .Map( DIM_UNITS_FORMAT::PAREN_SUFFIX, _HKI( "1234.0 (mm)" ) );
1992
1994 .Map( DIM_UNITS_MODE::INCH, _HKI( "Inches" ) )
1995 .Map( DIM_UNITS_MODE::MILS, _HKI( "Mils" ) )
1996 .Map( DIM_UNITS_MODE::MM, _HKI( "Millimeters" ) )
1997 .Map( DIM_UNITS_MODE::AUTOMATIC, _HKI( "Automatic" ) );
1998
2000 .Map( DIM_ARROW_DIRECTION::INWARD, _HKI( "Inward" ) )
2001 .Map( DIM_ARROW_DIRECTION::OUTWARD, _HKI( "Outward" ) );
2002
2011
2012 propMgr.Mask( TYPE_HASH( PCB_DIMENSION_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
2013
2014 const wxString groupDimension = _HKI( "Dimension Properties" );
2015
2016 auto isLeader =
2017 []( INSPECTABLE* aItem ) -> bool
2018 {
2019 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) != nullptr;
2020 };
2021
2022 auto isNotLeader =
2023 []( INSPECTABLE* aItem ) -> bool
2024 {
2025 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) == nullptr;
2026 };
2027
2028 auto isMultiArrowDirection =
2029 []( INSPECTABLE* aItem ) -> bool
2030 {
2031 return dynamic_cast<PCB_DIM_ALIGNED*>( aItem ) != nullptr;
2032 };
2033
2036 groupDimension )
2037 .SetAvailableFunc( isNotLeader );
2040 groupDimension )
2041 .SetAvailableFunc( isNotLeader );
2042 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, wxString>( _HKI( "Override Text" ),
2044 groupDimension )
2045 .SetAvailableFunc( isNotLeader );
2046
2049 groupDimension )
2050 .SetAvailableFunc( isLeader );
2051
2054 groupDimension )
2055 .SetAvailableFunc( isNotLeader );
2058 groupDimension )
2059 .SetAvailableFunc( isNotLeader );
2062 groupDimension )
2063 .SetAvailableFunc( isNotLeader );
2064 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Suppress Trailing Zeroes" ),
2066 groupDimension )
2067 .SetAvailableFunc( isNotLeader );
2068
2071 groupDimension )
2072 .SetAvailableFunc( isMultiArrowDirection );
2073
2074 const wxString groupText = _HKI( "Text Properties" );
2075
2076 const auto isTextOrientationWriteable =
2077 []( INSPECTABLE* aItem ) -> bool
2078 {
2079 return !static_cast<PCB_DIMENSION_BASE*>( aItem )->GetKeepTextAligned();
2080 };
2081
2082 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Keep Aligned with Dimension" ),
2085 groupText );
2086
2087 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, double>( _HKI( "Orientation" ),
2091 groupText )
2092 .SetWriteableFunc( isTextOrientationWriteable );
2093 }
2095
2100
2101
2103{
2105 {
2116
2117 const wxString groupDimension = _HKI( "Dimension Properties" );
2118
2119 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Crossbar Height" ),
2122 groupDimension );
2123 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Extension Line Overshoot" ),
2126 groupDimension );
2127
2129 _HKI( "Text" ),
2130 []( INSPECTABLE* aItem ) { return false; } );
2132 _HKI( "Vertical Justification" ),
2133 []( INSPECTABLE* aItem ) { return false; } );
2135 _HKI( "Hyperlink" ),
2136 []( INSPECTABLE* aItem ) { return false; } );
2138 _HKI( "Knockout" ),
2139 []( INSPECTABLE* aItem ) { return false; } );
2140 }
2142
2143
2145{
2147 {
2160
2162 _HKI( "Text" ),
2163 []( INSPECTABLE* aItem ) { return false; } );
2165 _HKI( "Vertical Justification" ),
2166 []( INSPECTABLE* aItem ) { return false; } );
2168 _HKI( "Hyperlink" ),
2169 []( INSPECTABLE* aItem ) { return false; } );
2171 _HKI( "Knockout" ),
2172 []( INSPECTABLE* aItem ) { return false; } );
2173 }
2175
2176
2178{
2180 {
2191
2192 const wxString groupDimension = _HKI( "Dimension Properties" );
2193
2194 propMgr.AddProperty( new PROPERTY<PCB_DIM_RADIAL, int>( _HKI( "Leader Length" ),
2197 groupDimension );
2198
2200 _HKI( "Text" ),
2201 []( INSPECTABLE* aItem ) { return false; } );
2203 _HKI( "Vertical Justification" ),
2204 []( INSPECTABLE* aItem ) { return false; } );
2206 _HKI( "Hyperlink" ),
2207 []( INSPECTABLE* aItem ) { return false; } );
2209 _HKI( "Knockout" ),
2210 []( INSPECTABLE* aItem ) { return false; } );
2211 }
2213
2214
2216{
2218 {
2220 .Map( DIM_TEXT_BORDER::NONE, _HKI( "None" ) )
2221 .Map( DIM_TEXT_BORDER::RECTANGLE, _HKI( "Rectangle" ) )
2222 .Map( DIM_TEXT_BORDER::CIRCLE, _HKI( "Circle" ) );
2223
2234
2235 const wxString groupDimension = _HKI( "Dimension Properties" );
2236
2239 groupDimension );
2240
2242 _HKI( "Text" ),
2243 []( INSPECTABLE* aItem ) { return false; } );
2245 _HKI( "Vertical Justification" ),
2246 []( INSPECTABLE* aItem ) { return false; } );
2248 _HKI( "Hyperlink" ),
2249 []( INSPECTABLE* aItem ) { return false; } );
2251 _HKI( "Knockout" ),
2252 []( INSPECTABLE* aItem ) { return false; } );
2253 }
2255
2257
2258
2260{
2262 {
2273
2274
2276 _HKI( "Text" ),
2277 []( INSPECTABLE* aItem ) { return false; } );
2279 _HKI( "Vertical Justification" ),
2280 []( INSPECTABLE* aItem ) { return false; } );
2282 _HKI( "Hyperlink" ),
2283 []( INSPECTABLE* aItem ) { return false; } );
2285 _HKI( "Knockout" ),
2286 []( INSPECTABLE* aItem ) { return false; } );
2287 }
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:47
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:918
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
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:81
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:83
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:265
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
Definition board_item.h:356
PCB_LAYER_ID m_layer
Definition board_item.h:508
bool IsLocked() const override
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:313
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:901
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:554
constexpr void SetHeight(size_type val)
Definition box2.h:288
constexpr const Vec GetEnd() const
Definition box2.h:208
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:142
constexpr coord_type GetY() const
Definition box2.h:204
constexpr size_type GetWidth() const
Definition box2.h:210
constexpr coord_type GetX() const
Definition box2.h:203
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:654
constexpr const Vec GetCenter() const
Definition box2.h:226
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:164
constexpr void SetWidth(size_type val)
Definition box2.h:283
constexpr void SetX(coord_type val)
Definition box2.h:273
constexpr const Vec & GetOrigin() const
Definition box2.h:206
constexpr void SetY(coord_type val)
Definition box2.h:278
constexpr coord_type GetRight() const
Definition box2.h:213
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:307
constexpr coord_type GetBottom() const
Definition box2.h:218
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:96
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:543
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:89
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:294
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:110
virtual void SetTextPos(const VECTOR2I &aPoint)
Definition eda_text.cpp:576
virtual int GetTextHeight() const
Definition eda_text.h:288
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition eda_text.cpp:208
KIFONT::FONT * GetFont() const
Definition eda_text.h:268
void SetMirrored(bool isMirrored)
Definition eda_text.cpp:388
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:773
virtual int GetTextWidth() const
Definition eda_text.h:285
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:695
double Similarity(const EDA_TEXT &aOther) const
virtual void ClearRenderCache()
Definition eda_text.cpp:689
bool IsMirrored() const
Definition eda_text.h:211
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:461
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:171
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:265
bool operator==(const EDA_TEXT &aRhs) const
Definition eda_text.h:419
static ENUM_MAP< T > & Instance()
Definition property.h:721
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:38
Definition kiid.h:44
A class to perform either relative or absolute display origin transforms for a single axis of a point...
T ToDisplayAbs(const T &aValue) 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)
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
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)
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
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_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
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)
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.
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
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:354
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition pcb_text.cpp:225
EDA_ANGLE GetTextAngle() const override
Definition pcb_text.cpp:543
void Offset(const VECTOR2I &aOffset) override
Definition pcb_text.cpp:508
void SetLibTextAngle(const EDA_ANGLE &aAngle)
Definition pcb_text.h:121
wxString GetShownText(bool aAllowExtraText, int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition pcb_text.cpp:161
VECTOR2I GetTextPos() const override
Definition pcb_text.cpp:444
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:597
bool TextHitTest(const VECTOR2I &aPoint, int aAccuracy=0) const override
Test if aPoint is within the bounds of this object.
Definition pcb_text.cpp:409
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:120
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition pcb_text.cpp:677
int GetTextThickness() const override
Definition pcb_text.cpp:480
void SetTextAngle(const EDA_ANGLE &aAngle) override
Definition pcb_text.cpp:552
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:262
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition property.h:287
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
A type-safe container of any type.
Definition ki_any.h:92
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.
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition eda_angle.h:408
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition eda_angle.h:407
static constexpr EDA_ANGLE ANGLE_45
Definition eda_angle.h:412
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
static constexpr EDA_ANGLE FULL_CIRCLE
Definition eda_angle.h:409
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
static constexpr EDA_ANGLE ANGLE_135
Definition eda_angle.h:414
#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:173
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:180
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 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 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)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#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:828
@ 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< 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:71
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:99
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:96
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:97
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:95
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:98
constexpr int sign(T val)
Definition util.h:141
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682