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 if( m_textPosition != other.m_textPosition )
75 return false;
76
78 return false;
79
80 if( m_units != other.m_units )
81 return false;
82
83 if( m_autoUnits != other.m_autoUnits )
84 return false;
85
86 if( m_unitsFormat != other.m_unitsFormat )
87 return false;
88
89 if( m_precision != other.m_precision )
90 return false;
91
93 return false;
94
95 if( m_lineThickness != other.m_lineThickness )
96 return false;
97
98 if( m_arrowLength != other.m_arrowLength )
99 return false;
100
102 return false;
103
104 if( m_measuredValue != other.m_measuredValue )
105 return false;
106
107 return EDA_TEXT::operator==( other );
108}
109
110
111double PCB_DIMENSION_BASE::Similarity( const BOARD_ITEM& aOther ) const
112{
113 if( m_Uuid == aOther.m_Uuid )
114 return 1.0;
115
116 if( Type() != aOther.Type() )
117 return 0.0;
118
119 const PCB_DIMENSION_BASE& other = static_cast<const PCB_DIMENSION_BASE&>( aOther );
120
121 double similarity = 1.0;
122
123 if( m_textPosition != other.m_textPosition )
124 similarity *= 0.9;
125
127 similarity *= 0.9;
128
129 if( m_units != other.m_units )
130 similarity *= 0.9;
131
132 if( m_autoUnits != other.m_autoUnits )
133 similarity *= 0.9;
134
135 if( m_unitsFormat != other.m_unitsFormat )
136 similarity *= 0.9;
137
138 if( m_precision != other.m_precision )
139 similarity *= 0.9;
140
142 similarity *= 0.9;
143
144 if( m_lineThickness != other.m_lineThickness )
145 similarity *= 0.9;
146
147 if( m_arrowLength != other.m_arrowLength )
148 similarity *= 0.9;
149
151 similarity *= 0.9;
152
153 if( m_measuredValue != other.m_measuredValue )
154 similarity *= 0.9;
155
156 similarity *= EDA_TEXT::Similarity( other );
157
158 return similarity;
159}
160
161
163{
165
166 switch( m_unitsFormat )
167 {
168 case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
169 break;
170
171 case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
173 break;
174
175 case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
176 text += wxT( " (" ) + EDA_UNIT_UTILS::GetText( m_units ).Trim( false ) + wxT( ")" );
177 break;
178 }
179
180 text.Prepend( m_prefix );
181 text.Append( m_suffix );
182
183 SetText( text );
184}
185
186
188{
190
191 // We use EDA_TEXT::ClearRenderCache() as a signal that the properties of the EDA_TEXT
192 // have changed and we may need to update the dimension text
193
195 {
197 updateText();
198 m_inClearRenderCache = false;
199 }
200}
201
202
203template<typename ShapeType>
204void PCB_DIMENSION_BASE::addShape( const ShapeType& aShape )
205{
206 m_shapes.push_back( std::make_shared<ShapeType>( aShape ) );
207}
208
209
211{
212 struct lconv* lc = localeconv();
213 wxChar sep = lc->decimal_point[0];
214
215 int val = GetMeasuredValue();
216 int precision = static_cast<int>( m_precision );
217 wxString text;
218
219 if( precision >= 6 )
220 {
221 switch( m_units )
222 {
223 case EDA_UNITS::INCHES: precision = precision - 4; break;
224 case EDA_UNITS::MILS: precision = std::max( 0, precision - 7 ); break;
225 case EDA_UNITS::MILLIMETRES: precision = precision - 5; break;
226 default: precision = precision - 4; break;
227 }
228 }
229
230 wxString format = wxT( "%." ) + wxString::Format( wxT( "%i" ), precision ) + wxT( "f" );
231
232 text.Printf( format, EDA_UNIT_UTILS::UI::ToUserUnit( pcbIUScale, m_units, val ) );
233
234 if( m_suppressZeroes )
235 {
236 while( text.Last() == '0' )
237 {
238 text.RemoveLast();
239
240 if( text.Last() == '.' || text.Last() == sep )
241 {
242 text.RemoveLast();
243 break;
244 }
245 }
246 }
247
248 return text;
249}
250
251
252void PCB_DIMENSION_BASE::SetPrefix( const wxString& aPrefix )
253{
254 m_prefix = aPrefix;
255}
256
257
258void PCB_DIMENSION_BASE::SetSuffix( const wxString& aSuffix )
259{
260 m_suffix = aSuffix;
261}
262
263
265{
266 m_units = aUnits;
267}
268
269
271{
272 if( m_autoUnits )
273 {
274 return DIM_UNITS_MODE::AUTOMATIC;
275 }
276 else
277 {
278 switch( m_units )
279 {
280 default:
281 case EDA_UNITS::INCHES: return DIM_UNITS_MODE::INCHES;
282 case EDA_UNITS::MILLIMETRES: return DIM_UNITS_MODE::MILLIMETRES;
283 case EDA_UNITS::MILS: return DIM_UNITS_MODE::MILS;
284 }
285 }
286}
287
288
290{
291 switch( aMode )
292 {
293 case DIM_UNITS_MODE::INCHES:
294 m_autoUnits = false;
295 m_units = EDA_UNITS::INCHES;
296 break;
297
298 case DIM_UNITS_MODE::MILS:
299 m_autoUnits = false;
300 m_units = EDA_UNITS::MILS;
301 break;
302
303 case DIM_UNITS_MODE::MILLIMETRES:
304 m_autoUnits = false;
305 m_units = EDA_UNITS::MILLIMETRES;
306 break;
307
308 case DIM_UNITS_MODE::AUTOMATIC:
309 m_autoUnits = true;
310 m_units = GetBoard() ? GetBoard()->GetUserUnits() : EDA_UNITS::MILLIMETRES;
311 break;
312 }
313}
314
315
317{
318 PCB_TEXT::Offset( offset );
319
320 m_start += offset;
321 m_end += offset;
322
323 Update();
324}
325
326
327void PCB_DIMENSION_BASE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
328{
329 EDA_ANGLE newAngle = GetTextAngle() + aAngle;
330
331 newAngle.Normalize();
332
333 SetTextAngle( newAngle );
334
335 VECTOR2I pt = GetTextPos();
336 RotatePoint( pt, aRotCentre, aAngle );
337 SetTextPos( pt );
338
339 RotatePoint( m_start, aRotCentre, aAngle );
340 RotatePoint( m_end, aRotCentre, aAngle );
341
342 Update();
343}
344
345
346void PCB_DIMENSION_BASE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
347{
348 Mirror( aCentre );
349
350 SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) );
351}
352
353
354void PCB_DIMENSION_BASE::Mirror( const VECTOR2I& axis_pos, bool aMirrorLeftRight )
355{
356 int axis = aMirrorLeftRight ? axis_pos.x : axis_pos.y;
357 VECTOR2I newPos = GetTextPos();
358
359#define INVERT( pos ) ( ( pos ) = axis - ( ( pos ) - axis ) )
360 if( aMirrorLeftRight )
361 INVERT( newPos.x );
362 else
363 INVERT( newPos.y );
364
365 SetTextPos( newPos );
366
367 // invert angle
369
370 if( aMirrorLeftRight )
371 {
372 INVERT( m_start.x );
373 INVERT( m_end.x );
374 }
375 else
376 {
377 INVERT( m_start.y );
378 INVERT( m_end.y );
379 }
380
381 if( ( GetLayerSet() & LSET::SideSpecificMask() ).any() )
383
384 Update();
385}
386
387
389 std::vector<MSG_PANEL_ITEM>& aList )
390{
391 // for now, display only the text within the DIMENSION using class PCB_TEXT.
392 wxString msg;
393
394 wxCHECK_RET( m_parent != nullptr, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
395
396 // Don't use GetShownText(); we want to see the variable references here
397 aList.emplace_back( _( "Dimension" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
398
399 aList.emplace_back( _( "Prefix" ), GetPrefix() );
400
402 {
403 aList.emplace_back( _( "Override Text" ), GetOverrideText() );
404 }
405 else
406 {
407 aList.emplace_back( _( "Value" ), GetValueText() );
408
409 switch( GetPrecision() )
410 {
411 case DIM_PRECISION::V_VV: msg = wxT( "0.00 in / 0 mils / 0.0 mm" ); break;
412 case DIM_PRECISION::V_VVV: msg = wxT( "0.000 in / 0 mils / 0.00 mm" ); break;
413 case DIM_PRECISION::V_VVVV: msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" ); break;
414 case DIM_PRECISION::V_VVVVV: msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
415 default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
416 }
417
418 aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
419 }
420
421 aList.emplace_back( _( "Suffix" ), GetSuffix() );
422
423 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
424 // in frame's units.
425 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
426 unitsProvider.SetUserUnits( GetUnits() );
427
428 aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( GetUnits() ) );
429
430 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
431 aList.emplace_back( _( "Text Thickness" ), unitsProvider.MessageTextFromValue( GetTextThickness() ) );
432 aList.emplace_back( _( "Text Width" ), unitsProvider.MessageTextFromValue( GetTextWidth() ) );
433 aList.emplace_back( _( "Text Height" ), unitsProvider.MessageTextFromValue( GetTextHeight() ) );
434
435 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
436
437 if( Type() == PCB_DIM_CENTER_T )
438 {
439 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
440 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
441 aFrame->MessageTextFromValue( startCoord.x ),
442 aFrame->MessageTextFromValue( startCoord.y ) );
443
444 aList.emplace_back( start, wxEmptyString );
445 }
446 else
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 VECTOR2I endCoord = originTransforms.ToDisplayAbs( GetEnd() );
453 wxString end = wxString::Format( wxT( "@(%s, %s)" ),
454 aFrame->MessageTextFromValue( endCoord.x ),
455 aFrame->MessageTextFromValue( endCoord.y ) );
456
457 aList.emplace_back( start, end );
458 }
459
460 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
461 aList.emplace_back( _( "Status" ), _( "Locked" ) );
462
463 aList.emplace_back( _( "Layer" ), GetLayerName() );
464}
465
466
467std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
468{
469 std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
470
471 effectiveShape->AddShape( GetEffectiveTextShape()->Clone() );
472
473 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
474 effectiveShape->AddShape( shape->Clone() );
475
476 return effectiveShape;
477}
478
479
480bool PCB_DIMENSION_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
481{
482 if( TextHitTest( aPosition ) )
483 return true;
484
485 int dist_max = aAccuracy + ( m_lineThickness / 2 );
486
487 // Locate SEGMENTS
488
489 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
490 {
491 if( shape->Collide( aPosition, dist_max ) )
492 return true;
493 }
494
495 return false;
496}
497
498
499bool PCB_DIMENSION_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
500{
501 BOX2I arect = aRect;
502 arect.Inflate( aAccuracy );
503
504 BOX2I rect = GetBoundingBox();
505
506 if( aAccuracy )
507 rect.Inflate( aAccuracy );
508
509 if( aContained )
510 return arect.Contains( rect );
511
512 return arect.Intersects( rect );
513}
514
515
517{
518 BOX2I bBox;
519 int xmin, xmax, ymin, ymax;
520
521 bBox = GetTextBox();
522 xmin = bBox.GetX();
523 xmax = bBox.GetRight();
524 ymin = bBox.GetY();
525 ymax = bBox.GetBottom();
526
527 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
528 {
529 BOX2I shapeBox = shape->BBox();
530 shapeBox.Inflate( m_lineThickness / 2 );
531
532 xmin = std::min( xmin, shapeBox.GetOrigin().x );
533 xmax = std::max( xmax, shapeBox.GetEnd().x );
534 ymin = std::min( ymin, shapeBox.GetOrigin().y );
535 ymax = std::max( ymax, shapeBox.GetEnd().y );
536 }
537
538 bBox.SetX( xmin );
539 bBox.SetY( ymin );
540 bBox.SetWidth( xmax - xmin + 1 );
541 bBox.SetHeight( ymax - ymin + 1 );
542
543 bBox.Normalize();
544
545 return bBox;
546}
547
548
550{
551 return wxString::Format( _( "Dimension '%s' on %s" ),
553 GetLayerName() );
554}
555
556
557
559{
561 VECTOR2I( GetBoundingBox().GetSize() ) );
562 dimBBox.Merge( PCB_TEXT::ViewBBox() );
563
564 return dimBBox;
565}
566
567
569 bool aStart )
570{
571 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
572 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
573
574 if( aPoly.Contains( start ) )
575 return std::nullopt;
576
577 for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
578 {
579 if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
580 {
581 if( ( *intersection - start ).SquaredEuclideanNorm() <
582 ( endpoint - start ).SquaredEuclideanNorm() )
583 endpoint = *intersection;
584 }
585 }
586
587 if( start == endpoint )
588 return std::nullopt;
589
590 return OPT_VECTOR2I( endpoint );
591}
592
593
595{
596 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
597 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
598
599 if( aCircle.Contains( start ) )
600 return std::nullopt;
601
602 std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
603
604 for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
605 {
606 if( ( intersection - start ).SquaredEuclideanNorm() <
607 ( endpoint - start ).SquaredEuclideanNorm() )
608 endpoint = intersection;
609 }
610
611 if( start == endpoint )
612 return std::nullopt;
613
614 return OPT_VECTOR2I( endpoint );
615}
616
617
619 int aClearance, int aError, ERROR_LOC aErrorLoc,
620 bool aIgnoreLineWidth ) const
621{
622 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
623
624 for( const std::shared_ptr<SHAPE>& shape : m_shapes )
625 {
626 const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
627 const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
628
629 if( circle )
630 {
631 TransformCircleToPolygon( aBuffer, circle->GetCenter(),
632 circle->GetRadius() + m_lineThickness / 2 + aClearance,
633 aError, aErrorLoc );
634 }
635 else if( seg )
636 {
637 TransformOvalToPolygon( aBuffer, seg->GetSeg().A, seg->GetSeg().B,
638 m_lineThickness + 2 * aClearance, aError, aErrorLoc );
639 }
640 else
641 {
642 wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeToPolygon unknown shape type." ) );
643 }
644 }
645}
646
647
649 PCB_DIMENSION_BASE( aParent, aType ),
650 m_height( 0 )
651{
652 // To preserve look of old dimensions, initialize extension height based on default arrow length
653 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
654}
655
656
658{
659 return new PCB_DIM_ALIGNED( *this );
660}
661
662
664{
665 wxASSERT( aImage->Type() == Type() );
666
667 m_shapes.clear();
668 static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
669
670 std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
671
672 Update();
673}
674
675
676void PCB_DIM_ALIGNED::Mirror( const VECTOR2I& axis_pos, bool aMirrorLeftRight )
677{
678 PCB_DIMENSION_BASE::Mirror( axis_pos, aMirrorLeftRight );
679
681}
682
683
685{
686 return BITMAPS::add_aligned_dimension;
687}
688
689
690void PCB_DIM_ALIGNED::UpdateHeight( const VECTOR2I& aCrossbarStart, const VECTOR2I& aCrossbarEnd )
691{
692 VECTOR2D height( aCrossbarStart - GetStart() );
693 VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
694
695 if( height.Cross( crossBar ) > 0 )
696 m_height = -height.EuclideanNorm();
697 else
698 m_height = height.EuclideanNorm();
699
700 Update();
701}
702
703
705{
706 m_shapes.clear();
707
708 VECTOR2I dimension( m_end - m_start );
709
710 m_measuredValue = KiROUND( dimension.EuclideanNorm() );
711
712 VECTOR2I extension;
713
714 if( m_height > 0 )
715 extension = VECTOR2I( -dimension.y, dimension.x );
716 else
717 extension = VECTOR2I( dimension.y, -dimension.x );
718
719 // Add extension lines
720 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
721
722 VECTOR2I extStart( m_start );
723 extStart += extension.Resize( m_extensionOffset );
724
725 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
726
727 extStart = VECTOR2I( m_end );
728 extStart += extension.Resize( m_extensionOffset );
729
730 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
731
732 // Add crossbar
733 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
734 m_crossBarStart = m_start + crossBarDistance;
735 m_crossBarEnd = m_end + crossBarDistance;
736
737 // Update text after calculating crossbar position but before adding crossbar lines
738 updateText();
739
740 // Now that we have the text updated, we can determine how to draw the crossbar.
741 // First we need to create an appropriate bounding polygon to collide with
743
744 SHAPE_POLY_SET polyBox;
745 polyBox.NewOutline();
746 polyBox.Append( textBox.GetOrigin() );
747 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
748 polyBox.Append( textBox.GetEnd() );
749 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
750 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
751
752 // The ideal crossbar, if the text doesn't collide
753 SEG crossbar( m_crossBarStart, m_crossBarEnd );
754
755 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
756 bool containsA = polyBox.Contains( crossbar.A );
757 bool containsB = polyBox.Contains( crossbar.B );
758
759 OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
760 OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
761
762 if( endpointA )
763 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
764
765 if( endpointB )
766 m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
767
768 if( !containsA && !containsB && !endpointA && !endpointB )
769 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
770
771 // Add arrows
772 VECTOR2I arrowEndPos( m_arrowLength, 0 );
773 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
774 RotatePoint( arrowEndPos, -EDA_ANGLE( dimension ) + s_arrowAngle );
775 RotatePoint( arrowEndNeg, -EDA_ANGLE( dimension ) - s_arrowAngle );
776
777 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndPos ) );
778 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndNeg ) );
779 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndPos ) );
780 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndNeg ) );
781}
782
783
785{
786 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
787
788 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
789 {
790 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
791 EDA_ANGLE rotation;
792
793 if( crossbarCenter.x == 0 )
794 rotation = ANGLE_90 * sign( -crossbarCenter.y );
795 else if( crossbarCenter.x < 0 )
796 rotation = -ANGLE_90;
797 else
798 rotation = ANGLE_90;
799
800 VECTOR2I textOffset = crossbarCenter;
801 RotatePoint( textOffset, rotation );
802 textOffset = crossbarCenter + textOffset.Resize( textOffsetDistance );
803
804 SetTextPos( m_crossBarStart + textOffset );
805 }
806 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
807 {
808 SetTextPos( m_crossBarStart + crossbarCenter );
809 }
810
812 {
813 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( crossbarCenter );
814 textAngle.Normalize();
815
816 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
817 textAngle -= ANGLE_180;
818
819 SetTextAngle( textAngle );
820 }
821
823}
824
825
826void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
827{
829
830 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
831 // in frame's units.
832 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
833 unitsProvider.SetUserUnits( GetUnits() );
834
835 aList.emplace_back( _( "Height" ), unitsProvider.MessageTextFromValue( m_height ) );
836}
837
838
841{
842 // To preserve look of old dimensions, initialize extension height based on default arrow length
843 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
845}
846
847
849{
850 return new PCB_DIM_ORTHOGONAL( *this );
851}
852
853
855{
856 wxASSERT( aImage->Type() == Type() );
857
858 m_shapes.clear();
859 static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
860
861 std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
862 *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
863
864 Update();
865}
866
867
869{
870 return BITMAPS::add_orthogonal_dimension;
871}
872
873
875{
876 m_shapes.clear();
877
879 m_end.y - m_start.y );
881
882 VECTOR2I extension;
883
885 extension = VECTOR2I( 0, m_height );
886 else
887 extension = VECTOR2I( m_height, 0 );
888
889 // Add first extension line
890 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
891
892 VECTOR2I extStart( m_start );
893 extStart += extension.Resize( m_extensionOffset );
894
895 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
896
897 // Add crossbar
898 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
899 m_crossBarStart = m_start + crossBarDistance;
900
903 else
905
906 // Add second extension line (m_end to crossbar end)
908 extension = VECTOR2I( 0, m_end.y - m_crossBarEnd.y );
909 else
910 extension = VECTOR2I( m_end.x - m_crossBarEnd.x, 0 );
911
912 extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
913
914 extStart = VECTOR2I( m_crossBarEnd );
915 extStart -= extension.Resize( m_extensionHeight );
916
917 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
918
919 // Update text after calculating crossbar position but before adding crossbar lines
920 updateText();
921
922 // Now that we have the text updated, we can determine how to draw the crossbar.
923 // First we need to create an appropriate bounding polygon to collide with
925
926 SHAPE_POLY_SET polyBox;
927 polyBox.NewOutline();
928 polyBox.Append( textBox.GetOrigin() );
929 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
930 polyBox.Append( textBox.GetEnd() );
931 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
932 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
933
934 // The ideal crossbar, if the text doesn't collide
935 SEG crossbar( m_crossBarStart, m_crossBarEnd );
936
937 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
938 bool containsA = polyBox.Contains( crossbar.A );
939 bool containsB = polyBox.Contains( crossbar.B );
940
941 OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
942 OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
943
944 if( endpointA )
945 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
946
947 if( endpointB )
948 m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
949
950 if( !containsA && !containsB && !endpointA && !endpointB )
951 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
952
953 // Add arrows
954 EDA_ANGLE crossBarAngle( m_crossBarEnd - m_crossBarStart );
955 VECTOR2I arrowEndPos( m_arrowLength, 0 );
956 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
957 RotatePoint( arrowEndPos, -crossBarAngle + s_arrowAngle );
958 RotatePoint( arrowEndNeg, -crossBarAngle - s_arrowAngle );
959
960 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndPos ) );
961 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndNeg ) );
962 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndPos ) );
963 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndNeg ) );
964}
965
966
968{
969 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
970
971 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
972 {
973 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
974
975 VECTOR2I textOffset;
976
978 textOffset.y = -textOffsetDistance;
979 else
980 textOffset.x = -textOffsetDistance;
981
982 textOffset += crossbarCenter;
983
984 SetTextPos( m_crossBarStart + textOffset );
985 }
986 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
987 {
988 SetTextPos( m_crossBarStart + crossbarCenter );
989 }
990
992 {
993 if( abs( crossbarCenter.x ) > abs( crossbarCenter.y ) )
995 else
997 }
998
1000}
1001
1002
1003void PCB_DIM_ORTHOGONAL::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1004{
1005 EDA_ANGLE angle( aAngle );
1006
1007 // restrict angle to -179.9 to 180.0 degrees
1008 angle.Normalize180();
1009
1010 // adjust orientation and height to new angle
1011 // we can only handle the cases of -90, 0, 90, 180 degrees exactly;
1012 // in the other cases we will use the nearest 90 degree angle to
1013 // choose at least an approximate axis for the target orientation
1014 // In case of exactly 45 or 135 degrees, we will round towards zero for consistency
1015 if( angle > ANGLE_45 && angle <= ANGLE_135 )
1016 {
1017 // about 90 degree
1019 {
1021 }
1022 else
1023 {
1025 m_height = -m_height;
1026 }
1027 }
1028 else if( angle < -ANGLE_45 && angle >= -ANGLE_135 )
1029 {
1030 // about -90 degree
1032 {
1034 m_height = -m_height;
1035 }
1036 else
1037 {
1039 }
1040 }
1041 else if( angle > ANGLE_135 || angle < -ANGLE_135 )
1042 {
1043 // about 180 degree
1044 m_height = -m_height;
1045 }
1046
1047 // this will update m_crossBarStart and m_crossbarEnd
1048 PCB_DIMENSION_BASE::Rotate( aRotCentre, angle );
1049}
1050
1051
1054 m_textBorder( DIM_TEXT_BORDER::NONE )
1055{
1056 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1057 m_overrideTextEnabled = true;
1058 m_keepTextAligned = false;
1059
1060 SetOverrideText( _( "Leader" ) );
1061}
1062
1063
1065{
1066 return new PCB_DIM_LEADER( *this );
1067}
1068
1069
1071{
1072 wxASSERT( aImage->Type() == Type() );
1073
1074 m_shapes.clear();
1075 static_cast<PCB_DIM_LEADER*>( aImage )->m_shapes.clear();
1076
1077 std::swap( *static_cast<PCB_DIM_LEADER*>( this ), *static_cast<PCB_DIM_LEADER*>( aImage ) );
1078
1079 Update();
1080}
1081
1082
1084{
1085 return BITMAPS::add_leader;
1086}
1087
1088
1090{
1091 // Our geometry is dependent on the size of the text, so just update the whole shebang
1093}
1094
1095
1097{
1098 m_shapes.clear();
1099
1101
1102 // Now that we have the text updated, we can determine how to draw the second line
1103 // First we need to create an appropriate bounding polygon to collide with
1104 BOX2I textBox = GetTextBox().Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() * 2 );
1105
1106 SHAPE_POLY_SET polyBox;
1107 polyBox.NewOutline();
1108 polyBox.Append( textBox.GetOrigin() );
1109 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1110 polyBox.Append( textBox.GetEnd() );
1111 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1112 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1113
1114 VECTOR2I firstLine( m_end - m_start );
1115 VECTOR2I start( m_start );
1116 start += firstLine.Resize( m_extensionOffset );
1117
1118 SEG arrowSeg( m_start, m_end );
1119 SEG textSeg( m_end, GetTextPos() );
1120 OPT_VECTOR2I arrowSegEnd;
1121 OPT_VECTOR2I textSegEnd;
1122
1123 if( m_textBorder == DIM_TEXT_BORDER::CIRCLE )
1124 {
1125 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1126 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1127 CIRCLE circle( textBox.GetCenter(), radius );
1128
1129 arrowSegEnd = segCircleIntersection( circle, arrowSeg );
1130 textSegEnd = segCircleIntersection( circle, textSeg );
1131 }
1132 else
1133 {
1134 arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1135 textSegEnd = segPolyIntersection( polyBox, textSeg );
1136 }
1137
1138 if( !arrowSegEnd )
1139 arrowSegEnd = m_end;
1140
1141 m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
1142
1143 // Add arrows
1144 VECTOR2I arrowEndPos( m_arrowLength, 0 );
1145 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
1146 RotatePoint( arrowEndPos, -EDA_ANGLE( firstLine ) + s_arrowAngle );
1147 RotatePoint( arrowEndNeg, -EDA_ANGLE( firstLine ) - s_arrowAngle );
1148
1149 m_shapes.emplace_back( new SHAPE_SEGMENT( start, start + arrowEndPos ) );
1150 m_shapes.emplace_back( new SHAPE_SEGMENT( start, start + arrowEndNeg ) );
1151
1152
1153 if( !GetText().IsEmpty() )
1154 {
1155 switch( m_textBorder )
1156 {
1157 case DIM_TEXT_BORDER::RECTANGLE:
1158 {
1159 for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
1160 m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
1161
1162 break;
1163 }
1164
1165 case DIM_TEXT_BORDER::CIRCLE:
1166 {
1167 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1168 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1169 m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
1170
1171 break;
1172 }
1173
1174 default:
1175 break;
1176 }
1177 }
1178
1179 if( textSegEnd && *arrowSegEnd == m_end )
1180 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textSegEnd ) );
1181}
1182
1183
1184void PCB_DIM_LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1185{
1186 // Don't use GetShownText(); we want to see the variable references here
1187 aList.emplace_back( _( "Leader" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
1188
1189 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
1190
1191 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
1192 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
1193 aFrame->MessageTextFromValue( startCoord.x ),
1194 aFrame->MessageTextFromValue( startCoord.y ) );
1195
1196 aList.emplace_back( start, wxEmptyString );
1197
1198 aList.emplace_back( _( "Layer" ), GetLayerName() );
1199}
1200
1201
1204{
1205 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1206 m_overrideTextEnabled = false;
1207 m_keepTextAligned = true;
1208 m_isDiameter = false;
1209 m_prefix = "R ";
1211}
1212
1213
1215{
1216 return new PCB_DIM_RADIAL( *this );
1217}
1218
1219
1221{
1222 wxASSERT( aImage->Type() == Type() );
1223
1224 m_shapes.clear();
1225 static_cast<PCB_DIM_RADIAL*>( aImage )->m_shapes.clear();
1226
1227 std::swap( *static_cast<PCB_DIM_RADIAL*>( this ), *static_cast<PCB_DIM_RADIAL*>( aImage ) );
1228
1229 Update();
1230}
1231
1232
1234{
1235 return BITMAPS::add_radial_dimension;
1236}
1237
1238
1240{
1241 VECTOR2I radial( m_end - m_start );
1242
1243 return m_end + radial.Resize( m_leaderLength );
1244}
1245
1246
1248{
1249 if( m_keepTextAligned )
1250 {
1251 VECTOR2I textLine( GetTextPos() - GetKnee() );
1252 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( textLine );
1253
1254 textAngle.Normalize();
1255
1256 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1257 textAngle -= ANGLE_180;
1258
1259 // Round to nearest degree
1260 textAngle = EDA_ANGLE( KiROUND( textAngle.AsDegrees() ), DEGREES_T );
1261
1262 SetTextAngle( textAngle );
1263 }
1264
1266}
1267
1268
1270{
1271 m_shapes.clear();
1272
1273 VECTOR2I center( m_start );
1274 VECTOR2I centerArm( 0, m_arrowLength );
1275
1276 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1277
1278 RotatePoint( centerArm, -ANGLE_90 );
1279
1280 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1281
1282 VECTOR2I radius( m_end - m_start );
1283
1284 if( m_isDiameter )
1285 m_measuredValue = KiROUND( radius.EuclideanNorm() * 2 );
1286 else
1288
1289 updateText();
1290
1291 // Now that we have the text updated, we can determine how to draw the second line
1292 // First we need to create an appropriate bounding polygon to collide with
1294
1295 SHAPE_POLY_SET polyBox;
1296 polyBox.NewOutline();
1297 polyBox.Append( textBox.GetOrigin() );
1298 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1299 polyBox.Append( textBox.GetEnd() );
1300 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1301 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1302
1303 VECTOR2I radial( m_end - m_start );
1304 radial = radial.Resize( m_leaderLength );
1305
1306 SEG arrowSeg( m_end, m_end + radial );
1307 SEG textSeg( arrowSeg.B, GetTextPos() );
1308
1309 OPT_VECTOR2I arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1310 OPT_VECTOR2I textSegEnd = segPolyIntersection( polyBox, textSeg );
1311
1312 if( arrowSegEnd )
1313 arrowSeg.B = *arrowSegEnd;
1314
1315 if( textSegEnd )
1316 textSeg.B = *textSegEnd;
1317
1318 m_shapes.emplace_back( new SHAPE_SEGMENT( arrowSeg ) );
1319
1320 // Add arrows
1321 VECTOR2I arrowEndPos( m_arrowLength, 0 );
1322 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
1323 RotatePoint( arrowEndPos, -EDA_ANGLE( radial ) + s_arrowAngle );
1324 RotatePoint( arrowEndNeg, -EDA_ANGLE( radial ) - s_arrowAngle );
1325
1326 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, m_end + arrowEndPos ) );
1327 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, m_end + arrowEndNeg ) );
1328
1329 m_shapes.emplace_back( new SHAPE_SEGMENT( textSeg ) );
1330}
1331
1332
1335{
1336 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1337 m_overrideTextEnabled = true;
1338}
1339
1340
1342{
1343 return new PCB_DIM_CENTER( *this );
1344}
1345
1346
1348{
1349 wxASSERT( aImage->Type() == Type() );
1350
1351 std::swap( *static_cast<PCB_DIM_CENTER*>( this ), *static_cast<PCB_DIM_CENTER*>( aImage ) );
1352}
1353
1354
1356{
1357 return BITMAPS::add_center_dimension;
1358}
1359
1360
1362{
1363 int halfWidth = VECTOR2I( m_end - m_start ).x + ( m_lineThickness / 2.0 );
1364
1365 BOX2I bBox;
1366
1367 bBox.SetX( m_start.x - halfWidth );
1368 bBox.SetY( m_start.y - halfWidth );
1369 bBox.SetWidth( halfWidth * 2 );
1370 bBox.SetHeight( halfWidth * 2 );
1371
1372 bBox.Normalize();
1373
1374 return bBox;
1375}
1376
1377
1379{
1381 VECTOR2I( GetBoundingBox().GetSize() ) );
1382}
1383
1384
1386{
1387 m_shapes.clear();
1388
1389 VECTOR2I center( m_start );
1390 VECTOR2I arm( m_end - m_start );
1391
1392 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1393
1394 RotatePoint( arm, -ANGLE_90 );
1395
1396 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1397}
1398
1399
1400static struct DIMENSION_DESC
1401{
1403 {
1405 .Map( DIM_PRECISION::X, _HKI( "0" ) )
1406 .Map( DIM_PRECISION::X_X, _HKI( "0.0" ) )
1407 .Map( DIM_PRECISION::X_XX, _HKI( "0.00" ) )
1408 .Map( DIM_PRECISION::X_XXX, _HKI( "0.000" ) )
1409 .Map( DIM_PRECISION::X_XXXX, _HKI( "0.0000" ) )
1410 .Map( DIM_PRECISION::X_XXXXX, _HKI( "0.00000" ) )
1411 .Map( DIM_PRECISION::V_VV, _HKI( "0.00 in / 0 mils / 0.0 mm" ) )
1412 .Map( DIM_PRECISION::V_VVV, _HKI( "0.000 / 0 / 0.00" ) )
1413 .Map( DIM_PRECISION::V_VVVV, _HKI( "0.0000 / 0.0 / 0.000" ) )
1414 .Map( DIM_PRECISION::V_VVVVV, _HKI( "0.00000 / 0.00 / 0.0000" ) );
1415
1417 .Map( DIM_UNITS_FORMAT::NO_SUFFIX, _HKI( "1234.0" ) )
1418 .Map( DIM_UNITS_FORMAT::BARE_SUFFIX, _HKI( "1234.0 mm" ) )
1419 .Map( DIM_UNITS_FORMAT::PAREN_SUFFIX, _HKI( "1234.0 (mm)" ) );
1420
1422 .Map( DIM_UNITS_MODE::INCHES, _HKI( "Inches" ) )
1423 .Map( DIM_UNITS_MODE::MILS, _HKI( "Mils" ) )
1424 .Map( DIM_UNITS_MODE::MILLIMETRES, _HKI( "Millimeters" ) )
1425 .Map( DIM_UNITS_MODE::AUTOMATIC, _HKI( "Automatic" ) );
1426
1435
1436 const wxString groupDimension = _HKI( "Dimension Properties" );
1437
1438 auto isLeader =
1439 []( INSPECTABLE* aItem ) -> bool
1440 {
1441 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) != nullptr;
1442 };
1443
1444 auto isNotLeader =
1445 []( INSPECTABLE* aItem ) -> bool
1446 {
1447 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) == nullptr;
1448 };
1449
1452 groupDimension )
1453 .SetAvailableFunc( isNotLeader );
1456 groupDimension )
1457 .SetAvailableFunc( isNotLeader );
1458 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, wxString>( _HKI( "Override Text" ),
1460 groupDimension )
1461 .SetAvailableFunc( isNotLeader );
1462
1465 groupDimension )
1466 .SetAvailableFunc( isLeader );
1467
1470 groupDimension )
1471 .SetAvailableFunc( isNotLeader );
1474 groupDimension )
1475 .SetAvailableFunc( isNotLeader );
1478 groupDimension )
1479 .SetAvailableFunc( isNotLeader );
1480 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Suppress Trailing Zeroes" ),
1482 groupDimension )
1483 .SetAvailableFunc( isNotLeader );
1484 }
1486
1490
1491
1493{
1495 {
1506
1507 const wxString groupDimension = _HKI( "Dimension Properties" );
1508
1509 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Crossbar Height" ),
1512 groupDimension );
1513 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Extension Line Overshoot" ),
1516 groupDimension );
1517
1519 _HKI( "Visible" ),
1520 []( INSPECTABLE* aItem ) { return false; } );
1522 _HKI( "Text" ),
1523 []( INSPECTABLE* aItem ) { return false; } );
1525 _HKI( "Vertical Justification" ),
1526 []( INSPECTABLE* aItem ) { return false; } );
1528 _HKI( "Hyperlink" ),
1529 []( INSPECTABLE* aItem ) { return false; } );
1531 _HKI( "Knockout" ),
1532 []( INSPECTABLE* aItem ) { return false; } );
1533 }
1535
1536
1538{
1540 {
1553
1555 _HKI( "Visible" ),
1556 []( INSPECTABLE* aItem ) { return false; } );
1558 _HKI( "Text" ),
1559 []( INSPECTABLE* aItem ) { return false; } );
1561 _HKI( "Vertical Justification" ),
1562 []( INSPECTABLE* aItem ) { return false; } );
1564 _HKI( "Hyperlink" ),
1565 []( INSPECTABLE* aItem ) { return false; } );
1567 _HKI( "Knockout" ),
1568 []( INSPECTABLE* aItem ) { return false; } );
1569 }
1571
1572
1574{
1576 {
1587
1588 const wxString groupDimension = _HKI( "Dimension Properties" );
1589
1590 propMgr.AddProperty( new PROPERTY<PCB_DIM_RADIAL, int>( _HKI( "Leader Length" ),
1592 PROPERTY_DISPLAY::PT_SIZE ),
1593 groupDimension );
1594
1596 _HKI( "Visible" ),
1597 []( INSPECTABLE* aItem ) { return false; } );
1599 _HKI( "Text" ),
1600 []( INSPECTABLE* aItem ) { return false; } );
1602 _HKI( "Vertical Justification" ),
1603 []( INSPECTABLE* aItem ) { return false; } );
1605 _HKI( "Hyperlink" ),
1606 []( INSPECTABLE* aItem ) { return false; } );
1608 _HKI( "Knockout" ),
1609 []( INSPECTABLE* aItem ) { return false; } );
1610 }
1612
1613
1615{
1617 {
1619 .Map( DIM_TEXT_BORDER::NONE, _HKI( "None" ) )
1620 .Map( DIM_TEXT_BORDER::RECTANGLE, _HKI( "Rectangle" ) )
1621 .Map( DIM_TEXT_BORDER::CIRCLE, _HKI( "Circle" ) );
1622
1633
1634 const wxString groupDimension = _HKI( "Dimension Properties" );
1635
1638 groupDimension );
1639
1641 _HKI( "Visible" ),
1642 []( INSPECTABLE* aItem ) { return false; } );
1644 _HKI( "Text" ),
1645 []( INSPECTABLE* aItem ) { return false; } );
1647 _HKI( "Vertical Justification" ),
1648 []( INSPECTABLE* aItem ) { return false; } );
1650 _HKI( "Hyperlink" ),
1651 []( INSPECTABLE* aItem ) { return false; } );
1653 _HKI( "Knockout" ),
1654 []( INSPECTABLE* aItem ) { return false; } );
1655 }
1657
1659
1660
1662{
1664 {
1675
1676
1678 _HKI( "Visible" ),
1679 []( INSPECTABLE* aItem ) { return false; } );
1681 _HKI( "Text" ),
1682 []( INSPECTABLE* aItem ) { return false; } );
1684 _HKI( "Vertical Justification" ),
1685 []( INSPECTABLE* aItem ) { return false; } );
1687 _HKI( "Hyperlink" ),
1688 []( INSPECTABLE* aItem ) { return false; } );
1690 _HKI( "Knockout" ),
1691 []( INSPECTABLE* aItem ) { return false; } );
1692 }
1694
1695
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:77
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:226
PCB_LAYER_ID m_layer
Definition: board_item.h:393
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:260
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:231
virtual bool IsLocked() const
Definition: board_item.cpp:74
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:103
EDA_UNITS GetUserUnits()
Definition: board.h:683
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:209
bool Contains(const VECTOR2I &aP) const
Return true if aP is on the circumference of this circle.
Definition: circle.cpp:188
EDA_ANGLE Normalize()
Definition: eda_angle.h:255
double Sin() const
Definition: eda_angle.h:212
double AsDegrees() const
Definition: eda_angle.h:155
EDA_ANGLE Normalize180()
Definition: eda_angle.h:294
ORIGIN_TRANSFORMS & GetOriginTransforms() override
Return a reference to the default ORIGIN_TRANSFORMS object.
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:88
const KIID m_Uuid
Definition: eda_item.h:485
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:100
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:488
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:83
int GetTextHeight() const
Definition: eda_text.h:228
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:234
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:417
KIFONT::FONT * GetFont() const
Definition: eda_text.h:211
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:565
void SetMirrored(bool isMirrored)
Definition: eda_text.cpp:250
int GetTextWidth() const
Definition: eda_text.h:225
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:435
double Similarity(const EDA_TEXT &aOther) const
Definition: eda_text.cpp:1137
virtual void ClearRenderCache()
Definition: eda_text.cpp:497
bool IsMirrored() const
Definition: eda_text.h:154
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition: eda_text.cpp:322
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:978
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:181
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition: eda_text.cpp:203
int GetTextThickness() const
Definition: eda_text.h:126
bool operator==(const EDA_TEXT &aRhs) const
Definition: eda_text.h:356
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
static LSET SideSpecificMask()
Definition: lset.cpp:998
A class to perform either relative or absolute display origin transforms for a single axis of a point...
T ToDisplayAbs(const T &aValue) const
Abstract dimension API.
EDA_UNITS GetUnits() const
bool m_autoUnits
If true, follow the currently selected UI units.
void Update()
Update the dimension's cached text and geometry.
void ChangeSuffix(const wxString &aSuffix)
wxString GetOverrideText() const
wxString GetSuffix() const
std::vector< std::shared_ptr< SHAPE > > m_shapes
double Similarity(const BOARD_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
void Flip(const VECTOR2I &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
void ClearRenderCache() override
int m_lineThickness
Thickness used for all graphics in the dimension.
void Move(const VECTOR2I &offset) override
Move this object.
bool m_suppressZeroes
Suppress trailing zeroes.
void SetUnits(EDA_UNITS aUnits)
DIM_PRECISION m_precision
Number of digits to display after decimal.
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
static OPT_VECTOR2I segCircleIntersection(CIRCLE &aCircle, SEG &aSeg, bool aStart=true)
void addShape(const ShapeType &aShape)
void SetPrefix(const wxString &aPrefix)
wxString m_suffix
String appended to the value.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void ChangeOverrideText(const wxString &aValue)
bool m_inClearRenderCache
re-entrancy guard
PCB_DIMENSION_BASE(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIMENSION_T)
int m_extensionOffset
Distance from feature points to extension line start.
bool m_keepTextAligned
Calculate text orientation to match dimension.
DIM_PRECISION GetPrecision() const
wxString GetPrefix() const
void SetSuffix(const wxString &aSuffix)
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
bool operator==(const BOARD_ITEM &aOther) const override
DIM_UNITS_MODE GetUnitsMode() const
virtual void updateText()
Update the text field value from the current geometry (called by updateGeometry normally).
bool HitTest(const VECTOR2I &aPosition, int aAccuracy) const override
Test if aPosition is inside or on the boundary of this item.
EDA_UNITS m_units
0 = inches, 1 = mm
int m_measuredValue
value of PCB dimensions
DIM_UNITS_FORMAT GetUnitsFormat() const
virtual const VECTOR2I & GetStart() const
The dimension's origin is the first feature point for the dimension.
wxString m_valueString
Displayed value when m_overrideValue = true.
void ChangePrecision(DIM_PRECISION aPrecision)
bool m_overrideTextEnabled
Manually specify the displayed measurement value.
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
DIM_UNITS_FORMAT m_unitsFormat
How to render the units suffix.
int GetMeasuredValue() const
bool GetSuppressZeroes() const
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
DIM_TEXT_POSITION m_textPosition
How to position the text.
static OPT_VECTOR2I segPolyIntersection(const SHAPE_POLY_SET &aPoly, const SEG &aSeg, bool aStart=true)
Find the intersection between a given segment and polygon outline.
void SetOverrideText(const wxString &aValue)
wxString GetValueText() const
void ChangePrefix(const wxString &aPrefix)
wxString m_prefix
String prepended to the value.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
void ChangeUnitsFormat(const DIM_UNITS_FORMAT aFormat)
void ChangeSuppressZeroes(bool aSuppress)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
virtual void Mirror(const VECTOR2I &axis_pos, bool aMirrorLeftRight=false)
Mirror the dimension relative to a given horizontal axis.
bool GetOverrideTextEnabled() const
void SetUnitsMode(DIM_UNITS_MODE aMode)
int m_arrowLength
Length of arrow shapes.
virtual const VECTOR2I & GetEnd() const
VECTOR2I m_end
Internal cache of drawn shapes.
void ChangeUnitsMode(DIM_UNITS_MODE aMode)
VECTOR2I GetPosition() const override
For better understanding of the points that make a dimension:
int GetHeight() const
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
int m_height
Perpendicular distance from features to crossbar.
void ChangeExtensionHeight(int aHeight)
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
VECTOR2I m_crossBarStart
Crossbar start control point.
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
virtual void swapData(BOARD_ITEM *aImage) override
int m_extensionHeight
Length of extension lines past the crossbar.
VECTOR2I m_crossBarEnd
Crossbar end control point.
void Mirror(const VECTOR2I &axis_pos, bool aMirrorLeftRight=false) override
Mirror the dimension relative to a given horizontal axis.
PCB_DIM_ALIGNED(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIM_ALIGNED_T)
void ChangeHeight(int aHeight)
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
int GetExtensionHeight() const
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Mark the center of a circle or arc with a cross shape.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
virtual void swapData(BOARD_ITEM *aImage) override
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
PCB_DIM_CENTER(BOARD_ITEM *aParent)
A leader is a dimension-like object pointing to a specific point.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
DIM_TEXT_BORDER m_textBorder
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
DIM_TEXT_BORDER GetTextBorder() const
virtual void swapData(BOARD_ITEM *aImage) override
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
PCB_DIM_LEADER(BOARD_ITEM *aParent)
void ChangeTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
void swapData(BOARD_ITEM *aImage) override
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
DIR m_orientation
What axis to lock the dimension line to.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
PCB_DIM_ORTHOGONAL(BOARD_ITEM *aParent)
A radial dimension indicates either the radius or diameter of an arc or circle.
int GetLeaderLength() const
PCB_DIM_RADIAL(BOARD_ITEM *aParent)
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
virtual void swapData(BOARD_ITEM *aImage) override
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void ChangeLeaderLength(int aLength)
VECTOR2I GetKnee() const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pcb_text.cpp:249
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
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:87
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int GetRadius() const
Definition: shape_circle.h:108
const VECTOR2I GetCenter() const
Definition: shape_circle.h:113
Base class for iterating over all segments in a given SHAPE_POLY_SET.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
SEGMENT_ITERATOR IterateSegments(int aFirst, int aLast, bool aIterateHoles=false)
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
const SEG & GetSeg() const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:265
extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector2d.h:471
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:354
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
#define _HKI(x)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:437
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_VERTICAL
Definition: eda_angle.h:432
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
Definition: eda_angle.h:431
static constexpr EDA_ANGLE ANGLE_45
Definition: eda_angle.h:436
static constexpr EDA_ANGLE ANGLE_270
Definition: eda_angle.h:440
static constexpr EDA_ANGLE FULL_CIRCLE
Definition: eda_angle.h:433
static constexpr EDA_ANGLE ANGLE_180
Definition: eda_angle.h:439
static constexpr EDA_ANGLE ANGLE_135
Definition: eda_angle.h:438
#define PCB_EDIT_FRAME_NAME
EDA_UNITS
Definition: eda_units.h:46
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ NONE
Definition: kibis.h:54
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:149
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ Dwgs_User
Definition: layer_ids.h:109
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:634
KICOMMON_API double ToUserUnit(const EDA_IU_SCALE &aIuScale, EDA_UNITS aUnit, double aValue)
Function To_User_Unit convert aValue in internal units to the appropriate user units defined by aUnit...
Definition: eda_units.cpp: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:424
static const EDA_ANGLE s_arrowAngle(27.5, DEGREES_T)
static struct DIMENSION_DESC _DIMENSION_DESC
#define INVERT(pos)
DIM_TEXT_POSITION
Where to place the text on a dimension.
Definition: pcb_dimension.h:62
@ OUTSIDE
Text appears outside the dimension line (default)
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
Definition: pcb_dimension.h:40
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
Definition: pcb_dimension.h:72
DIM_TEXT_BORDER
Frame to show around dimension text.
Definition: pcb_dimension.h:83
DIM_PRECISION
Definition: pcb_dimension.h:47
#define TYPE_HASH(x)
Definition: property.h: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
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:168
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:118
VECTOR2< int > VECTOR2I
Definition: vector2d.h:602