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 (C) 1992-2023 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, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28#include <bitmaps.h>
29#include <pcb_edit_frame.h>
30#include <base_units.h>
32#include <font/font.h>
33#include <board.h>
34#include <pcb_dimension.h>
35#include <pcb_text.h>
41#include <trigo.h>
42
44
45static const EDA_ANGLE s_arrowAngle( 27.5, DEGREES_T );
46
47
56static OPT_VECTOR2I segPolyIntersection( const SHAPE_POLY_SET& aPoly, const SEG& aSeg,
57 bool aStart = true )
58{
59 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
60 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
61
62 if( aPoly.Contains( start ) )
63 return std::nullopt;
64
65 for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
66 {
67 if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
68 {
69 if( ( *intersection - start ).SquaredEuclideanNorm()
70 < ( endpoint - start ).SquaredEuclideanNorm() )
71 endpoint = *intersection;
72 }
73 }
74
75 if( start == endpoint )
76 return std::nullopt;
77
78 return OPT_VECTOR2I( endpoint );
79}
80
81
82static OPT_VECTOR2I segCircleIntersection( CIRCLE& aCircle, SEG& aSeg, bool aStart = true )
83{
84 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
85 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
86
87 if( aCircle.Contains( start ) )
88 return std::nullopt;
89
90 std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
91
92 for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
93 {
94 if( ( intersection - start ).SquaredEuclideanNorm()
95 < ( endpoint - start ).SquaredEuclideanNorm() )
96 endpoint = intersection;
97 }
98
99 if( start == endpoint )
100 return std::nullopt;
101
102 return OPT_VECTOR2I( endpoint );
103}
104
105
110static void CollectKnockedOutSegments( const SHAPE_POLY_SET& aPoly, const SEG& aSeg,
111 std::vector<std::shared_ptr<SHAPE>>& aSegmentsAfterKnockout )
112{
113 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
114 const bool containsA = aPoly.Contains( aSeg.A );
115 const bool containsB = aPoly.Contains( aSeg.B );
116
117 const OPT_VECTOR2I endpointA = segPolyIntersection( aPoly, aSeg );
118 const OPT_VECTOR2I endpointB = segPolyIntersection( aPoly, aSeg, false );
119
120 if( endpointA )
121 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( aSeg.A, *endpointA ) );
122
123 if( endpointB )
124 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( *endpointB, aSeg.B ) );
125
126 if( !containsA && !containsB && !endpointA && !endpointB )
127 aSegmentsAfterKnockout.emplace_back( new SHAPE_SEGMENT( aSeg ) );
128}
129
130
132 PCB_TEXT( aParent, aType ),
133 m_overrideTextEnabled( false ),
134 m_units( EDA_UNITS::INCHES ),
135 m_autoUnits( false ),
136 m_unitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX ),
137 m_arrowDirection( DIM_ARROW_DIRECTION::OUTWARD ),
138 m_precision( DIM_PRECISION::X_XXXX ),
139 m_suppressZeroes( false ),
140 m_lineThickness( pcbIUScale.mmToIU( 0.2 ) ),
141 m_arrowLength( pcbIUScale.MilsToIU( 50 ) ),
142 m_extensionOffset( 0 ),
143 m_textPosition( DIM_TEXT_POSITION::OUTSIDE ),
144 m_keepTextAligned( true ),
145 m_measuredValue( 0 ),
146 m_inClearRenderCache( false )
147{
149}
150
151
153{
154 if( Type() != aOther.Type() )
155 return false;
156
157 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
158
159 return *this == other;
160}
161
162
164{
165 if( m_textPosition != aOther.m_textPosition )
166 return false;
167
169 return false;
170
171 if( m_units != aOther.m_units )
172 return false;
173
174 if( m_autoUnits != aOther.m_autoUnits )
175 return false;
176
177 if( m_unitsFormat != aOther.m_unitsFormat )
178 return false;
179
180 if( m_precision != aOther.m_precision )
181 return false;
182
183 if( m_suppressZeroes != aOther.m_suppressZeroes )
184 return false;
185
186 if( m_lineThickness != aOther.m_lineThickness )
187 return false;
188
189 if( m_arrowLength != aOther.m_arrowLength )
190 return false;
191
193 return false;
194
195 if( m_measuredValue != aOther.m_measuredValue )
196 return false;
197
198 return EDA_TEXT::operator==( aOther );
199}
200
201
202double PCB_DIMENSION_BASE::Similarity( const BOARD_ITEM& aOther ) const
203{
204 if( m_Uuid == aOther.m_Uuid )
205 return 1.0;
206
207 if( Type() != aOther.Type() )
208 return 0.0;
209
210 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
211
212 double similarity = 1.0;
213
214 if( m_textPosition != other.m_textPosition )
215 similarity *= 0.9;
216
218 similarity *= 0.9;
219
220 if( m_units != other.m_units )
221 similarity *= 0.9;
222
223 if( m_autoUnits != other.m_autoUnits )
224 similarity *= 0.9;
225
226 if( m_unitsFormat != other.m_unitsFormat )
227 similarity *= 0.9;
228
229 if( m_precision != other.m_precision )
230 similarity *= 0.9;
231
233 similarity *= 0.9;
234
235 if( m_lineThickness != other.m_lineThickness )
236 similarity *= 0.9;
237
238 if( m_arrowLength != other.m_arrowLength )
239 similarity *= 0.9;
240
242 similarity *= 0.9;
243
244 if( m_measuredValue != other.m_measuredValue )
245 similarity *= 0.9;
246
247 similarity *= EDA_TEXT::Similarity( other );
248
249 return similarity;
250}
251
252
253void PCB_DIMENSION_BASE::drawAnArrow( VECTOR2I startPoint, EDA_ANGLE anAngle, int aLength )
254{
255 if( aLength )
256 {
257 VECTOR2I tailEnd( aLength, 0 );
258 RotatePoint( tailEnd, -anAngle );
259 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + tailEnd ) );
260 }
261
262 VECTOR2I arrowEndPos( m_arrowLength, 0 );
263 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
264
265 RotatePoint( arrowEndPos, -anAngle + s_arrowAngle );
266 RotatePoint( arrowEndNeg, -anAngle - s_arrowAngle );
267
268 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + arrowEndPos ) );
269 m_shapes.emplace_back( new SHAPE_SEGMENT( startPoint, startPoint + arrowEndNeg ) );
270}
271
272
274{
276
277 switch( m_unitsFormat )
278 {
279 case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
280 break;
281
282 case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
284 break;
285
286 case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
287 text += wxT( " (" ) + EDA_UNIT_UTILS::GetText( m_units ).Trim( false ) + wxT( ")" );
288 break;
289 }
290
291 text.Prepend( m_prefix );
292 text.Append( m_suffix );
293
294 SetText( text );
295}
296
297
299{
301
302 // We use EDA_TEXT::ClearRenderCache() as a signal that the properties of the EDA_TEXT
303 // have changed and we may need to update the dimension text
304
306 {
308 Update();
309 m_inClearRenderCache = false;
310 }
311}
312
313
314template<typename ShapeType>
315void PCB_DIMENSION_BASE::addShape( const ShapeType& aShape )
316{
317 m_shapes.push_back( std::make_shared<ShapeType>( aShape ) );
318}
319
320
322{
323 struct lconv* lc = localeconv();
324 wxChar sep = lc->decimal_point[0];
325
326 int val = GetMeasuredValue();
327 int precision = static_cast<int>( m_precision );
328 wxString text;
329
330 if( precision >= 6 )
331 {
332 switch( m_units )
333 {
334 case EDA_UNITS::INCHES: precision = precision - 4; break;
335 case EDA_UNITS::MILS: precision = std::max( 0, precision - 7 ); break;
336 case EDA_UNITS::MILLIMETRES: precision = precision - 5; break;
337 default: precision = precision - 4; break;
338 }
339 }
340
341 wxString format = wxT( "%." ) + wxString::Format( wxT( "%i" ), precision ) + wxT( "f" );
342
343 text.Printf( format, EDA_UNIT_UTILS::UI::ToUserUnit( pcbIUScale, m_units, val ) );
344
345 if( m_suppressZeroes )
346 {
347 while( text.Last() == '0' )
348 {
349 text.RemoveLast();
350
351 if( text.Last() == '.' || text.Last() == sep )
352 {
353 text.RemoveLast();
354 break;
355 }
356 }
357 }
358
359 return text;
360}
361
362
363void PCB_DIMENSION_BASE::SetPrefix( const wxString& aPrefix )
364{
365 m_prefix = aPrefix;
366}
367
368
369void PCB_DIMENSION_BASE::SetSuffix( const wxString& aSuffix )
370{
371 m_suffix = aSuffix;
372}
373
374
376{
377 m_units = aUnits;
378}
379
380
382{
383 if( m_autoUnits )
384 {
385 return DIM_UNITS_MODE::AUTOMATIC;
386 }
387 else
388 {
389 switch( m_units )
390 {
391 default:
392 case EDA_UNITS::INCHES: return DIM_UNITS_MODE::INCHES;
393 case EDA_UNITS::MILLIMETRES: return DIM_UNITS_MODE::MILLIMETRES;
394 case EDA_UNITS::MILS: return DIM_UNITS_MODE::MILS;
395 }
396 }
397}
398
399
401{
402 switch( aMode )
403 {
404 case DIM_UNITS_MODE::INCHES:
405 m_autoUnits = false;
406 m_units = EDA_UNITS::INCHES;
407 break;
408
409 case DIM_UNITS_MODE::MILS:
410 m_autoUnits = false;
411 m_units = EDA_UNITS::MILS;
412 break;
413
414 case DIM_UNITS_MODE::MILLIMETRES:
415 m_autoUnits = false;
416 m_units = EDA_UNITS::MILLIMETRES;
417 break;
418
419 case DIM_UNITS_MODE::AUTOMATIC:
420 m_autoUnits = true;
421 m_units = GetBoard() ? GetBoard()->GetUserUnits() : EDA_UNITS::MILLIMETRES;
422 break;
423 }
424}
425
426
428{
429 SetTextAngleDegrees( aDegrees );
430 // Create or repair any knockouts
431 Update();
432}
433
434
436{
437 SetKeepTextAligned( aKeepAligned );
438 // Re-align the text and repair any knockouts
439 Update();
440}
441
442
444{
445 PCB_TEXT::Offset( offset );
446
447 m_start += offset;
448 m_end += offset;
449
450 Update();
451}
452
453
454void PCB_DIMENSION_BASE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
455{
456 EDA_ANGLE newAngle = GetTextAngle() + aAngle;
457
458 newAngle.Normalize();
459
460 SetTextAngle( newAngle );
461
462 VECTOR2I pt = GetTextPos();
463 RotatePoint( pt, aRotCentre, aAngle );
464 SetTextPos( pt );
465
466 RotatePoint( m_start, aRotCentre, aAngle );
467 RotatePoint( m_end, aRotCentre, aAngle );
468
469 Update();
470}
471
472
473void PCB_DIMENSION_BASE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
474{
475 Mirror( aCentre, aFlipDirection );
476
478}
479
480
481void PCB_DIMENSION_BASE::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
482{
483 VECTOR2I newPos = GetTextPos();
484
485 MIRROR( newPos, axis_pos, aFlipDirection );
486
487 SetTextPos( newPos );
488
489 // invert angle
491
492 MIRROR( m_start, axis_pos, aFlipDirection );
493 MIRROR( m_end, axis_pos, aFlipDirection );
494
495 if( IsSideSpecific() )
497
498 Update();
499}
500
501
503 std::vector<MSG_PANEL_ITEM>& aList )
504{
505 // for now, display only the text within the DIMENSION using class PCB_TEXT.
506 wxString msg;
507
508 wxCHECK_RET( m_parent != nullptr, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
509
510 // Don't use GetShownText(); we want to see the variable references here
511 aList.emplace_back( _( "Dimension" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
512
513 aList.emplace_back( _( "Prefix" ), GetPrefix() );
514
516 {
517 aList.emplace_back( _( "Override Text" ), GetOverrideText() );
518 }
519 else
520 {
521 aList.emplace_back( _( "Value" ), GetValueText() );
522
523 switch( GetPrecision() )
524 {
525 case DIM_PRECISION::V_VV: msg = wxT( "0.00 in / 0 mils / 0.0 mm" ); break;
526 case DIM_PRECISION::V_VVV: msg = wxT( "0.000 in / 0 mils / 0.00 mm" ); break;
527 case DIM_PRECISION::V_VVVV: msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" ); break;
528 case DIM_PRECISION::V_VVVVV: msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
529 default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
530 }
531
532 aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
533 }
534
535 aList.emplace_back( _( "Suffix" ), GetSuffix() );
536
537 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
538 // in frame's units.
539 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
540 unitsProvider.SetUserUnits( GetUnits() );
541
542 aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( GetUnits() ) );
543
544 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
545 aList.emplace_back( _( "Text Thickness" ), unitsProvider.MessageTextFromValue( GetTextThickness() ) );
546 aList.emplace_back( _( "Text Width" ), unitsProvider.MessageTextFromValue( GetTextWidth() ) );
547 aList.emplace_back( _( "Text Height" ), unitsProvider.MessageTextFromValue( GetTextHeight() ) );
548
549 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
550
551 if( Type() == PCB_DIM_CENTER_T )
552 {
553 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
554 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
555 aFrame->MessageTextFromValue( startCoord.x ),
556 aFrame->MessageTextFromValue( startCoord.y ) );
557
558 aList.emplace_back( start, wxEmptyString );
559 }
560 else
561 {
562 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
563 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
564 aFrame->MessageTextFromValue( startCoord.x ),
565 aFrame->MessageTextFromValue( startCoord.y ) );
566 VECTOR2I endCoord = originTransforms.ToDisplayAbs( GetEnd() );
567 wxString end = wxString::Format( wxT( "@(%s, %s)" ),
568 aFrame->MessageTextFromValue( endCoord.x ),
569 aFrame->MessageTextFromValue( endCoord.y ) );
570
571 aList.emplace_back( start, end );
572 }
573
574 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
575 aList.emplace_back( _( "Status" ), _( "Locked" ) );
576
577 aList.emplace_back( _( "Layer" ), GetLayerName() );
578}
579
580
581std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
582{
583 std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
584
585 effectiveShape->AddShape( GetEffectiveTextShape()->Clone() );
586
587 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
588 effectiveShape->AddShape( shape->Clone() );
589
590 return effectiveShape;
591}
592
593
594bool PCB_DIMENSION_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
595{
596 if( TextHitTest( aPosition ) )
597 return true;
598
599 int dist_max = aAccuracy + ( m_lineThickness / 2 );
600
601 // Locate SEGMENTS
602
603 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
604 {
605 if( shape->Collide( aPosition, dist_max ) )
606 return true;
607 }
608
609 return false;
610}
611
612
613bool PCB_DIMENSION_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
614{
615 BOX2I arect = aRect;
616 arect.Inflate( aAccuracy );
617
618 BOX2I rect = GetBoundingBox();
619
620 if( aAccuracy )
621 rect.Inflate( aAccuracy );
622
623 if( aContained )
624 return arect.Contains( rect );
625
626 return arect.Intersects( rect );
627}
628
629
631{
632 BOX2I bBox;
633 int xmin, xmax, ymin, ymax;
634
635 bBox = GetTextBox();
636 xmin = bBox.GetX();
637 xmax = bBox.GetRight();
638 ymin = bBox.GetY();
639 ymax = bBox.GetBottom();
640
641 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
642 {
643 BOX2I shapeBox = shape->BBox();
644 shapeBox.Inflate( m_lineThickness / 2 );
645
646 xmin = std::min( xmin, shapeBox.GetOrigin().x );
647 xmax = std::max( xmax, shapeBox.GetEnd().x );
648 ymin = std::min( ymin, shapeBox.GetOrigin().y );
649 ymax = std::max( ymax, shapeBox.GetEnd().y );
650 }
651
652 bBox.SetX( xmin );
653 bBox.SetY( ymin );
654 bBox.SetWidth( xmax - xmin + 1 );
655 bBox.SetHeight( ymax - ymin + 1 );
656
657 bBox.Normalize();
658
659 return bBox;
660}
661
662
663wxString PCB_DIMENSION_BASE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
664{
665 return wxString::Format( _( "Dimension '%s' on %s" ),
666 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ),
667 GetLayerName() );
668}
669
670
671
673{
675 VECTOR2I( GetBoundingBox().GetSize() ) );
676 dimBBox.Merge( PCB_TEXT::ViewBBox() );
677
678 return dimBBox;
679}
680
681
683 int aClearance, int aError, ERROR_LOC aErrorLoc,
684 bool aIgnoreLineWidth ) const
685{
686 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
687
688 for( const std::shared_ptr<SHAPE>& shape : m_shapes )
689 {
690 const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
691 const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
692
693 if( circle )
694 {
695 TransformCircleToPolygon( aBuffer, circle->GetCenter(),
696 circle->GetRadius() + m_lineThickness / 2 + aClearance,
697 aError, aErrorLoc );
698 }
699 else if( seg )
700 {
701 TransformOvalToPolygon( aBuffer, seg->GetSeg().A, seg->GetSeg().B,
702 m_lineThickness + 2 * aClearance, aError, aErrorLoc );
703 }
704 else
705 {
706 wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeToPolygon unknown shape type." ) );
707 }
708 }
709}
710
711
713 PCB_DIMENSION_BASE( aParent, aType ),
714 m_height( 0 )
715{
716 // To preserve look of old dimensions, initialize extension height based on default arrow length
717 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
718}
719
720
722{
723 return new PCB_DIM_ALIGNED( *this );
724}
725
726
728{
729 wxASSERT( aImage->Type() == Type() );
730
731 m_shapes.clear();
732 static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
733
734 std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
735
736 Update();
737}
738
739
740void PCB_DIM_ALIGNED::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
741{
743 // Call this last for the Update()
744 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
745}
746
747
749{
750 return BITMAPS::add_aligned_dimension;
751}
752
753
754void PCB_DIM_ALIGNED::UpdateHeight( const VECTOR2I& aCrossbarStart, const VECTOR2I& aCrossbarEnd )
755{
756 VECTOR2D height( aCrossbarStart - GetStart() );
757 VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
758
759 if( height.Cross( crossBar ) > 0 )
760 m_height = -height.EuclideanNorm();
761 else
762 m_height = height.EuclideanNorm();
763
764 Update();
765}
766
767
769{
770 m_shapes.clear();
771
772 VECTOR2I dimension( m_end - m_start );
773
774 m_measuredValue = KiROUND( dimension.EuclideanNorm() );
775
776 VECTOR2I extension;
777
778 if( m_height > 0 )
779 extension = VECTOR2I( -dimension.y, dimension.x );
780 else
781 extension = VECTOR2I( dimension.y, -dimension.x );
782
783 // Add extension lines
784 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
785
786 VECTOR2I extStart( m_start );
787 extStart += extension.Resize( m_extensionOffset );
788
789 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
790
791 extStart = VECTOR2I( m_end );
792 extStart += extension.Resize( m_extensionOffset );
793
794 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
795
796 // Add crossbar
797 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
798 m_crossBarStart = m_start + crossBarDistance;
799 m_crossBarEnd = m_end + crossBarDistance;
800
801 // Update text after calculating crossbar position but before adding crossbar lines
802 updateText();
803
804 // Now that we have the text updated, we can determine how to draw the crossbar.
805 // First we need to create an appropriate bounding polygon to collide with
807
808 SHAPE_POLY_SET polyBox;
809 polyBox.NewOutline();
810 polyBox.Append( textBox.GetOrigin() );
811 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
812 polyBox.Append( textBox.GetEnd() );
813 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
814 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
815
816 // The ideal crossbar, if the text doesn't collide
817 SEG crossbar( m_crossBarStart, m_crossBarEnd );
818
819 CollectKnockedOutSegments( polyBox, crossbar, m_shapes );
820
821 if( m_arrowDirection == DIM_ARROW_DIRECTION::INWARD )
822 {
823 drawAnArrow( m_crossBarStart, EDA_ANGLE( dimension ) + EDA_ANGLE( 180 ),
825 drawAnArrow( m_crossBarEnd, EDA_ANGLE( dimension ),
827 }
828 else
829 {
830 drawAnArrow( m_crossBarStart, EDA_ANGLE( dimension ), 0 );
831 drawAnArrow( m_crossBarEnd, EDA_ANGLE( dimension ) + EDA_ANGLE( 180 ), 0 );
832 }
833}
834
835
837{
838 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
839
840 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
841 {
842 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
843 EDA_ANGLE rotation;
844
845 if( crossbarCenter.x == 0 )
846 rotation = ANGLE_90 * sign( -crossbarCenter.y );
847 else if( crossbarCenter.x < 0 )
848 rotation = -ANGLE_90;
849 else
850 rotation = ANGLE_90;
851
852 VECTOR2I textOffset = crossbarCenter;
853 RotatePoint( textOffset, rotation );
854 textOffset = crossbarCenter + textOffset.Resize( textOffsetDistance );
855
856 SetTextPos( m_crossBarStart + textOffset );
857 }
858 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
859 {
860 SetTextPos( m_crossBarStart + crossbarCenter );
861 }
862
864 {
865 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( crossbarCenter );
866 textAngle.Normalize();
867
868 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
869 textAngle -= ANGLE_180;
870
871 SetTextAngle( textAngle );
872 }
873
875}
876
877
878void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
879{
881
882 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
883 // in frame's units.
884 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
885 unitsProvider.SetUserUnits( GetUnits() );
886
887 aList.emplace_back( _( "Height" ), unitsProvider.MessageTextFromValue( m_height ) );
888}
889
890
893{
894 // To preserve look of old dimensions, initialize extension height based on default arrow length
895 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
897}
898
899
901{
902 return new PCB_DIM_ORTHOGONAL( *this );
903}
904
905
907{
908 wxASSERT( aImage->Type() == Type() );
909
910 m_shapes.clear();
911 static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
912
913 std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
914 *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
915
916 Update();
917}
918
919
920void PCB_DIM_ORTHOGONAL::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
921{
922 // Only reverse the height if the height is aligned with the flip
923 if( m_orientation == DIR::HORIZONTAL && aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
925 else if( m_orientation == DIR::VERTICAL && aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
927
928 // Call this last, as we need the Update()
929 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
930}
931
932
934{
935 return BITMAPS::add_orthogonal_dimension;
936}
937
938
940{
941 m_shapes.clear();
942
944 m_end.y - m_start.y );
946
947 VECTOR2I extension;
948
950 extension = VECTOR2I( 0, m_height );
951 else
952 extension = VECTOR2I( m_height, 0 );
953
954 // Add first extension line
955 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
956
957 VECTOR2I extStart( m_start );
958 extStart += extension.Resize( m_extensionOffset );
959
960 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
961
962 // Add crossbar
963 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
964 m_crossBarStart = m_start + crossBarDistance;
965
968 else
970
971 // Add second extension line (m_end to crossbar end)
973 extension = VECTOR2I( 0, m_end.y - m_crossBarEnd.y );
974 else
975 extension = VECTOR2I( m_end.x - m_crossBarEnd.x, 0 );
976
977 extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
978
979 extStart = VECTOR2I( m_crossBarEnd );
980 extStart -= extension.Resize( m_extensionHeight );
981
982 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
983
984 // Update text after calculating crossbar position but before adding crossbar lines
985 updateText();
986
987 // Now that we have the text updated, we can determine how to draw the crossbar.
988 // First we need to create an appropriate bounding polygon to collide with
990
991 SHAPE_POLY_SET polyBox;
992 polyBox.NewOutline();
993 polyBox.Append( textBox.GetOrigin() );
994 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
995 polyBox.Append( textBox.GetEnd() );
996 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
997 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
998
999 // The ideal crossbar, if the text doesn't collide
1000 SEG crossbar( m_crossBarStart, m_crossBarEnd );
1001
1002 CollectKnockedOutSegments( polyBox, crossbar, m_shapes );
1003
1004 EDA_ANGLE crossBarAngle( m_crossBarEnd - m_crossBarStart );
1005
1006 if( m_arrowDirection == DIM_ARROW_DIRECTION::INWARD )
1007 {
1008 // Arrows with fixed length.
1009 drawAnArrow( m_crossBarStart, crossBarAngle + EDA_ANGLE( 180 ),
1012 }
1013 else
1014 {
1015 drawAnArrow( m_crossBarStart, crossBarAngle, 0 );
1016 drawAnArrow( m_crossBarEnd, crossBarAngle + EDA_ANGLE( 180 ), 0 );
1017 }
1018}
1019
1020
1022{
1023 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
1024
1025 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
1026 {
1027 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
1028
1029 VECTOR2I textOffset;
1030
1032 textOffset.y = -textOffsetDistance;
1033 else
1034 textOffset.x = -textOffsetDistance;
1035
1036 textOffset += crossbarCenter;
1037
1038 SetTextPos( m_crossBarStart + textOffset );
1039 }
1040 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
1041 {
1042 SetTextPos( m_crossBarStart + crossbarCenter );
1043 }
1044
1045 if( m_keepTextAligned )
1046 {
1047 if( abs( crossbarCenter.x ) > abs( crossbarCenter.y ) )
1049 else
1051 }
1052
1054}
1055
1056
1057void PCB_DIM_ORTHOGONAL::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1058{
1059 EDA_ANGLE angle( aAngle );
1060
1061 // restrict angle to -179.9 to 180.0 degrees
1062 angle.Normalize180();
1063
1064 // adjust orientation and height to new angle
1065 // we can only handle the cases of -90, 0, 90, 180 degrees exactly;
1066 // in the other cases we will use the nearest 90 degree angle to
1067 // choose at least an approximate axis for the target orientation
1068 // In case of exactly 45 or 135 degrees, we will round towards zero for consistency
1069 if( angle > ANGLE_45 && angle <= ANGLE_135 )
1070 {
1071 // about 90 degree
1073 {
1075 }
1076 else
1077 {
1079 m_height = -m_height;
1080 }
1081 }
1082 else if( angle < -ANGLE_45 && angle >= -ANGLE_135 )
1083 {
1084 // about -90 degree
1086 {
1088 m_height = -m_height;
1089 }
1090 else
1091 {
1093 }
1094 }
1095 else if( angle > ANGLE_135 || angle < -ANGLE_135 )
1096 {
1097 // about 180 degree
1098 m_height = -m_height;
1099 }
1100
1101 // this will update m_crossBarStart and m_crossbarEnd
1102 PCB_DIMENSION_BASE::Rotate( aRotCentre, angle );
1103}
1104
1105
1108 m_textBorder( DIM_TEXT_BORDER::NONE )
1109{
1110 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1111 m_overrideTextEnabled = true;
1112 m_keepTextAligned = false;
1113
1114 SetOverrideText( _( "Leader" ) );
1115}
1116
1117
1119{
1120 return new PCB_DIM_LEADER( *this );
1121}
1122
1123
1125{
1126 wxASSERT( aImage->Type() == Type() );
1127
1128 m_shapes.clear();
1129 static_cast<PCB_DIM_LEADER*>( aImage )->m_shapes.clear();
1130
1131 std::swap( *static_cast<PCB_DIM_LEADER*>( this ), *static_cast<PCB_DIM_LEADER*>( aImage ) );
1132
1133 Update();
1134}
1135
1136
1138{
1139 return BITMAPS::add_leader;
1140}
1141
1142
1144{
1145 // Our geometry is dependent on the size of the text, so just update the whole shebang
1147}
1148
1149
1151{
1152 m_shapes.clear();
1153
1155
1156 // Now that we have the text updated, we can determine how to draw the second line
1157 // First we need to create an appropriate bounding polygon to collide with
1158 BOX2I textBox = GetTextBox().Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() * 2 );
1159
1160 SHAPE_POLY_SET polyBox;
1161 polyBox.NewOutline();
1162 polyBox.Append( textBox.GetOrigin() );
1163 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1164 polyBox.Append( textBox.GetEnd() );
1165 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1166 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1167
1168 VECTOR2I firstLine( m_end - m_start );
1169 VECTOR2I start( m_start );
1170 start += firstLine.Resize( m_extensionOffset );
1171
1172 SEG arrowSeg( m_start, m_end );
1173 SEG textSeg( m_end, GetTextPos() );
1174 OPT_VECTOR2I arrowSegEnd;
1175 OPT_VECTOR2I textSegEnd;
1176
1177 if( m_textBorder == DIM_TEXT_BORDER::CIRCLE )
1178 {
1179 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1180 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1181 CIRCLE circle( textBox.GetCenter(), radius );
1182
1183 arrowSegEnd = segCircleIntersection( circle, arrowSeg );
1184 textSegEnd = segCircleIntersection( circle, textSeg );
1185 }
1186 else
1187 {
1188 arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1189 textSegEnd = segPolyIntersection( polyBox, textSeg );
1190 }
1191
1192 if( !arrowSegEnd )
1193 arrowSegEnd = m_end;
1194
1195 m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
1196
1197 drawAnArrow( start, EDA_ANGLE( firstLine ), 0 );
1198
1199 if( !GetText().IsEmpty() )
1200 {
1201 switch( m_textBorder )
1202 {
1203 case DIM_TEXT_BORDER::RECTANGLE:
1204 {
1205 for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
1206 m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
1207
1208 break;
1209 }
1210
1211 case DIM_TEXT_BORDER::CIRCLE:
1212 {
1213 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1214 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1215 m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
1216
1217 break;
1218 }
1219
1220 default:
1221 break;
1222 }
1223 }
1224
1225 if( textSegEnd && *arrowSegEnd == m_end )
1226 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textSegEnd ) );
1227}
1228
1229
1230void PCB_DIM_LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1231{
1232 // Don't use GetShownText(); we want to see the variable references here
1233 aList.emplace_back( _( "Leader" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
1234
1235 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
1236
1237 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
1238 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
1239 aFrame->MessageTextFromValue( startCoord.x ),
1240 aFrame->MessageTextFromValue( startCoord.y ) );
1241
1242 aList.emplace_back( start, wxEmptyString );
1243
1244 aList.emplace_back( _( "Layer" ), GetLayerName() );
1245}
1246
1247
1250{
1251 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1252 m_overrideTextEnabled = false;
1253 m_keepTextAligned = true;
1254 m_prefix = "R ";
1256}
1257
1258
1260{
1261 return new PCB_DIM_RADIAL( *this );
1262}
1263
1264
1266{
1267 wxASSERT( aImage->Type() == Type() );
1268
1269 m_shapes.clear();
1270 static_cast<PCB_DIM_RADIAL*>( aImage )->m_shapes.clear();
1271
1272 std::swap( *static_cast<PCB_DIM_RADIAL*>( this ), *static_cast<PCB_DIM_RADIAL*>( aImage ) );
1273
1274 Update();
1275}
1276
1277
1279{
1280 return BITMAPS::add_radial_dimension;
1281}
1282
1283
1285{
1286 VECTOR2I radial( m_end - m_start );
1287
1288 return m_end + radial.Resize( m_leaderLength );
1289}
1290
1291
1293{
1294 if( m_keepTextAligned )
1295 {
1296 VECTOR2I textLine( GetTextPos() - GetKnee() );
1297 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( textLine );
1298
1299 textAngle.Normalize();
1300
1301 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1302 textAngle -= ANGLE_180;
1303
1304 // Round to nearest degree
1305 textAngle = EDA_ANGLE( KiROUND( textAngle.AsDegrees() ), DEGREES_T );
1306
1307 SetTextAngle( textAngle );
1308 }
1309
1311}
1312
1313
1315{
1316 m_shapes.clear();
1317
1318 VECTOR2I center( m_start );
1319 VECTOR2I centerArm( 0, m_arrowLength );
1320
1321 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1322
1323 RotatePoint( centerArm, -ANGLE_90 );
1324
1325 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1326
1327 VECTOR2I radius( m_end - m_start );
1328
1330
1331 updateText();
1332
1333 // Now that we have the text updated, we can determine how to draw the second line
1334 // First we need to create an appropriate bounding polygon to collide with
1336
1337 SHAPE_POLY_SET polyBox;
1338 polyBox.NewOutline();
1339 polyBox.Append( textBox.GetOrigin() );
1340 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1341 polyBox.Append( textBox.GetEnd() );
1342 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1343 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1344
1345 VECTOR2I radial( m_end - m_start );
1346 radial = radial.Resize( m_leaderLength );
1347
1348 SEG arrowSeg( m_end, m_end + radial );
1349 SEG textSeg( arrowSeg.B, GetTextPos() );
1350
1351 CollectKnockedOutSegments( polyBox, arrowSeg, m_shapes );
1352 CollectKnockedOutSegments( polyBox, textSeg, m_shapes );
1353
1354 drawAnArrow( m_end, EDA_ANGLE( radial ), 0 );
1355}
1356
1357
1360{
1361 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1362 m_overrideTextEnabled = true;
1363}
1364
1365
1367{
1368 return new PCB_DIM_CENTER( *this );
1369}
1370
1371
1373{
1374 wxASSERT( aImage->Type() == Type() );
1375
1376 std::swap( *static_cast<PCB_DIM_CENTER*>( this ), *static_cast<PCB_DIM_CENTER*>( aImage ) );
1377}
1378
1379
1381{
1382 return BITMAPS::add_center_dimension;
1383}
1384
1385
1387{
1388 int halfWidth = VECTOR2I( m_end - m_start ).x + ( m_lineThickness / 2.0 );
1389
1390 BOX2I bBox;
1391
1392 bBox.SetX( m_start.x - halfWidth );
1393 bBox.SetY( m_start.y - halfWidth );
1394 bBox.SetWidth( halfWidth * 2 );
1395 bBox.SetHeight( halfWidth * 2 );
1396
1397 bBox.Normalize();
1398
1399 return bBox;
1400}
1401
1402
1404{
1406 VECTOR2I( GetBoundingBox().GetSize() ) );
1407}
1408
1409
1411{
1412 m_shapes.clear();
1413
1414 VECTOR2I center( m_start );
1415 VECTOR2I arm( m_end - m_start );
1416
1417 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1418
1419 RotatePoint( arm, -ANGLE_90 );
1420
1421 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1422}
1423
1424
1425static struct DIMENSION_DESC
1426{
1428 {
1430 .Map( DIM_PRECISION::X, _HKI( "0" ) )
1431 .Map( DIM_PRECISION::X_X, _HKI( "0.0" ) )
1432 .Map( DIM_PRECISION::X_XX, _HKI( "0.00" ) )
1433 .Map( DIM_PRECISION::X_XXX, _HKI( "0.000" ) )
1434 .Map( DIM_PRECISION::X_XXXX, _HKI( "0.0000" ) )
1435 .Map( DIM_PRECISION::X_XXXXX, _HKI( "0.00000" ) )
1436 .Map( DIM_PRECISION::V_VV, _HKI( "0.00 in / 0 mils / 0.0 mm" ) )
1437 .Map( DIM_PRECISION::V_VVV, _HKI( "0.000 / 0 / 0.00" ) )
1438 .Map( DIM_PRECISION::V_VVVV, _HKI( "0.0000 / 0.0 / 0.000" ) )
1439 .Map( DIM_PRECISION::V_VVVVV, _HKI( "0.00000 / 0.00 / 0.0000" ) );
1440
1442 .Map( DIM_UNITS_FORMAT::NO_SUFFIX, _HKI( "1234.0" ) )
1443 .Map( DIM_UNITS_FORMAT::BARE_SUFFIX, _HKI( "1234.0 mm" ) )
1444 .Map( DIM_UNITS_FORMAT::PAREN_SUFFIX, _HKI( "1234.0 (mm)" ) );
1445
1447 .Map( DIM_UNITS_MODE::INCHES, _HKI( "Inches" ) )
1448 .Map( DIM_UNITS_MODE::MILS, _HKI( "Mils" ) )
1449 .Map( DIM_UNITS_MODE::MILLIMETRES, _HKI( "Millimeters" ) )
1450 .Map( DIM_UNITS_MODE::AUTOMATIC, _HKI( "Automatic" ) );
1451
1453 .Map( DIM_ARROW_DIRECTION::INWARD, _HKI( "Inward" ) )
1454 .Map( DIM_ARROW_DIRECTION::OUTWARD, _HKI( "Outward" ) );
1455
1464
1465 propMgr.Mask( TYPE_HASH( PCB_DIMENSION_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
1466
1467 const wxString groupDimension = _HKI( "Dimension Properties" );
1468
1469 auto isLeader =
1470 []( INSPECTABLE* aItem ) -> bool
1471 {
1472 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) != nullptr;
1473 };
1474
1475 auto isNotLeader =
1476 []( INSPECTABLE* aItem ) -> bool
1477 {
1478 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) == nullptr;
1479 };
1480
1481 auto isMultiArrowDirection =
1482 []( INSPECTABLE* aItem ) -> bool
1483 {
1484 return dynamic_cast<PCB_DIM_ALIGNED*>( aItem ) != nullptr;
1485 };
1486
1489 groupDimension )
1490 .SetAvailableFunc( isNotLeader );
1493 groupDimension )
1494 .SetAvailableFunc( isNotLeader );
1495 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, wxString>( _HKI( "Override Text" ),
1497 groupDimension )
1498 .SetAvailableFunc( isNotLeader );
1499
1502 groupDimension )
1503 .SetAvailableFunc( isLeader );
1504
1507 groupDimension )
1508 .SetAvailableFunc( isNotLeader );
1511 groupDimension )
1512 .SetAvailableFunc( isNotLeader );
1515 groupDimension )
1516 .SetAvailableFunc( isNotLeader );
1517 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Suppress Trailing Zeroes" ),
1519 groupDimension )
1520 .SetAvailableFunc( isNotLeader );
1521
1524 groupDimension )
1525 .SetAvailableFunc( isMultiArrowDirection );
1526
1527 const wxString groupText = _HKI( "Text Properties" );
1528
1529 const auto isTextOrientationWriteable =
1530 []( INSPECTABLE* aItem ) -> bool
1531 {
1532 return !static_cast<PCB_DIMENSION_BASE*>( aItem )->GetKeepTextAligned();
1533 };
1534
1535 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Keep Aligned with Dimension" ),
1538 groupText );
1539
1540 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, double>( _HKI( "Orientation" ),
1543 PROPERTY_DISPLAY::PT_DEGREE ),
1544 groupText )
1545 .SetWriteableFunc( isTextOrientationWriteable );
1546 }
1548
1553
1554
1556{
1558 {
1569
1570 const wxString groupDimension = _HKI( "Dimension Properties" );
1571
1572 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Crossbar Height" ),
1575 groupDimension );
1576 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Extension Line Overshoot" ),
1579 groupDimension );
1580
1582 _HKI( "Visible" ),
1583 []( INSPECTABLE* aItem ) { return false; } );
1585 _HKI( "Text" ),
1586 []( INSPECTABLE* aItem ) { return false; } );
1588 _HKI( "Vertical Justification" ),
1589 []( INSPECTABLE* aItem ) { return false; } );
1591 _HKI( "Hyperlink" ),
1592 []( INSPECTABLE* aItem ) { return false; } );
1594 _HKI( "Knockout" ),
1595 []( INSPECTABLE* aItem ) { return false; } );
1596 }
1598
1599
1601{
1603 {
1616
1618 _HKI( "Visible" ),
1619 []( INSPECTABLE* aItem ) { return false; } );
1621 _HKI( "Text" ),
1622 []( INSPECTABLE* aItem ) { return false; } );
1624 _HKI( "Vertical Justification" ),
1625 []( INSPECTABLE* aItem ) { return false; } );
1627 _HKI( "Hyperlink" ),
1628 []( INSPECTABLE* aItem ) { return false; } );
1630 _HKI( "Knockout" ),
1631 []( INSPECTABLE* aItem ) { return false; } );
1632 }
1634
1635
1637{
1639 {
1650
1651 const wxString groupDimension = _HKI( "Dimension Properties" );
1652
1653 propMgr.AddProperty( new PROPERTY<PCB_DIM_RADIAL, int>( _HKI( "Leader Length" ),
1655 PROPERTY_DISPLAY::PT_SIZE ),
1656 groupDimension );
1657
1659 _HKI( "Visible" ),
1660 []( INSPECTABLE* aItem ) { return false; } );
1662 _HKI( "Text" ),
1663 []( INSPECTABLE* aItem ) { return false; } );
1665 _HKI( "Vertical Justification" ),
1666 []( INSPECTABLE* aItem ) { return false; } );
1668 _HKI( "Hyperlink" ),
1669 []( INSPECTABLE* aItem ) { return false; } );
1671 _HKI( "Knockout" ),
1672 []( INSPECTABLE* aItem ) { return false; } );
1673 }
1675
1676
1678{
1680 {
1682 .Map( DIM_TEXT_BORDER::NONE, _HKI( "None" ) )
1683 .Map( DIM_TEXT_BORDER::RECTANGLE, _HKI( "Rectangle" ) )
1684 .Map( DIM_TEXT_BORDER::CIRCLE, _HKI( "Circle" ) );
1685
1696
1697 const wxString groupDimension = _HKI( "Dimension Properties" );
1698
1701 groupDimension );
1702
1704 _HKI( "Visible" ),
1705 []( INSPECTABLE* aItem ) { return false; } );
1707 _HKI( "Text" ),
1708 []( INSPECTABLE* aItem ) { return false; } );
1710 _HKI( "Vertical Justification" ),
1711 []( INSPECTABLE* aItem ) { return false; } );
1713 _HKI( "Hyperlink" ),
1714 []( INSPECTABLE* aItem ) { return false; } );
1716 _HKI( "Knockout" ),
1717 []( INSPECTABLE* aItem ) { return false; } );
1718 }
1720
1722
1723
1725{
1727 {
1738
1739
1741 _HKI( "Visible" ),
1742 []( INSPECTABLE* aItem ) { return false; } );
1744 _HKI( "Text" ),
1745 []( INSPECTABLE* aItem ) { return false; } );
1747 _HKI( "Vertical Justification" ),
1748 []( INSPECTABLE* aItem ) { return false; } );
1750 _HKI( "Hyperlink" ),
1751 []( INSPECTABLE* aItem ) { return false; } );
1753 _HKI( "Knockout" ),
1754 []( INSPECTABLE* aItem ) { return false; } );
1755 }
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
Definition: approximation.h:32
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
BOX2< VECTOR2I > BOX2I
Definition: box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:237
PCB_LAYER_ID m_layer
Definition: board_item.h:436
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:288
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:47
virtual bool IsLocked() const
Definition: board_item.cpp:75
bool IsSideSpecific() const
Definition: board_item.cpp:149
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:139
EDA_UNITS GetUserUnits()
Definition: board.h:701
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr void SetHeight(size_type val)
Definition: box2.h:292
constexpr const Vec GetEnd() const
Definition: box2.h:212
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:146
constexpr coord_type GetY() const
Definition: box2.h:208
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr coord_type GetX() const
Definition: box2.h:207
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
constexpr const Vec GetCenter() const
Definition: box2.h:230
constexpr bool Contains(const Vec &aPoint) const
Definition: box2.h:168
constexpr void SetWidth(size_type val)
Definition: box2.h:287
constexpr void SetX(coord_type val)
Definition: box2.h:277
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
constexpr void SetY(coord_type val)
Definition: box2.h:282
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:311
constexpr coord_type GetBottom() const
Definition: box2.h:222
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:221
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:221
double Sin() const
Definition: eda_angle.h:170
double AsDegrees() const
Definition: eda_angle.h:113
EDA_ANGLE Normalize180()
Definition: eda_angle.h:260
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:89
const KIID m_Uuid
Definition: eda_item.h:489
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:500
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
int GetTextHeight() const
Definition: eda_text.h:247
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:253
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:130
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:94
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:464
KIFONT::FONT * GetFont() const
Definition: eda_text.h:230
BOX2I GetTextBox(int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:616
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:297
int GetTextWidth() const
Definition: eda_text.h:244
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:482
double Similarity(const EDA_TEXT &aOther) const
Definition: eda_text.cpp:1182
virtual void ClearRenderCache()
Definition: eda_text.cpp:544
bool IsMirrored() const
Definition: eda_text.h:173
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition: eda_text.cpp:369
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.
Definition: eda_text.cpp:1023
void SetTextAngleDegrees(double aOrientation)
Definition: eda_text.h:133
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:182
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:204
int GetTextThickness() const
Definition: eda_text.h:122
bool operator==(const EDA_TEXT &aRhs) const
Definition: eda_text.h:376
static ENUM_MAP< T > & Instance()
Definition: property.h:663
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:36
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)
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 ClearRenderCache() override
int m_lineThickness
Thickness used for all graphics in the dimension.
void Move(const VECTOR2I &offset) override
Move this object.
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)
DIM_PRECISION m_precision
Number of digits to display after decimal.
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
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)
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 ChangeTextAngleDegrees(double aDegrees)
bool m_keepTextAligned
Calculate text orientation to match dimension.
DIM_PRECISION GetPrecision() const
wxString GetPrefix() const
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.
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
virtual const VECTOR2I & GetStart() const
The dimension's origin is the first feature point for the dimension.
DIM_ARROW_DIRECTION GetArrowDirection() const
wxString m_valueString
Displayed value when m_overrideValue = true.
void ChangePrecision(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
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.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
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 const VECTOR2I & GetEnd() const
virtual void Mirror(const VECTOR2I &axis_pos, FLIP_DIRECTION aFlipDirection) override
Mirror the dimension relative to a given horizontal axis.
VECTOR2I m_end
Internal cache of drawn shapes.
void ChangeUnitsMode(DIM_UNITS_MODE aMode)
void SetKeepTextAligned(bool aKeepAligned)
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.
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).
VECTOR2I m_crossBarStart
Crossbar start control point.
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.
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.
virtual void swapData(BOARD_ITEM *aImage) override
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
PCB_DIM_CENTER(BOARD_ITEM *aParent)
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
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).
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 ChangeTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
void swapData(BOARD_ITEM *aImage) override
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
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.
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 updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void ChangeLeaderLength(int aLength)
VECTOR2I GetKnee() const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pcb_text.cpp:250
wxString GetShownText(bool aAllowExtraText, int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: pcb_text.cpp:186
bool TextHitTest(const VECTOR2I &aPoint, int aAccuracy=0) const override
Test if aPoint is within the bounds of this object.
Definition: pcb_text.cpp:404
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_text.cpp:507
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition: property.h:257
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition: property.h:268
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
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()
Definition: property_mgr.h:87
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:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int GetRadius() const
Definition: shape_circle.h:118
const VECTOR2I GetCenter() const
Definition: shape_circle.h:123
Base class for iterating over all segments in a given SHAPE_POLY_SET.
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...
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.
const SEG & GetSeg() 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:542
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:385
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 _HKI(x)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:398
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:397
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:402
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:406
static constexpr EDA_ANGLE FULL_CIRCLE
Definition: eda_angle.h:399
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:405
static constexpr EDA_ANGLE ANGLE_135
Definition: eda_angle.h:404
#define PCB_EDIT_FRAME_NAME
EDA_UNITS
Definition: eda_units.h:46
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: layer_id.cpp:208
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:147
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Dwgs_User
Definition: layer_ids.h:107
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:45
FLIP_DIRECTION
Definition: mirror.h:27
KICOMMON_API double ToUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Function To_User_Unit convert aValue in internal units to the appropriate user units defined by aUnit...
Definition: eda_units.cpp:259
KICOMMON_API wxString GetText(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:126
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:155
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
Definition: ui_common.cpp:213
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.
Definition: ui_common.cpp:195
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
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.
Definition: pcb_dimension.h:62
@ OUTSIDE
Text appears outside the dimension line (default)
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
Definition: pcb_dimension.h:40
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
Definition: pcb_dimension.h:72
DIM_ARROW_DIRECTION
Used for dimension's arrow.
Definition: pcb_dimension.h:83
DIM_TEXT_BORDER
Frame to show around dimension text.
Definition: pcb_dimension.h:92
DIM_PRECISION
Definition: pcb_dimension.h:47
#define TYPE_HASH(x)
Definition: property.h:71
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition: property.h:765
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition: property.h:62
#define REGISTER_TYPE(x)
Definition: property_mgr.h:371
@ NONE
No connection to this item.
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
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:229
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:103
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:104
constexpr int sign(T val)
Definition: util.h:159
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691