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