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 <pcb_dimension.h>
34#include <pcb_text.h>
40#include <trigo.h>
41
42
43static const EDA_ANGLE s_arrowAngle( 27.5, DEGREES_T );
44
45
47 PCB_TEXT( aParent, aType ),
48 m_overrideTextEnabled( false ),
49 m_units( EDA_UNITS::INCHES ),
50 m_autoUnits( false ),
51 m_unitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX ),
52 m_precision( DIM_PRECISION::X_XXXX ),
53 m_suppressZeroes( false ),
54 m_lineThickness( pcbIUScale.mmToIU( 0.2 ) ),
55 m_arrowLength( pcbIUScale.MilsToIU( 50 ) ),
56 m_extensionOffset( 0 ),
57 m_textPosition( DIM_TEXT_POSITION::OUTSIDE ),
58 m_keepTextAligned( true ),
59 m_measuredValue( 0 ),
60 m_inClearRenderCache( false )
61{
63}
64
65
66bool PCB_DIMENSION_BASE::operator==( const BOARD_ITEM& aOther ) const
67{
68 if( Type() != aOther.Type() )
69 return false;
70
71 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
72
73 if( m_textPosition != other.m_textPosition )
74 return false;
75
77 return false;
78
79 if( m_units != other.m_units )
80 return false;
81
82 if( m_autoUnits != other.m_autoUnits )
83 return false;
84
85 if( m_unitsFormat != other.m_unitsFormat )
86 return false;
87
88 if( m_precision != other.m_precision )
89 return false;
90
92 return false;
93
94 if( m_lineThickness != other.m_lineThickness )
95 return false;
96
97 if( m_arrowLength != other.m_arrowLength )
98 return false;
99
101 return false;
102
103 if( m_measuredValue != other.m_measuredValue )
104 return false;
105
106 return EDA_TEXT::operator==( other );
107}
108
109
110double PCB_DIMENSION_BASE::Similarity( const BOARD_ITEM& aOther ) const
111{
112 if( m_Uuid == aOther.m_Uuid )
113 return 1.0;
114
115 if( Type() != aOther.Type() )
116 return 0.0;
117
118 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
119
120 double similarity = 1.0;
121
122 if( m_textPosition != other.m_textPosition )
123 similarity *= 0.9;
124
126 similarity *= 0.9;
127
128 if( m_units != other.m_units )
129 similarity *= 0.9;
130
131 if( m_autoUnits != other.m_autoUnits )
132 similarity *= 0.9;
133
134 if( m_unitsFormat != other.m_unitsFormat )
135 similarity *= 0.9;
136
137 if( m_precision != other.m_precision )
138 similarity *= 0.9;
139
141 similarity *= 0.9;
142
143 if( m_lineThickness != other.m_lineThickness )
144 similarity *= 0.9;
145
146 if( m_arrowLength != other.m_arrowLength )
147 similarity *= 0.9;
148
150 similarity *= 0.9;
151
152 if( m_measuredValue != other.m_measuredValue )
153 similarity *= 0.9;
154
155 similarity *= EDA_TEXT::Similarity( other );
156
157 return similarity;
158}
159
160
162{
164
165 switch( m_unitsFormat )
166 {
167 case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
168 break;
169
170 case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
172 break;
173
174 case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
175 text += wxT( " (" ) + EDA_UNIT_UTILS::GetText( m_units ).Trim( false ) + wxT( ")" );
176 break;
177 }
178
179 text.Prepend( m_prefix );
180 text.Append( m_suffix );
181
182 SetText( text );
183}
184
185
187{
189
190 // We use EDA_TEXT::ClearRenderCache() as a signal that the properties of the EDA_TEXT
191 // have changed and we may need to update the dimension text
192
194 {
196 updateText();
197 m_inClearRenderCache = false;
198 }
199}
200
201
202template<typename ShapeType>
203void PCB_DIMENSION_BASE::addShape( const ShapeType& aShape )
204{
205 m_shapes.push_back( std::make_shared<ShapeType>( aShape ) );
206}
207
208
210{
211 struct lconv* lc = localeconv();
212 wxChar sep = lc->decimal_point[0];
213
214 int val = GetMeasuredValue();
215 int precision = static_cast<int>( m_precision );
216 wxString text;
217
218 if( precision >= 6 )
219 {
220 switch( m_units )
221 {
222 case EDA_UNITS::INCHES: precision = precision - 4; break;
223 case EDA_UNITS::MILS: precision = std::max( 0, precision - 7 ); break;
224 case EDA_UNITS::MILLIMETRES: precision = precision - 5; break;
225 default: precision = precision - 4; break;
226 }
227 }
228
229 wxString format = wxT( "%." ) + wxString::Format( wxT( "%i" ), precision ) + wxT( "f" );
230
231 text.Printf( format, EDA_UNIT_UTILS::UI::ToUserUnit( pcbIUScale, m_units, val ) );
232
233 if( m_suppressZeroes )
234 {
235 while( text.Last() == '0' )
236 {
237 text.RemoveLast();
238
239 if( text.Last() == '.' || text.Last() == sep )
240 {
241 text.RemoveLast();
242 break;
243 }
244 }
245 }
246
247 return text;
248}
249
250
251void PCB_DIMENSION_BASE::SetPrefix( const wxString& aPrefix )
252{
253 m_prefix = aPrefix;
254}
255
256
257void PCB_DIMENSION_BASE::SetSuffix( const wxString& aSuffix )
258{
259 m_suffix = aSuffix;
260}
261
262
264{
265 m_units = aUnits;
266}
267
268
270{
271 if( m_autoUnits )
272 {
273 return DIM_UNITS_MODE::AUTOMATIC;
274 }
275 else
276 {
277 switch( m_units )
278 {
279 default:
280 case EDA_UNITS::INCHES: return DIM_UNITS_MODE::INCHES;
281 case EDA_UNITS::MILLIMETRES: return DIM_UNITS_MODE::MILLIMETRES;
282 case EDA_UNITS::MILS: return DIM_UNITS_MODE::MILS;
283 }
284 }
285}
286
287
289{
290 switch( aMode )
291 {
292 case DIM_UNITS_MODE::INCHES:
293 m_autoUnits = false;
294 m_units = EDA_UNITS::INCHES;
295 break;
296
297 case DIM_UNITS_MODE::MILS:
298 m_autoUnits = false;
299 m_units = EDA_UNITS::MILS;
300 break;
301
302 case DIM_UNITS_MODE::MILLIMETRES:
303 m_autoUnits = false;
304 m_units = EDA_UNITS::MILLIMETRES;
305 break;
306
307 case DIM_UNITS_MODE::AUTOMATIC:
308 m_autoUnits = true;
309 m_units = GetBoard() ? GetBoard()->GetUserUnits() : EDA_UNITS::MILLIMETRES;
310 break;
311 }
312}
313
314
316{
317 PCB_TEXT::Offset( offset );
318
319 m_start += offset;
320 m_end += offset;
321
322 Update();
323}
324
325
326void PCB_DIMENSION_BASE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
327{
328 EDA_ANGLE newAngle = GetTextAngle() + aAngle;
329
330 newAngle.Normalize();
331
332 SetTextAngle( newAngle );
333
334 VECTOR2I pt = GetTextPos();
335 RotatePoint( pt, aRotCentre, aAngle );
336 SetTextPos( pt );
337
338 RotatePoint( m_start, aRotCentre, aAngle );
339 RotatePoint( m_end, aRotCentre, aAngle );
340
341 Update();
342}
343
344
345void PCB_DIMENSION_BASE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
346{
347 Mirror( aCentre );
348
349 SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) );
350}
351
352
353void PCB_DIMENSION_BASE::Mirror( const VECTOR2I& axis_pos, bool aMirrorLeftRight )
354{
355 int axis = aMirrorLeftRight ? axis_pos.x : axis_pos.y;
356 VECTOR2I newPos = GetTextPos();
357
358#define INVERT( pos ) ( ( pos ) = axis - ( ( pos ) - axis ) )
359 if( aMirrorLeftRight )
360 INVERT( newPos.x );
361 else
362 INVERT( newPos.y );
363
364 SetTextPos( newPos );
365
366 // invert angle
368
369 if( aMirrorLeftRight )
370 {
371 INVERT( m_start.x );
372 INVERT( m_end.x );
373 }
374 else
375 {
376 INVERT( m_start.y );
377 INVERT( m_end.y );
378 }
379
380 if( ( GetLayerSet() & LSET::SideSpecificMask() ).any() )
382
383 Update();
384}
385
386
388 std::vector<MSG_PANEL_ITEM>& aList )
389{
390 // for now, display only the text within the DIMENSION using class PCB_TEXT.
391 wxString msg;
392
393 wxCHECK_RET( m_parent != nullptr, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
394
395 // Don't use GetShownText(); we want to see the variable references here
396 aList.emplace_back( _( "Dimension" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
397
398 aList.emplace_back( _( "Prefix" ), GetPrefix() );
399
401 {
402 aList.emplace_back( _( "Override Text" ), GetOverrideText() );
403 }
404 else
405 {
406 aList.emplace_back( _( "Value" ), GetValueText() );
407
408 switch( GetPrecision() )
409 {
410 case DIM_PRECISION::V_VV: msg = wxT( "0.00 in / 0 mils / 0.0 mm" ); break;
411 case DIM_PRECISION::V_VVV: msg = wxT( "0.000 in / 0 mils / 0.00 mm" ); break;
412 case DIM_PRECISION::V_VVVV: msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" ); break;
413 case DIM_PRECISION::V_VVVVV: msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
414 default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
415 }
416
417 aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
418 }
419
420 aList.emplace_back( _( "Suffix" ), GetSuffix() );
421
422 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
423 // in frame's units.
424 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
425 unitsProvider.SetUserUnits( GetUnits() );
426
427 aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( GetUnits() ) );
428
429 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
430 aList.emplace_back( _( "Text Thickness" ), unitsProvider.MessageTextFromValue( GetTextThickness() ) );
431 aList.emplace_back( _( "Text Width" ), unitsProvider.MessageTextFromValue( GetTextWidth() ) );
432 aList.emplace_back( _( "Text Height" ), unitsProvider.MessageTextFromValue( GetTextHeight() ) );
433
434 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
435
436 if( Type() == PCB_DIM_CENTER_T )
437 {
438 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
439 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
440 aFrame->MessageTextFromValue( startCoord.x ),
441 aFrame->MessageTextFromValue( startCoord.y ) );
442
443 aList.emplace_back( start, wxEmptyString );
444 }
445 else
446 {
447 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
448 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
449 aFrame->MessageTextFromValue( startCoord.x ),
450 aFrame->MessageTextFromValue( startCoord.y ) );
451 VECTOR2I endCoord = originTransforms.ToDisplayAbs( GetEnd() );
452 wxString end = wxString::Format( wxT( "@(%s, %s)" ),
453 aFrame->MessageTextFromValue( endCoord.x ),
454 aFrame->MessageTextFromValue( endCoord.y ) );
455
456 aList.emplace_back( start, end );
457 }
458
459 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
460 aList.emplace_back( _( "Status" ), _( "Locked" ) );
461
462 aList.emplace_back( _( "Layer" ), GetLayerName() );
463}
464
465
466std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
467{
468 std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
469
470 effectiveShape->AddShape( GetEffectiveTextShape()->Clone() );
471
472 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
473 effectiveShape->AddShape( shape->Clone() );
474
475 return effectiveShape;
476}
477
478
479bool PCB_DIMENSION_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
480{
481 if( TextHitTest( aPosition ) )
482 return true;
483
484 int dist_max = aAccuracy + ( m_lineThickness / 2 );
485
486 // Locate SEGMENTS
487
488 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
489 {
490 if( shape->Collide( aPosition, dist_max ) )
491 return true;
492 }
493
494 return false;
495}
496
497
498bool PCB_DIMENSION_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
499{
500 BOX2I arect = aRect;
501 arect.Inflate( aAccuracy );
502
503 BOX2I rect = GetBoundingBox();
504
505 if( aAccuracy )
506 rect.Inflate( aAccuracy );
507
508 if( aContained )
509 return arect.Contains( rect );
510
511 return arect.Intersects( rect );
512}
513
514
516{
517 BOX2I bBox;
518 int xmin, xmax, ymin, ymax;
519
520 bBox = GetTextBox();
521 xmin = bBox.GetX();
522 xmax = bBox.GetRight();
523 ymin = bBox.GetY();
524 ymax = bBox.GetBottom();
525
526 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
527 {
528 BOX2I shapeBox = shape->BBox();
529 shapeBox.Inflate( m_lineThickness / 2 );
530
531 xmin = std::min( xmin, shapeBox.GetOrigin().x );
532 xmax = std::max( xmax, shapeBox.GetEnd().x );
533 ymin = std::min( ymin, shapeBox.GetOrigin().y );
534 ymax = std::max( ymax, shapeBox.GetEnd().y );
535 }
536
537 bBox.SetX( xmin );
538 bBox.SetY( ymin );
539 bBox.SetWidth( xmax - xmin + 1 );
540 bBox.SetHeight( ymax - ymin + 1 );
541
542 bBox.Normalize();
543
544 return bBox;
545}
546
547
549{
550 return wxString::Format( _( "Dimension '%s' on %s" ),
552 GetLayerName() );
553}
554
555
556
558{
560 VECTOR2I( GetBoundingBox().GetSize() ) );
561 dimBBox.Merge( PCB_TEXT::ViewBBox() );
562
563 return dimBBox;
564}
565
566
568 bool aStart )
569{
570 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
571 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
572
573 if( aPoly.Contains( start ) )
574 return std::nullopt;
575
576 for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
577 {
578 if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
579 {
580 if( ( *intersection - start ).SquaredEuclideanNorm() <
581 ( endpoint - start ).SquaredEuclideanNorm() )
582 endpoint = *intersection;
583 }
584 }
585
586 if( start == endpoint )
587 return std::nullopt;
588
589 return OPT_VECTOR2I( endpoint );
590}
591
592
594{
595 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
596 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
597
598 if( aCircle.Contains( start ) )
599 return std::nullopt;
600
601 std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
602
603 for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
604 {
605 if( ( intersection - start ).SquaredEuclideanNorm() <
606 ( endpoint - start ).SquaredEuclideanNorm() )
607 endpoint = intersection;
608 }
609
610 if( start == endpoint )
611 return std::nullopt;
612
613 return OPT_VECTOR2I( endpoint );
614}
615
616
618 int aClearance, int aError, ERROR_LOC aErrorLoc,
619 bool aIgnoreLineWidth ) const
620{
621 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
622
623 for( const std::shared_ptr<SHAPE>& shape : m_shapes )
624 {
625 const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
626 const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
627
628 if( circle )
629 {
630 TransformCircleToPolygon( aBuffer, circle->GetCenter(),
631 circle->GetRadius() + m_lineThickness / 2 + aClearance,
632 aError, aErrorLoc );
633 }
634 else if( seg )
635 {
636 TransformOvalToPolygon( aBuffer, seg->GetSeg().A, seg->GetSeg().B,
637 m_lineThickness + 2 * aClearance, aError, aErrorLoc );
638 }
639 else
640 {
641 wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeToPolygon unknown shape type." ) );
642 }
643 }
644}
645
646
648 PCB_DIMENSION_BASE( aParent, aType ),
649 m_height( 0 )
650{
651 // To preserve look of old dimensions, initialize extension height based on default arrow length
652 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
653}
654
655
657{
658 return new PCB_DIM_ALIGNED( *this );
659}
660
661
663{
664 wxASSERT( aImage->Type() == Type() );
665
666 m_shapes.clear();
667 static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
668
669 std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
670
671 Update();
672}
673
674
675void PCB_DIM_ALIGNED::Mirror( const VECTOR2I& axis_pos, bool aMirrorLeftRight )
676{
677 PCB_DIMENSION_BASE::Mirror( axis_pos, aMirrorLeftRight );
678
680}
681
682
684{
685 return BITMAPS::add_aligned_dimension;
686}
687
688
689void PCB_DIM_ALIGNED::UpdateHeight( const VECTOR2I& aCrossbarStart, const VECTOR2I& aCrossbarEnd )
690{
691 VECTOR2D height( aCrossbarStart - GetStart() );
692 VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
693
694 if( height.Cross( crossBar ) > 0 )
695 m_height = -height.EuclideanNorm();
696 else
697 m_height = height.EuclideanNorm();
698
699 Update();
700}
701
702
704{
705 m_shapes.clear();
706
707 VECTOR2I dimension( m_end - m_start );
708
709 m_measuredValue = KiROUND( dimension.EuclideanNorm() );
710
711 VECTOR2I extension;
712
713 if( m_height > 0 )
714 extension = VECTOR2I( -dimension.y, dimension.x );
715 else
716 extension = VECTOR2I( dimension.y, -dimension.x );
717
718 // Add extension lines
719 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
720
721 VECTOR2I extStart( m_start );
722 extStart += extension.Resize( m_extensionOffset );
723
724 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
725
726 extStart = VECTOR2I( m_end );
727 extStart += extension.Resize( m_extensionOffset );
728
729 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
730
731 // Add crossbar
732 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
733 m_crossBarStart = m_start + crossBarDistance;
734 m_crossBarEnd = m_end + crossBarDistance;
735
736 // Update text after calculating crossbar position but before adding crossbar lines
737 updateText();
738
739 // Now that we have the text updated, we can determine how to draw the crossbar.
740 // First we need to create an appropriate bounding polygon to collide with
742
743 SHAPE_POLY_SET polyBox;
744 polyBox.NewOutline();
745 polyBox.Append( textBox.GetOrigin() );
746 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
747 polyBox.Append( textBox.GetEnd() );
748 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
749 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
750
751 // The ideal crossbar, if the text doesn't collide
752 SEG crossbar( m_crossBarStart, m_crossBarEnd );
753
754 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
755 bool containsA = polyBox.Contains( crossbar.A );
756 bool containsB = polyBox.Contains( crossbar.B );
757
758 OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
759 OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
760
761 if( endpointA )
762 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
763
764 if( endpointB )
765 m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
766
767 if( !containsA && !containsB && !endpointA && !endpointB )
768 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
769
770 // Add arrows
771 VECTOR2I arrowEndPos( m_arrowLength, 0 );
772 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
773 RotatePoint( arrowEndPos, -EDA_ANGLE( dimension ) + s_arrowAngle );
774 RotatePoint( arrowEndNeg, -EDA_ANGLE( dimension ) - s_arrowAngle );
775
776 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndPos ) );
777 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndNeg ) );
778 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndPos ) );
779 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndNeg ) );
780}
781
782
784{
785 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
786
787 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
788 {
789 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
790 EDA_ANGLE rotation;
791
792 if( crossbarCenter.x == 0 )
793 rotation = ANGLE_90 * sign( -crossbarCenter.y );
794 else if( crossbarCenter.x < 0 )
795 rotation = -ANGLE_90;
796 else
797 rotation = ANGLE_90;
798
799 VECTOR2I textOffset = crossbarCenter;
800 RotatePoint( textOffset, rotation );
801 textOffset = crossbarCenter + textOffset.Resize( textOffsetDistance );
802
803 SetTextPos( m_crossBarStart + textOffset );
804 }
805 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
806 {
807 SetTextPos( m_crossBarStart + crossbarCenter );
808 }
809
811 {
812 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( crossbarCenter );
813 textAngle.Normalize();
814
815 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
816 textAngle -= ANGLE_180;
817
818 SetTextAngle( textAngle );
819 }
820
822}
823
824
825void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
826{
828
829 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
830 // in frame's units.
831 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
832 unitsProvider.SetUserUnits( GetUnits() );
833
834 aList.emplace_back( _( "Height" ), unitsProvider.MessageTextFromValue( m_height ) );
835}
836
837
840{
841 // To preserve look of old dimensions, initialize extension height based on default arrow length
842 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
844}
845
846
848{
849 return new PCB_DIM_ORTHOGONAL( *this );
850}
851
852
854{
855 wxASSERT( aImage->Type() == Type() );
856
857 m_shapes.clear();
858 static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
859
860 std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
861 *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
862
863 Update();
864}
865
866
868{
869 return BITMAPS::add_orthogonal_dimension;
870}
871
872
874{
875 m_shapes.clear();
876
878 m_end.y - m_start.y );
880
881 VECTOR2I extension;
882
884 extension = VECTOR2I( 0, m_height );
885 else
886 extension = VECTOR2I( m_height, 0 );
887
888 // Add first extension line
889 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
890
891 VECTOR2I extStart( m_start );
892 extStart += extension.Resize( m_extensionOffset );
893
894 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
895
896 // Add crossbar
897 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
898 m_crossBarStart = m_start + crossBarDistance;
899
902 else
904
905 // Add second extension line (m_end to crossbar end)
907 extension = VECTOR2I( 0, m_end.y - m_crossBarEnd.y );
908 else
909 extension = VECTOR2I( m_end.x - m_crossBarEnd.x, 0 );
910
911 extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
912
913 extStart = VECTOR2I( m_crossBarEnd );
914 extStart -= extension.Resize( m_extensionHeight );
915
916 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
917
918 // Update text after calculating crossbar position but before adding crossbar lines
919 updateText();
920
921 // Now that we have the text updated, we can determine how to draw the crossbar.
922 // First we need to create an appropriate bounding polygon to collide with
924
925 SHAPE_POLY_SET polyBox;
926 polyBox.NewOutline();
927 polyBox.Append( textBox.GetOrigin() );
928 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
929 polyBox.Append( textBox.GetEnd() );
930 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
931 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
932
933 // The ideal crossbar, if the text doesn't collide
934 SEG crossbar( m_crossBarStart, m_crossBarEnd );
935
936 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
937 bool containsA = polyBox.Contains( crossbar.A );
938 bool containsB = polyBox.Contains( crossbar.B );
939
940 OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
941 OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
942
943 if( endpointA )
944 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
945
946 if( endpointB )
947 m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
948
949 if( !containsA && !containsB && !endpointA && !endpointB )
950 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
951
952 // Add arrows
953 EDA_ANGLE crossBarAngle( m_crossBarEnd - m_crossBarStart );
954 VECTOR2I arrowEndPos( m_arrowLength, 0 );
955 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
956 RotatePoint( arrowEndPos, -crossBarAngle + s_arrowAngle );
957 RotatePoint( arrowEndNeg, -crossBarAngle - s_arrowAngle );
958
959 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndPos ) );
960 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndNeg ) );
961 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndPos ) );
962 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndNeg ) );
963}
964
965
967{
968 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
969
970 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
971 {
972 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
973
974 VECTOR2I textOffset;
975
977 textOffset.y = -textOffsetDistance;
978 else
979 textOffset.x = -textOffsetDistance;
980
981 textOffset += crossbarCenter;
982
983 SetTextPos( m_crossBarStart + textOffset );
984 }
985 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
986 {
987 SetTextPos( m_crossBarStart + crossbarCenter );
988 }
989
991 {
992 if( abs( crossbarCenter.x ) > abs( crossbarCenter.y ) )
994 else
996 }
997
999}
1000
1001
1002void PCB_DIM_ORTHOGONAL::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1003{
1004 EDA_ANGLE angle( aAngle );
1005
1006 // restrict angle to -179.9 to 180.0 degrees
1007 angle.Normalize180();
1008
1009 // adjust orientation and height to new angle
1010 // we can only handle the cases of -90, 0, 90, 180 degrees exactly;
1011 // in the other cases we will use the nearest 90 degree angle to
1012 // choose at least an approximate axis for the target orientation
1013 // In case of exactly 45 or 135 degrees, we will round towards zero for consistency
1014 if( angle > ANGLE_45 && angle <= ANGLE_135 )
1015 {
1016 // about 90 degree
1018 {
1020 }
1021 else
1022 {
1024 m_height = -m_height;
1025 }
1026 }
1027 else if( angle < -ANGLE_45 && angle >= -ANGLE_135 )
1028 {
1029 // about -90 degree
1031 {
1033 m_height = -m_height;
1034 }
1035 else
1036 {
1038 }
1039 }
1040 else if( angle > ANGLE_135 || angle < -ANGLE_135 )
1041 {
1042 // about 180 degree
1043 m_height = -m_height;
1044 }
1045
1046 // this will update m_crossBarStart and m_crossbarEnd
1047 PCB_DIMENSION_BASE::Rotate( aRotCentre, angle );
1048}
1049
1050
1053 m_textBorder( DIM_TEXT_BORDER::NONE )
1054{
1055 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1056 m_overrideTextEnabled = true;
1057 m_keepTextAligned = false;
1058
1059 SetOverrideText( _( "Leader" ) );
1060}
1061
1062
1064{
1065 return new PCB_DIM_LEADER( *this );
1066}
1067
1068
1070{
1071 wxASSERT( aImage->Type() == Type() );
1072
1073 m_shapes.clear();
1074 static_cast<PCB_DIM_LEADER*>( aImage )->m_shapes.clear();
1075
1076 std::swap( *static_cast<PCB_DIM_LEADER*>( this ), *static_cast<PCB_DIM_LEADER*>( aImage ) );
1077
1078 Update();
1079}
1080
1081
1083{
1084 return BITMAPS::add_leader;
1085}
1086
1087
1089{
1090 // Our geometry is dependent on the size of the text, so just update the whole shebang
1092}
1093
1094
1096{
1097 m_shapes.clear();
1098
1100
1101 // Now that we have the text updated, we can determine how to draw the second line
1102 // First we need to create an appropriate bounding polygon to collide with
1103 BOX2I textBox = GetTextBox().Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() * 2 );
1104
1105 SHAPE_POLY_SET polyBox;
1106 polyBox.NewOutline();
1107 polyBox.Append( textBox.GetOrigin() );
1108 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1109 polyBox.Append( textBox.GetEnd() );
1110 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1111 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1112
1113 VECTOR2I firstLine( m_end - m_start );
1114 VECTOR2I start( m_start );
1115 start += firstLine.Resize( m_extensionOffset );
1116
1117 SEG arrowSeg( m_start, m_end );
1118 SEG textSeg( m_end, GetTextPos() );
1119 OPT_VECTOR2I arrowSegEnd;
1120 OPT_VECTOR2I textSegEnd;
1121
1122 if( m_textBorder == DIM_TEXT_BORDER::CIRCLE )
1123 {
1124 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1125 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1126 CIRCLE circle( textBox.GetCenter(), radius );
1127
1128 arrowSegEnd = segCircleIntersection( circle, arrowSeg );
1129 textSegEnd = segCircleIntersection( circle, textSeg );
1130 }
1131 else
1132 {
1133 arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1134 textSegEnd = segPolyIntersection( polyBox, textSeg );
1135 }
1136
1137 if( !arrowSegEnd )
1138 arrowSegEnd = m_end;
1139
1140 m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
1141
1142 // Add arrows
1143 VECTOR2I arrowEndPos( m_arrowLength, 0 );
1144 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
1145 RotatePoint( arrowEndPos, -EDA_ANGLE( firstLine ) + s_arrowAngle );
1146 RotatePoint( arrowEndNeg, -EDA_ANGLE( firstLine ) - s_arrowAngle );
1147
1148 m_shapes.emplace_back( new SHAPE_SEGMENT( start, start + arrowEndPos ) );
1149 m_shapes.emplace_back( new SHAPE_SEGMENT( start, start + arrowEndNeg ) );
1150
1151
1152 if( !GetText().IsEmpty() )
1153 {
1154 switch( m_textBorder )
1155 {
1156 case DIM_TEXT_BORDER::RECTANGLE:
1157 {
1158 for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
1159 m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
1160
1161 break;
1162 }
1163
1164 case DIM_TEXT_BORDER::CIRCLE:
1165 {
1166 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1167 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1168 m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
1169
1170 break;
1171 }
1172
1173 default:
1174 break;
1175 }
1176 }
1177
1178 if( textSegEnd && *arrowSegEnd == m_end )
1179 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textSegEnd ) );
1180}
1181
1182
1183void PCB_DIM_LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1184{
1185 // Don't use GetShownText(); we want to see the variable references here
1186 aList.emplace_back( _( "Leader" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
1187
1188 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
1189
1190 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
1191 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
1192 aFrame->MessageTextFromValue( startCoord.x ),
1193 aFrame->MessageTextFromValue( startCoord.y ) );
1194
1195 aList.emplace_back( start, wxEmptyString );
1196
1197 aList.emplace_back( _( "Layer" ), GetLayerName() );
1198}
1199
1200
1203{
1204 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1205 m_overrideTextEnabled = false;
1206 m_keepTextAligned = true;
1207 m_isDiameter = false;
1208 m_prefix = "R ";
1210}
1211
1212
1214{
1215 return new PCB_DIM_RADIAL( *this );
1216}
1217
1218
1220{
1221 wxASSERT( aImage->Type() == Type() );
1222
1223 m_shapes.clear();
1224 static_cast<PCB_DIM_RADIAL*>( aImage )->m_shapes.clear();
1225
1226 std::swap( *static_cast<PCB_DIM_RADIAL*>( this ), *static_cast<PCB_DIM_RADIAL*>( aImage ) );
1227
1228 Update();
1229}
1230
1231
1233{
1234 return BITMAPS::add_radial_dimension;
1235}
1236
1237
1239{
1240 VECTOR2I radial( m_end - m_start );
1241
1242 return m_end + radial.Resize( m_leaderLength );
1243}
1244
1245
1247{
1248 if( m_keepTextAligned )
1249 {
1250 VECTOR2I textLine( GetTextPos() - GetKnee() );
1251 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( textLine );
1252
1253 textAngle.Normalize();
1254
1255 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1256 textAngle -= ANGLE_180;
1257
1258 // Round to nearest degree
1259 textAngle = EDA_ANGLE( KiROUND( textAngle.AsDegrees() ), DEGREES_T );
1260
1261 SetTextAngle( textAngle );
1262 }
1263
1265}
1266
1267
1269{
1270 m_shapes.clear();
1271
1272 VECTOR2I center( m_start );
1273 VECTOR2I centerArm( 0, m_arrowLength );
1274
1275 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1276
1277 RotatePoint( centerArm, -ANGLE_90 );
1278
1279 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1280
1281 VECTOR2I radius( m_end - m_start );
1282
1283 if( m_isDiameter )
1284 m_measuredValue = KiROUND( radius.EuclideanNorm() * 2 );
1285 else
1287
1288 updateText();
1289
1290 // Now that we have the text updated, we can determine how to draw the second line
1291 // First we need to create an appropriate bounding polygon to collide with
1293
1294 SHAPE_POLY_SET polyBox;
1295 polyBox.NewOutline();
1296 polyBox.Append( textBox.GetOrigin() );
1297 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1298 polyBox.Append( textBox.GetEnd() );
1299 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1300 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1301
1302 VECTOR2I radial( m_end - m_start );
1303 radial = radial.Resize( m_leaderLength );
1304
1305 SEG arrowSeg( m_end, m_end + radial );
1306 SEG textSeg( arrowSeg.B, GetTextPos() );
1307
1308 OPT_VECTOR2I arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1309 OPT_VECTOR2I textSegEnd = segPolyIntersection( polyBox, textSeg );
1310
1311 if( arrowSegEnd )
1312 arrowSeg.B = *arrowSegEnd;
1313
1314 if( textSegEnd )
1315 textSeg.B = *textSegEnd;
1316
1317 m_shapes.emplace_back( new SHAPE_SEGMENT( arrowSeg ) );
1318
1319 // Add arrows
1320 VECTOR2I arrowEndPos( m_arrowLength, 0 );
1321 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
1322 RotatePoint( arrowEndPos, -EDA_ANGLE( radial ) + s_arrowAngle );
1323 RotatePoint( arrowEndNeg, -EDA_ANGLE( radial ) - s_arrowAngle );
1324
1325 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, m_end + arrowEndPos ) );
1326 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, m_end + arrowEndNeg ) );
1327
1328 m_shapes.emplace_back( new SHAPE_SEGMENT( textSeg ) );
1329}
1330
1331
1334{
1335 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1336 m_overrideTextEnabled = true;
1337}
1338
1339
1341{
1342 return new PCB_DIM_CENTER( *this );
1343}
1344
1345
1347{
1348 wxASSERT( aImage->Type() == Type() );
1349
1350 std::swap( *static_cast<PCB_DIM_CENTER*>( this ), *static_cast<PCB_DIM_CENTER*>( aImage ) );
1351}
1352
1353
1355{
1356 return BITMAPS::add_center_dimension;
1357}
1358
1359
1361{
1362 int halfWidth = VECTOR2I( m_end - m_start ).x + ( m_lineThickness / 2.0 );
1363
1364 BOX2I bBox;
1365
1366 bBox.SetX( m_start.x - halfWidth );
1367 bBox.SetY( m_start.y - halfWidth );
1368 bBox.SetWidth( halfWidth * 2 );
1369 bBox.SetHeight( halfWidth * 2 );
1370
1371 bBox.Normalize();
1372
1373 return bBox;
1374}
1375
1376
1378{
1380 VECTOR2I( GetBoundingBox().GetSize() ) );
1381}
1382
1383
1385{
1386 m_shapes.clear();
1387
1388 VECTOR2I center( m_start );
1389 VECTOR2I arm( m_end - m_start );
1390
1391 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1392
1393 RotatePoint( arm, -ANGLE_90 );
1394
1395 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1396}
1397
1398
1399static struct DIMENSION_DESC
1400{
1402 {
1404 .Map( DIM_PRECISION::X, _HKI( "0" ) )
1405 .Map( DIM_PRECISION::X_X, _HKI( "0.0" ) )
1406 .Map( DIM_PRECISION::X_XX, _HKI( "0.00" ) )
1407 .Map( DIM_PRECISION::X_XXX, _HKI( "0.000" ) )
1408 .Map( DIM_PRECISION::X_XXXX, _HKI( "0.0000" ) )
1409 .Map( DIM_PRECISION::X_XXXXX, _HKI( "0.00000" ) )
1410 .Map( DIM_PRECISION::V_VV, _HKI( "0.00 in / 0 mils / 0.0 mm" ) )
1411 .Map( DIM_PRECISION::V_VVV, _HKI( "0.000 / 0 / 0.00" ) )
1412 .Map( DIM_PRECISION::V_VVVV, _HKI( "0.0000 / 0.0 / 0.000" ) )
1413 .Map( DIM_PRECISION::V_VVVVV, _HKI( "0.00000 / 0.00 / 0.0000" ) );
1414
1416 .Map( DIM_UNITS_FORMAT::NO_SUFFIX, _HKI( "1234.0" ) )
1417 .Map( DIM_UNITS_FORMAT::BARE_SUFFIX, _HKI( "1234.0 mm" ) )
1418 .Map( DIM_UNITS_FORMAT::PAREN_SUFFIX, _HKI( "1234.0 (mm)" ) );
1419
1421 .Map( DIM_UNITS_MODE::INCHES, _HKI( "Inches" ) )
1422 .Map( DIM_UNITS_MODE::MILS, _HKI( "Mils" ) )
1423 .Map( DIM_UNITS_MODE::MILLIMETRES, _HKI( "Millimeters" ) )
1424 .Map( DIM_UNITS_MODE::AUTOMATIC, _HKI( "Automatic" ) );
1425
1434
1435 const wxString groupDimension = _HKI( "Dimension Properties" );
1436
1437 auto isLeader =
1438 []( INSPECTABLE* aItem ) -> bool
1439 {
1440 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) != nullptr;
1441 };
1442
1443 auto isNotLeader =
1444 []( INSPECTABLE* aItem ) -> bool
1445 {
1446 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) == nullptr;
1447 };
1448
1451 groupDimension )
1452 .SetAvailableFunc( isNotLeader );
1455 groupDimension )
1456 .SetAvailableFunc( isNotLeader );
1457 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, wxString>( _HKI( "Override Text" ),
1459 groupDimension )
1460 .SetAvailableFunc( isNotLeader );
1461
1464 groupDimension )
1465 .SetAvailableFunc( isLeader );
1466
1469 groupDimension )
1470 .SetAvailableFunc( isNotLeader );
1473 groupDimension )
1474 .SetAvailableFunc( isNotLeader );
1477 groupDimension )
1478 .SetAvailableFunc( isNotLeader );
1479 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Suppress Trailing Zeroes" ),
1481 groupDimension )
1482 .SetAvailableFunc( isNotLeader );
1483 }
1485
1489
1490
1492{
1494 {
1505
1506 const wxString groupDimension = _HKI( "Dimension Properties" );
1507
1508 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Crossbar Height" ),
1511 groupDimension );
1512 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Extension Line Overshoot" ),
1515 groupDimension );
1516
1518 _HKI( "Visible" ),
1519 []( INSPECTABLE* aItem ) { return false; } );
1521 _HKI( "Text" ),
1522 []( INSPECTABLE* aItem ) { return false; } );
1524 _HKI( "Vertical Justification" ),
1525 []( INSPECTABLE* aItem ) { return false; } );
1527 _HKI( "Hyperlink" ),
1528 []( INSPECTABLE* aItem ) { return false; } );
1530 _HKI( "Knockout" ),
1531 []( INSPECTABLE* aItem ) { return false; } );
1532 }
1534
1535
1537{
1539 {
1552
1554 _HKI( "Visible" ),
1555 []( INSPECTABLE* aItem ) { return false; } );
1557 _HKI( "Text" ),
1558 []( INSPECTABLE* aItem ) { return false; } );
1560 _HKI( "Vertical Justification" ),
1561 []( INSPECTABLE* aItem ) { return false; } );
1563 _HKI( "Hyperlink" ),
1564 []( INSPECTABLE* aItem ) { return false; } );
1566 _HKI( "Knockout" ),
1567 []( INSPECTABLE* aItem ) { return false; } );
1568 }
1570
1571
1573{
1575 {
1586
1587 const wxString groupDimension = _HKI( "Dimension Properties" );
1588
1589 propMgr.AddProperty( new PROPERTY<PCB_DIM_RADIAL, int>( _HKI( "Leader Length" ),
1591 PROPERTY_DISPLAY::PT_SIZE ),
1592 groupDimension );
1593
1595 _HKI( "Visible" ),
1596 []( INSPECTABLE* aItem ) { return false; } );
1598 _HKI( "Text" ),
1599 []( INSPECTABLE* aItem ) { return false; } );
1601 _HKI( "Vertical Justification" ),
1602 []( INSPECTABLE* aItem ) { return false; } );
1604 _HKI( "Hyperlink" ),
1605 []( INSPECTABLE* aItem ) { return false; } );
1607 _HKI( "Knockout" ),
1608 []( INSPECTABLE* aItem ) { return false; } );
1609 }
1611
1612
1614{
1616 {
1618 .Map( DIM_TEXT_BORDER::NONE, _HKI( "None" ) )
1619 .Map( DIM_TEXT_BORDER::RECTANGLE, _HKI( "Rectangle" ) )
1620 .Map( DIM_TEXT_BORDER::CIRCLE, _HKI( "Circle" ) );
1621
1632
1633 const wxString groupDimension = _HKI( "Dimension Properties" );
1634
1637 groupDimension );
1638
1640 _HKI( "Visible" ),
1641 []( INSPECTABLE* aItem ) { return false; } );
1643 _HKI( "Text" ),
1644 []( INSPECTABLE* aItem ) { return false; } );
1646 _HKI( "Vertical Justification" ),
1647 []( INSPECTABLE* aItem ) { return false; } );
1649 _HKI( "Hyperlink" ),
1650 []( INSPECTABLE* aItem ) { return false; } );
1652 _HKI( "Knockout" ),
1653 []( INSPECTABLE* aItem ) { return false; } );
1654 }
1656
1658
1659
1661{
1663 {
1674
1675
1677 _HKI( "Visible" ),
1678 []( INSPECTABLE* aItem ) { return false; } );
1680 _HKI( "Text" ),
1681 []( INSPECTABLE* aItem ) { return false; } );
1683 _HKI( "Vertical Justification" ),
1684 []( INSPECTABLE* aItem ) { return false; } );
1686 _HKI( "Hyperlink" ),
1687 []( INSPECTABLE* aItem ) { return false; } );
1689 _HKI( "Knockout" ),
1690 []( INSPECTABLE* aItem ) { return false; } );
1691 }
1693
1694
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:109
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
BOX2< VECTOR2I > BOX2I
Definition: box2.h:853
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:226
PCB_LAYER_ID m_layer
Definition: board_item.h:388
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:260
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:231
virtual bool IsLocked() const
Definition: board_item.cpp:74
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:103
EDA_UNITS GetUserUnits()
Definition: board.h:662
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:120
const Vec & GetOrigin() const
Definition: box2.h:184
void SetX(coord_type val)
Definition: box2.h:236
const Vec GetCenter() const
Definition: box2.h:196
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:270
void SetY(coord_type val)
Definition: box2.h:241
coord_type GetY() const
Definition: box2.h:182
coord_type GetWidth() const
Definition: box2.h:188
void SetWidth(coord_type val)
Definition: box2.h:246
const Vec GetEnd() const
Definition: box2.h:186
bool Contains(const Vec &aPoint) const
Definition: box2.h:142
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:507
coord_type GetX() const
Definition: box2.h:181
coord_type GetRight() const
Definition: box2.h:190
void SetHeight(coord_type val)
Definition: box2.h:251
coord_type GetBottom() const
Definition: box2.h:191
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:589
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:209
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:255
double Sin() const
Definition: eda_angle.h:212
double AsDegrees() const
Definition: eda_angle.h:155
EDA_ANGLE Normalize180()
Definition: eda_angle.h:294
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:85
const KIID m_Uuid
Definition: eda_item.h:482
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:485
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
int GetTextHeight() const
Definition: eda_text.h:225
BOX2I GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:567
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:231
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:131
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:95
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:419
KIFONT::FONT * GetFont() const
Definition: eda_text.h:208
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:252
int GetTextWidth() const
Definition: eda_text.h:222
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:437
double Similarity(const EDA_TEXT &aOther) const
Definition: eda_text.cpp:1151
virtual void ClearRenderCache()
Definition: eda_text.cpp:499
bool IsMirrored() const
Definition: eda_text.h:151
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition: eda_text.cpp:324
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:985
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:183
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:205
int GetTextThickness() const
Definition: eda_text.h:123
bool operator==(const EDA_TEXT &aRhs) const
Definition: eda_text.h:354
static ENUM_MAP< T > & Instance()
Definition: property.h:653
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:36
static LSET SideSpecificMask()
Definition: lset.cpp:998
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 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 Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
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.
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.
static OPT_VECTOR2I segCircleIntersection(CIRCLE &aCircle, SEG &aSeg, bool aStart=true)
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.
bool m_keepTextAligned
Calculate text orientation to match dimension.
DIM_PRECISION GetPrecision() const
wxString GetPrefix() const
void SetSuffix(const wxString &aSuffix)
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
bool operator==(const BOARD_ITEM &aOther) const override
DIM_UNITS_MODE GetUnitsMode() const
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.
wxString m_valueString
Displayed value when m_overrideValue = true.
void ChangePrecision(DIM_PRECISION aPrecision)
bool m_overrideTextEnabled
Manually specify the displayed measurement value.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
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.
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.
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.
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.
virtual void Mirror(const VECTOR2I &axis_pos, bool aMirrorLeftRight=false)
Mirror the dimension relative to a given horizontal axis.
bool GetOverrideTextEnabled() const
void SetUnitsMode(DIM_UNITS_MODE aMode)
int m_arrowLength
Length of arrow shapes.
virtual const VECTOR2I & GetEnd() const
VECTOR2I m_end
Internal cache of drawn shapes.
void ChangeUnitsMode(DIM_UNITS_MODE aMode)
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 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.
void Mirror(const VECTOR2I &axis_pos, bool aMirrorLeftRight=false) override
Mirror the dimension relative to a given horizontal axis.
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 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:141
bool TextHitTest(const VECTOR2I &aPoint, int aAccuracy=0) const override
Test if aPoint is within the bounds of this object.
Definition: pcb_text.cpp:299
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_text.cpp:402
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition: property.h:252
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.
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:108
const VECTOR2I GetCenter() const
Definition: shape_circle.h:113
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)
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:265
extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector2d.h:457
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:350
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:437
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:432
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:431
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:436
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:440
static constexpr EDA_ANGLE FULL_CIRCLE
Definition: eda_angle.h:433
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:439
static constexpr EDA_ANGLE ANGLE_135
Definition: eda_angle.h:438
#define PCB_EDIT_FRAME_NAME
EDA_UNITS
Definition: eda_units.h:46
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ NONE
Definition: kibis.h:54
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:148
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Dwgs_User
Definition: layer_ids.h:110
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:634
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:243
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:110
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:139
wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
Definition: ui_common.cpp:210
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:192
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:424
static const EDA_ANGLE s_arrowAngle(27.5, DEGREES_T)
static struct DIMENSION_DESC _DIMENSION_DESC
#define INVERT(pos)
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_TEXT_BORDER
Frame to show around dimension text.
Definition: pcb_dimension.h:83
DIM_PRECISION
Definition: pcb_dimension.h:47
#define TYPE_HASH(x)
Definition: property.h:67
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition: property.h:755
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition: property.h:58
#define REGISTER_TYPE(x)
Definition: property_mgr.h:366
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:228
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
int sign(T val)
Definition: util.h:135
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588