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, FLIP_DIRECTION aFlipDirection )
369{
370 Mirror( aCentre, aFlipDirection );
371
373}
374
375
376void PCB_DIMENSION_BASE::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
377{
378 VECTOR2I newPos = GetTextPos();
379
380 MIRROR( newPos, axis_pos, aFlipDirection );
381
382 SetTextPos( newPos );
383
384 // invert angle
386
387 MIRROR( m_start, axis_pos, aFlipDirection );
388 MIRROR( m_end, axis_pos, aFlipDirection );
389
390 if( IsSideSpecific() )
392
393 Update();
394}
395
396
398 std::vector<MSG_PANEL_ITEM>& aList )
399{
400 // for now, display only the text within the DIMENSION using class PCB_TEXT.
401 wxString msg;
402
403 wxCHECK_RET( m_parent != nullptr, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
404
405 // Don't use GetShownText(); we want to see the variable references here
406 aList.emplace_back( _( "Dimension" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
407
408 aList.emplace_back( _( "Prefix" ), GetPrefix() );
409
411 {
412 aList.emplace_back( _( "Override Text" ), GetOverrideText() );
413 }
414 else
415 {
416 aList.emplace_back( _( "Value" ), GetValueText() );
417
418 switch( GetPrecision() )
419 {
420 case DIM_PRECISION::V_VV: msg = wxT( "0.00 in / 0 mils / 0.0 mm" ); break;
421 case DIM_PRECISION::V_VVV: msg = wxT( "0.000 in / 0 mils / 0.00 mm" ); break;
422 case DIM_PRECISION::V_VVVV: msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" ); break;
423 case DIM_PRECISION::V_VVVVV: msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
424 default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
425 }
426
427 aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
428 }
429
430 aList.emplace_back( _( "Suffix" ), GetSuffix() );
431
432 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
433 // in frame's units.
434 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
435 unitsProvider.SetUserUnits( GetUnits() );
436
437 aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( GetUnits() ) );
438
439 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
440 aList.emplace_back( _( "Text Thickness" ), unitsProvider.MessageTextFromValue( GetTextThickness() ) );
441 aList.emplace_back( _( "Text Width" ), unitsProvider.MessageTextFromValue( GetTextWidth() ) );
442 aList.emplace_back( _( "Text Height" ), unitsProvider.MessageTextFromValue( GetTextHeight() ) );
443
444 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
445
446 if( Type() == PCB_DIM_CENTER_T )
447 {
448 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
449 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
450 aFrame->MessageTextFromValue( startCoord.x ),
451 aFrame->MessageTextFromValue( startCoord.y ) );
452
453 aList.emplace_back( start, wxEmptyString );
454 }
455 else
456 {
457 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
458 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
459 aFrame->MessageTextFromValue( startCoord.x ),
460 aFrame->MessageTextFromValue( startCoord.y ) );
461 VECTOR2I endCoord = originTransforms.ToDisplayAbs( GetEnd() );
462 wxString end = wxString::Format( wxT( "@(%s, %s)" ),
463 aFrame->MessageTextFromValue( endCoord.x ),
464 aFrame->MessageTextFromValue( endCoord.y ) );
465
466 aList.emplace_back( start, end );
467 }
468
469 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
470 aList.emplace_back( _( "Status" ), _( "Locked" ) );
471
472 aList.emplace_back( _( "Layer" ), GetLayerName() );
473}
474
475
476std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
477{
478 std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
479
480 effectiveShape->AddShape( GetEffectiveTextShape()->Clone() );
481
482 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
483 effectiveShape->AddShape( shape->Clone() );
484
485 return effectiveShape;
486}
487
488
489bool PCB_DIMENSION_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
490{
491 if( TextHitTest( aPosition ) )
492 return true;
493
494 int dist_max = aAccuracy + ( m_lineThickness / 2 );
495
496 // Locate SEGMENTS
497
498 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
499 {
500 if( shape->Collide( aPosition, dist_max ) )
501 return true;
502 }
503
504 return false;
505}
506
507
508bool PCB_DIMENSION_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
509{
510 BOX2I arect = aRect;
511 arect.Inflate( aAccuracy );
512
513 BOX2I rect = GetBoundingBox();
514
515 if( aAccuracy )
516 rect.Inflate( aAccuracy );
517
518 if( aContained )
519 return arect.Contains( rect );
520
521 return arect.Intersects( rect );
522}
523
524
526{
527 BOX2I bBox;
528 int xmin, xmax, ymin, ymax;
529
530 bBox = GetTextBox();
531 xmin = bBox.GetX();
532 xmax = bBox.GetRight();
533 ymin = bBox.GetY();
534 ymax = bBox.GetBottom();
535
536 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
537 {
538 BOX2I shapeBox = shape->BBox();
539 shapeBox.Inflate( m_lineThickness / 2 );
540
541 xmin = std::min( xmin, shapeBox.GetOrigin().x );
542 xmax = std::max( xmax, shapeBox.GetEnd().x );
543 ymin = std::min( ymin, shapeBox.GetOrigin().y );
544 ymax = std::max( ymax, shapeBox.GetEnd().y );
545 }
546
547 bBox.SetX( xmin );
548 bBox.SetY( ymin );
549 bBox.SetWidth( xmax - xmin + 1 );
550 bBox.SetHeight( ymax - ymin + 1 );
551
552 bBox.Normalize();
553
554 return bBox;
555}
556
557
558wxString PCB_DIMENSION_BASE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
559{
560 return wxString::Format( _( "Dimension '%s' on %s" ),
561 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ),
562 GetLayerName() );
563}
564
565
566
568{
570 VECTOR2I( GetBoundingBox().GetSize() ) );
571 dimBBox.Merge( PCB_TEXT::ViewBBox() );
572
573 return dimBBox;
574}
575
576
578 bool aStart )
579{
580 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
581 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
582
583 if( aPoly.Contains( start ) )
584 return std::nullopt;
585
586 for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
587 {
588 if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
589 {
590 if( ( *intersection - start ).SquaredEuclideanNorm() <
591 ( endpoint - start ).SquaredEuclideanNorm() )
592 endpoint = *intersection;
593 }
594 }
595
596 if( start == endpoint )
597 return std::nullopt;
598
599 return OPT_VECTOR2I( endpoint );
600}
601
602
604{
605 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
606 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
607
608 if( aCircle.Contains( start ) )
609 return std::nullopt;
610
611 std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
612
613 for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
614 {
615 if( ( intersection - start ).SquaredEuclideanNorm() <
616 ( endpoint - start ).SquaredEuclideanNorm() )
617 endpoint = intersection;
618 }
619
620 if( start == endpoint )
621 return std::nullopt;
622
623 return OPT_VECTOR2I( endpoint );
624}
625
626
628 int aClearance, int aError, ERROR_LOC aErrorLoc,
629 bool aIgnoreLineWidth ) const
630{
631 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
632
633 for( const std::shared_ptr<SHAPE>& shape : m_shapes )
634 {
635 const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
636 const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
637
638 if( circle )
639 {
640 TransformCircleToPolygon( aBuffer, circle->GetCenter(),
641 circle->GetRadius() + m_lineThickness / 2 + aClearance,
642 aError, aErrorLoc );
643 }
644 else if( seg )
645 {
646 TransformOvalToPolygon( aBuffer, seg->GetSeg().A, seg->GetSeg().B,
647 m_lineThickness + 2 * aClearance, aError, aErrorLoc );
648 }
649 else
650 {
651 wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeToPolygon unknown shape type." ) );
652 }
653 }
654}
655
656
658 PCB_DIMENSION_BASE( aParent, aType ),
659 m_height( 0 )
660{
661 // To preserve look of old dimensions, initialize extension height based on default arrow length
662 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
663}
664
665
667{
668 return new PCB_DIM_ALIGNED( *this );
669}
670
671
673{
674 wxASSERT( aImage->Type() == Type() );
675
676 m_shapes.clear();
677 static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
678
679 std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
680
681 Update();
682}
683
684
685void PCB_DIM_ALIGNED::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
686{
688 // Call this last for the Update()
689 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
690}
691
692
694{
695 return BITMAPS::add_aligned_dimension;
696}
697
698
699void PCB_DIM_ALIGNED::UpdateHeight( const VECTOR2I& aCrossbarStart, const VECTOR2I& aCrossbarEnd )
700{
701 VECTOR2D height( aCrossbarStart - GetStart() );
702 VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
703
704 if( height.Cross( crossBar ) > 0 )
705 m_height = -height.EuclideanNorm();
706 else
707 m_height = height.EuclideanNorm();
708
709 Update();
710}
711
712
714{
715 m_shapes.clear();
716
717 VECTOR2I dimension( m_end - m_start );
718
719 m_measuredValue = KiROUND( dimension.EuclideanNorm() );
720
721 VECTOR2I extension;
722
723 if( m_height > 0 )
724 extension = VECTOR2I( -dimension.y, dimension.x );
725 else
726 extension = VECTOR2I( dimension.y, -dimension.x );
727
728 // Add extension lines
729 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
730
731 VECTOR2I extStart( m_start );
732 extStart += extension.Resize( m_extensionOffset );
733
734 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
735
736 extStart = VECTOR2I( m_end );
737 extStart += extension.Resize( m_extensionOffset );
738
739 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
740
741 // Add crossbar
742 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
743 m_crossBarStart = m_start + crossBarDistance;
744 m_crossBarEnd = m_end + crossBarDistance;
745
746 // Update text after calculating crossbar position but before adding crossbar lines
747 updateText();
748
749 // Now that we have the text updated, we can determine how to draw the crossbar.
750 // First we need to create an appropriate bounding polygon to collide with
752
753 SHAPE_POLY_SET polyBox;
754 polyBox.NewOutline();
755 polyBox.Append( textBox.GetOrigin() );
756 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
757 polyBox.Append( textBox.GetEnd() );
758 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
759 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
760
761 // The ideal crossbar, if the text doesn't collide
762 SEG crossbar( m_crossBarStart, m_crossBarEnd );
763
764 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
765 bool containsA = polyBox.Contains( crossbar.A );
766 bool containsB = polyBox.Contains( crossbar.B );
767
768 OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
769 OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
770
771 if( endpointA )
772 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
773
774 if( endpointB )
775 m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
776
777 if( !containsA && !containsB && !endpointA && !endpointB )
778 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
779
780 // Add arrows
781 VECTOR2I arrowEndPos( m_arrowLength, 0 );
782 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
783 RotatePoint( arrowEndPos, -EDA_ANGLE( dimension ) + s_arrowAngle );
784 RotatePoint( arrowEndNeg, -EDA_ANGLE( dimension ) - s_arrowAngle );
785
786 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndPos ) );
787 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndNeg ) );
788 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndPos ) );
789 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndNeg ) );
790}
791
792
794{
795 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
796
797 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
798 {
799 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
800 EDA_ANGLE rotation;
801
802 if( crossbarCenter.x == 0 )
803 rotation = ANGLE_90 * sign( -crossbarCenter.y );
804 else if( crossbarCenter.x < 0 )
805 rotation = -ANGLE_90;
806 else
807 rotation = ANGLE_90;
808
809 VECTOR2I textOffset = crossbarCenter;
810 RotatePoint( textOffset, rotation );
811 textOffset = crossbarCenter + textOffset.Resize( textOffsetDistance );
812
813 SetTextPos( m_crossBarStart + textOffset );
814 }
815 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
816 {
817 SetTextPos( m_crossBarStart + crossbarCenter );
818 }
819
821 {
822 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( crossbarCenter );
823 textAngle.Normalize();
824
825 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
826 textAngle -= ANGLE_180;
827
828 SetTextAngle( textAngle );
829 }
830
832}
833
834
835void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
836{
838
839 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
840 // in frame's units.
841 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
842 unitsProvider.SetUserUnits( GetUnits() );
843
844 aList.emplace_back( _( "Height" ), unitsProvider.MessageTextFromValue( m_height ) );
845}
846
847
850{
851 // To preserve look of old dimensions, initialize extension height based on default arrow length
852 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
854}
855
856
858{
859 return new PCB_DIM_ORTHOGONAL( *this );
860}
861
862
864{
865 wxASSERT( aImage->Type() == Type() );
866
867 m_shapes.clear();
868 static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
869
870 std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
871 *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
872
873 Update();
874}
875
876
877void PCB_DIM_ORTHOGONAL::Mirror( const VECTOR2I& axis_pos, FLIP_DIRECTION aFlipDirection )
878{
879 // Only reverse the height if the height is aligned with the flip
880 if( m_orientation == DIR::HORIZONTAL && aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
882 else if( m_orientation == DIR::VERTICAL && aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
884
885 // Call this last, as we need the Update()
886 PCB_DIMENSION_BASE::Mirror( axis_pos, aFlipDirection );
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 }
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
Definition: approximation.h:32
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
BOX2< VECTOR2I > BOX2I
Definition: box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition: box2.h:990
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:238
PCB_LAYER_ID m_layer
Definition: board_item.h:435
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:289
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:47
virtual bool IsLocked() const
Definition: board_item.cpp:75
bool IsSideSpecific() const
Definition: board_item.cpp:149
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:139
EDA_UNITS GetUserUnits()
Definition: board.h:701
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:558
constexpr void SetHeight(size_type val)
Definition: box2.h:292
constexpr const Vec GetEnd() const
Definition: box2.h:212
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:146
constexpr coord_type GetY() const
Definition: box2.h:208
constexpr size_type GetWidth() const
Definition: box2.h:214
constexpr coord_type GetX() const
Definition: box2.h:207
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:658
constexpr const Vec GetCenter() const
Definition: box2.h:230
constexpr bool Contains(const Vec &aPoint) const
Definition: box2.h:168
constexpr void SetWidth(size_type val)
Definition: box2.h:287
constexpr void SetX(coord_type val)
Definition: box2.h:277
constexpr const Vec & GetOrigin() const
Definition: box2.h:210
constexpr void SetY(coord_type val)
Definition: box2.h:282
constexpr coord_type GetRight() const
Definition: box2.h:217
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:311
constexpr coord_type GetBottom() const
Definition: box2.h:222
Represent basic circle geometry with utility geometry functions.
Definition: circle.h:33
std::vector< VECTOR2I > Intersect(const CIRCLE &aCircle) const
Compute the intersection points between this circle and aCircle.
Definition: circle.cpp:221
bool Contains(const VECTOR2I &aP) const
Return true if aP is on the circumference of this circle.
Definition: circle.cpp:188
EDA_ANGLE Normalize()
Definition: eda_angle.h:221
double Sin() const
Definition: eda_angle.h:170
double AsDegrees() const
Definition: eda_angle.h:113
EDA_ANGLE Normalize180()
Definition: eda_angle.h:260
ORIGIN_TRANSFORMS & GetOriginTransforms() override
Return a reference to the default ORIGIN_TRANSFORMS object.
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
const KIID m_Uuid
Definition: eda_item.h:489
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:500
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:79
int GetTextHeight() const
Definition: eda_text.h:247
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:253
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:130
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:94
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:449
KIFONT::FONT * GetFont() const
Definition: eda_text.h:230
BOX2I GetTextBox(int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:601
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:282
int GetTextWidth() const
Definition: eda_text.h:244
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:467
double Similarity(const EDA_TEXT &aOther) const
Definition: eda_text.cpp:1167
virtual void ClearRenderCache()
Definition: eda_text.cpp:529
bool IsMirrored() const
Definition: eda_text.h:173
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition: eda_text.cpp:354
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:1008
void SetTextAngleDegrees(double aOrientation)
Definition: eda_text.h:133
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:182
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:204
int GetTextThickness() const
Definition: eda_text.h:122
bool operator==(const EDA_TEXT &aRhs) const
Definition: eda_text.h:376
static ENUM_MAP< T > & Instance()
Definition: property.h:663
Class that other classes need to inherit from, in order to be inspectable.
Definition: inspectable.h:36
A class to perform either relative or absolute display origin transforms for a single axis of a point...
T ToDisplayAbs(const T &aValue) const
Abstract dimension API.
EDA_UNITS GetUnits() const
bool m_autoUnits
If true, follow the currently selected UI units.
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
void Update()
Update the dimension's cached text and geometry.
void ChangeSuffix(const wxString &aSuffix)
wxString GetOverrideText() const
wxString GetSuffix() const
std::vector< std::shared_ptr< SHAPE > > m_shapes
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
void ClearRenderCache() override
int m_lineThickness
Thickness used for all graphics in the dimension.
void Move(const VECTOR2I &offset) override
Move this object.
bool m_suppressZeroes
Suppress trailing zeroes.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
void SetUnits(EDA_UNITS aUnits)
DIM_PRECISION m_precision
Number of digits to display after decimal.
virtual void Mirror(const VECTOR2I &axis_pos, FLIP_DIRECTION aFlipDirection)
Mirror the dimension relative to a given horizontal axis.
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.
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 Mirror(const VECTOR2I &axis_pos, FLIP_DIRECTION aFlipDirection) override
Mirror the dimension relative to a given horizontal axis.
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
virtual void swapData(BOARD_ITEM *aImage) override
int m_extensionHeight
Length of extension lines past the crossbar.
VECTOR2I m_crossBarEnd
Crossbar end control point.
PCB_DIM_ALIGNED(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIM_ALIGNED_T)
void ChangeHeight(int aHeight)
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
int GetExtensionHeight() const
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Mark the center of a circle or arc with a cross shape.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
virtual void swapData(BOARD_ITEM *aImage) override
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
PCB_DIM_CENTER(BOARD_ITEM *aParent)
A leader is a dimension-like object pointing to a specific point.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
DIM_TEXT_BORDER m_textBorder
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
DIM_TEXT_BORDER GetTextBorder() const
virtual void swapData(BOARD_ITEM *aImage) override
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
PCB_DIM_LEADER(BOARD_ITEM *aParent)
void ChangeTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
void swapData(BOARD_ITEM *aImage) override
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
DIR m_orientation
What axis to lock the dimension line to.
void Mirror(const VECTOR2I &axis_pos, FLIP_DIRECTION aFlipDirection) override
Mirror the dimension relative to a given horizontal axis.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
PCB_DIM_ORTHOGONAL(BOARD_ITEM *aParent)
A radial dimension indicates either the radius or diameter of an arc or circle.
int GetLeaderLength() const
PCB_DIM_RADIAL(BOARD_ITEM *aParent)
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
virtual void swapData(BOARD_ITEM *aImage) override
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void ChangeLeaderLength(int aLength)
VECTOR2I GetKnee() const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pcb_text.cpp: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:403
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_text.cpp:506
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition: property.h:257
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition: property.h:268
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:87
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int GetRadius() const
Definition: shape_circle.h:118
const VECTOR2I GetCenter() const
Definition: shape_circle.h:123
Base class for iterating over all segments in a given SHAPE_POLY_SET.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
SEGMENT_ITERATOR IterateSegments(int aFirst, int aLast, bool aIterateHoles=false)
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
const SEG & GetSeg() const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector2d.h:542
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:283
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:385
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define _HKI(x)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:398
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:397
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:402
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:406
static constexpr EDA_ANGLE FULL_CIRCLE
Definition: eda_angle.h:399
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:405
static constexpr EDA_ANGLE ANGLE_135
Definition: eda_angle.h:404
#define PCB_EDIT_FRAME_NAME
EDA_UNITS
Definition: eda_units.h:46
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: layer_id.cpp:209
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:147
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Dwgs_User
Definition: layer_ids.h:107
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition: mirror.h:45
FLIP_DIRECTION
Definition: mirror.h:27
KICOMMON_API double ToUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Function To_User_Unit convert aValue in internal units to the appropriate user units defined by aUnit...
Definition: eda_units.cpp:259
KICOMMON_API wxString GetText(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:126
KICOMMON_API wxString GetLabel(EDA_UNITS aUnits, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
Get the units string for a given units type.
Definition: eda_units.cpp:155
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
Definition: ui_common.cpp:213
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
Definition: ui_common.cpp:195
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
static const EDA_ANGLE s_arrowAngle(27.5, DEGREES_T)
static struct DIMENSION_DESC _DIMENSION_DESC
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:229
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:78
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:103
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:104
constexpr int sign(T val)
Definition: util.h:159
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691