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 Update();
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 SetTextAngleDegrees( aDegrees );
319 // Create or repair any knockouts
320 Update();
321}
322
323
325{
326 SetKeepTextAligned( aKeepAligned );
327 // Re-align the text and repair any knockouts
328 Update();
329}
330
331
333{
334 PCB_TEXT::Offset( offset );
335
336 m_start += offset;
337 m_end += offset;
338
339 Update();
340}
341
342
343void PCB_DIMENSION_BASE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
344{
345 EDA_ANGLE newAngle = GetTextAngle() + aAngle;
346
347 newAngle.Normalize();
348
349 SetTextAngle( newAngle );
350
351 VECTOR2I pt = GetTextPos();
352 RotatePoint( pt, aRotCentre, aAngle );
353 SetTextPos( pt );
354
355 RotatePoint( m_start, aRotCentre, aAngle );
356 RotatePoint( m_end, aRotCentre, aAngle );
357
358 Update();
359}
360
361
362void PCB_DIMENSION_BASE::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
363{
364 Mirror( aCentre );
365
366 SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) );
367}
368
369
370void PCB_DIMENSION_BASE::Mirror( const VECTOR2I& axis_pos, bool aMirrorLeftRight )
371{
372 int axis = aMirrorLeftRight ? axis_pos.x : axis_pos.y;
373 VECTOR2I newPos = GetTextPos();
374
375#define INVERT( pos ) ( ( pos ) = axis - ( ( pos ) - axis ) )
376 if( aMirrorLeftRight )
377 INVERT( newPos.x );
378 else
379 INVERT( newPos.y );
380
381 SetTextPos( newPos );
382
383 // invert angle
385
386 if( aMirrorLeftRight )
387 {
388 INVERT( m_start.x );
389 INVERT( m_end.x );
390 }
391 else
392 {
393 INVERT( m_start.y );
394 INVERT( m_end.y );
395 }
396
397 if( ( GetLayerSet() & LSET::SideSpecificMask() ).any() )
399
400 Update();
401}
402
403
405 std::vector<MSG_PANEL_ITEM>& aList )
406{
407 // for now, display only the text within the DIMENSION using class PCB_TEXT.
408 wxString msg;
409
410 wxCHECK_RET( m_parent != nullptr, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
411
412 // Don't use GetShownText(); we want to see the variable references here
413 aList.emplace_back( _( "Dimension" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
414
415 aList.emplace_back( _( "Prefix" ), GetPrefix() );
416
418 {
419 aList.emplace_back( _( "Override Text" ), GetOverrideText() );
420 }
421 else
422 {
423 aList.emplace_back( _( "Value" ), GetValueText() );
424
425 switch( GetPrecision() )
426 {
427 case DIM_PRECISION::V_VV: msg = wxT( "0.00 in / 0 mils / 0.0 mm" ); break;
428 case DIM_PRECISION::V_VVV: msg = wxT( "0.000 in / 0 mils / 0.00 mm" ); break;
429 case DIM_PRECISION::V_VVVV: msg = wxT( "0.0000 in / 0.0 mils / 0.000 mm" ); break;
430 case DIM_PRECISION::V_VVVVV: msg = wxT( "0.00000 in / 0.00 mils / 0.0000 mm" ); break;
431 default: msg = wxT( "%" ) + wxString::Format( wxT( "1.%df" ), GetPrecision() );
432 }
433
434 aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
435 }
436
437 aList.emplace_back( _( "Suffix" ), GetSuffix() );
438
439 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
440 // in frame's units.
441 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
442 unitsProvider.SetUserUnits( GetUnits() );
443
444 aList.emplace_back( _( "Units" ), EDA_UNIT_UTILS::GetLabel( GetUnits() ) );
445
446 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
447 aList.emplace_back( _( "Text Thickness" ), unitsProvider.MessageTextFromValue( GetTextThickness() ) );
448 aList.emplace_back( _( "Text Width" ), unitsProvider.MessageTextFromValue( GetTextWidth() ) );
449 aList.emplace_back( _( "Text Height" ), unitsProvider.MessageTextFromValue( GetTextHeight() ) );
450
451 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
452
453 if( Type() == PCB_DIM_CENTER_T )
454 {
455 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
456 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
457 aFrame->MessageTextFromValue( startCoord.x ),
458 aFrame->MessageTextFromValue( startCoord.y ) );
459
460 aList.emplace_back( start, wxEmptyString );
461 }
462 else
463 {
464 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
465 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
466 aFrame->MessageTextFromValue( startCoord.x ),
467 aFrame->MessageTextFromValue( startCoord.y ) );
468 VECTOR2I endCoord = originTransforms.ToDisplayAbs( GetEnd() );
469 wxString end = wxString::Format( wxT( "@(%s, %s)" ),
470 aFrame->MessageTextFromValue( endCoord.x ),
471 aFrame->MessageTextFromValue( endCoord.y ) );
472
473 aList.emplace_back( start, end );
474 }
475
476 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
477 aList.emplace_back( _( "Status" ), _( "Locked" ) );
478
479 aList.emplace_back( _( "Layer" ), GetLayerName() );
480}
481
482
483std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
484{
485 std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
486
487 effectiveShape->AddShape( GetEffectiveTextShape()->Clone() );
488
489 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
490 effectiveShape->AddShape( shape->Clone() );
491
492 return effectiveShape;
493}
494
495
496bool PCB_DIMENSION_BASE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
497{
498 if( TextHitTest( aPosition ) )
499 return true;
500
501 int dist_max = aAccuracy + ( m_lineThickness / 2 );
502
503 // Locate SEGMENTS
504
505 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
506 {
507 if( shape->Collide( aPosition, dist_max ) )
508 return true;
509 }
510
511 return false;
512}
513
514
515bool PCB_DIMENSION_BASE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
516{
517 BOX2I arect = aRect;
518 arect.Inflate( aAccuracy );
519
520 BOX2I rect = GetBoundingBox();
521
522 if( aAccuracy )
523 rect.Inflate( aAccuracy );
524
525 if( aContained )
526 return arect.Contains( rect );
527
528 return arect.Intersects( rect );
529}
530
531
533{
534 BOX2I bBox;
535 int xmin, xmax, ymin, ymax;
536
537 bBox = GetTextBox();
538 xmin = bBox.GetX();
539 xmax = bBox.GetRight();
540 ymin = bBox.GetY();
541 ymax = bBox.GetBottom();
542
543 for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
544 {
545 BOX2I shapeBox = shape->BBox();
546 shapeBox.Inflate( m_lineThickness / 2 );
547
548 xmin = std::min( xmin, shapeBox.GetOrigin().x );
549 xmax = std::max( xmax, shapeBox.GetEnd().x );
550 ymin = std::min( ymin, shapeBox.GetOrigin().y );
551 ymax = std::max( ymax, shapeBox.GetEnd().y );
552 }
553
554 bBox.SetX( xmin );
555 bBox.SetY( ymin );
556 bBox.SetWidth( xmax - xmin + 1 );
557 bBox.SetHeight( ymax - ymin + 1 );
558
559 bBox.Normalize();
560
561 return bBox;
562}
563
564
566{
567 return wxString::Format( _( "Dimension '%s' on %s" ),
569 GetLayerName() );
570}
571
572
573
575{
577 VECTOR2I( GetBoundingBox().GetSize() ) );
578 dimBBox.Merge( PCB_TEXT::ViewBBox() );
579
580 return dimBBox;
581}
582
583
585 bool aStart )
586{
587 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
588 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
589
590 if( aPoly.Contains( start ) )
591 return std::nullopt;
592
593 for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
594 {
595 if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
596 {
597 if( ( *intersection - start ).SquaredEuclideanNorm() <
598 ( endpoint - start ).SquaredEuclideanNorm() )
599 endpoint = *intersection;
600 }
601 }
602
603 if( start == endpoint )
604 return std::nullopt;
605
606 return OPT_VECTOR2I( endpoint );
607}
608
609
611{
612 VECTOR2I start( aStart ? aSeg.A : aSeg.B );
613 VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
614
615 if( aCircle.Contains( start ) )
616 return std::nullopt;
617
618 std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
619
620 for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
621 {
622 if( ( intersection - start ).SquaredEuclideanNorm() <
623 ( endpoint - start ).SquaredEuclideanNorm() )
624 endpoint = intersection;
625 }
626
627 if( start == endpoint )
628 return std::nullopt;
629
630 return OPT_VECTOR2I( endpoint );
631}
632
633
635 int aClearance, int aError, ERROR_LOC aErrorLoc,
636 bool aIgnoreLineWidth ) const
637{
638 wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
639
640 for( const std::shared_ptr<SHAPE>& shape : m_shapes )
641 {
642 const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
643 const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
644
645 if( circle )
646 {
647 TransformCircleToPolygon( aBuffer, circle->GetCenter(),
648 circle->GetRadius() + m_lineThickness / 2 + aClearance,
649 aError, aErrorLoc );
650 }
651 else if( seg )
652 {
653 TransformOvalToPolygon( aBuffer, seg->GetSeg().A, seg->GetSeg().B,
654 m_lineThickness + 2 * aClearance, aError, aErrorLoc );
655 }
656 else
657 {
658 wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeToPolygon unknown shape type." ) );
659 }
660 }
661}
662
663
665 PCB_DIMENSION_BASE( aParent, aType ),
666 m_height( 0 )
667{
668 // To preserve look of old dimensions, initialize extension height based on default arrow length
669 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
670}
671
672
674{
675 return new PCB_DIM_ALIGNED( *this );
676}
677
678
680{
681 wxASSERT( aImage->Type() == Type() );
682
683 m_shapes.clear();
684 static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
685
686 std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
687
688 Update();
689}
690
691
692void PCB_DIM_ALIGNED::Mirror( const VECTOR2I& axis_pos, bool aMirrorLeftRight )
693{
694 PCB_DIMENSION_BASE::Mirror( axis_pos, aMirrorLeftRight );
695
697}
698
699
701{
702 return BITMAPS::add_aligned_dimension;
703}
704
705
706void PCB_DIM_ALIGNED::UpdateHeight( const VECTOR2I& aCrossbarStart, const VECTOR2I& aCrossbarEnd )
707{
708 VECTOR2D height( aCrossbarStart - GetStart() );
709 VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
710
711 if( height.Cross( crossBar ) > 0 )
712 m_height = -height.EuclideanNorm();
713 else
714 m_height = height.EuclideanNorm();
715
716 Update();
717}
718
719
721{
722 m_shapes.clear();
723
724 VECTOR2I dimension( m_end - m_start );
725
726 m_measuredValue = KiROUND( dimension.EuclideanNorm() );
727
728 VECTOR2I extension;
729
730 if( m_height > 0 )
731 extension = VECTOR2I( -dimension.y, dimension.x );
732 else
733 extension = VECTOR2I( dimension.y, -dimension.x );
734
735 // Add extension lines
736 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
737
738 VECTOR2I extStart( m_start );
739 extStart += extension.Resize( m_extensionOffset );
740
741 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
742
743 extStart = VECTOR2I( m_end );
744 extStart += extension.Resize( m_extensionOffset );
745
746 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
747
748 // Add crossbar
749 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
750 m_crossBarStart = m_start + crossBarDistance;
751 m_crossBarEnd = m_end + crossBarDistance;
752
753 // Update text after calculating crossbar position but before adding crossbar lines
754 updateText();
755
756 // Now that we have the text updated, we can determine how to draw the crossbar.
757 // First we need to create an appropriate bounding polygon to collide with
759
760 SHAPE_POLY_SET polyBox;
761 polyBox.NewOutline();
762 polyBox.Append( textBox.GetOrigin() );
763 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
764 polyBox.Append( textBox.GetEnd() );
765 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
766 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
767
768 // The ideal crossbar, if the text doesn't collide
769 SEG crossbar( m_crossBarStart, m_crossBarEnd );
770
771 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
772 bool containsA = polyBox.Contains( crossbar.A );
773 bool containsB = polyBox.Contains( crossbar.B );
774
775 OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
776 OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
777
778 if( endpointA )
779 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
780
781 if( endpointB )
782 m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
783
784 if( !containsA && !containsB && !endpointA && !endpointB )
785 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
786
787 // Add arrows
788 VECTOR2I arrowEndPos( m_arrowLength, 0 );
789 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
790 RotatePoint( arrowEndPos, -EDA_ANGLE( dimension ) + s_arrowAngle );
791 RotatePoint( arrowEndNeg, -EDA_ANGLE( dimension ) - s_arrowAngle );
792
793 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndPos ) );
794 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndNeg ) );
795 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndPos ) );
796 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndNeg ) );
797}
798
799
801{
802 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
803
804 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
805 {
806 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
807 EDA_ANGLE rotation;
808
809 if( crossbarCenter.x == 0 )
810 rotation = ANGLE_90 * sign( -crossbarCenter.y );
811 else if( crossbarCenter.x < 0 )
812 rotation = -ANGLE_90;
813 else
814 rotation = ANGLE_90;
815
816 VECTOR2I textOffset = crossbarCenter;
817 RotatePoint( textOffset, rotation );
818 textOffset = crossbarCenter + textOffset.Resize( textOffsetDistance );
819
820 SetTextPos( m_crossBarStart + textOffset );
821 }
822 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
823 {
824 SetTextPos( m_crossBarStart + crossbarCenter );
825 }
826
828 {
829 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( crossbarCenter );
830 textAngle.Normalize();
831
832 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
833 textAngle -= ANGLE_180;
834
835 SetTextAngle( textAngle );
836 }
837
839}
840
841
842void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
843{
845
846 // Use our own UNITS_PROVIDER to report dimension info in dimension's units rather than
847 // in frame's units.
848 UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::MILLIMETRES );
849 unitsProvider.SetUserUnits( GetUnits() );
850
851 aList.emplace_back( _( "Height" ), unitsProvider.MessageTextFromValue( m_height ) );
852}
853
854
857{
858 // To preserve look of old dimensions, initialize extension height based on default arrow length
859 m_extensionHeight = static_cast<int>( m_arrowLength * s_arrowAngle.Sin() );
861}
862
863
865{
866 return new PCB_DIM_ORTHOGONAL( *this );
867}
868
869
871{
872 wxASSERT( aImage->Type() == Type() );
873
874 m_shapes.clear();
875 static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
876
877 std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
878 *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
879
880 Update();
881}
882
883
885{
886 return BITMAPS::add_orthogonal_dimension;
887}
888
889
891{
892 m_shapes.clear();
893
895 m_end.y - m_start.y );
897
898 VECTOR2I extension;
899
901 extension = VECTOR2I( 0, m_height );
902 else
903 extension = VECTOR2I( m_height, 0 );
904
905 // Add first extension line
906 int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
907
908 VECTOR2I extStart( m_start );
909 extStart += extension.Resize( m_extensionOffset );
910
911 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
912
913 // Add crossbar
914 VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
915 m_crossBarStart = m_start + crossBarDistance;
916
919 else
921
922 // Add second extension line (m_end to crossbar end)
924 extension = VECTOR2I( 0, m_end.y - m_crossBarEnd.y );
925 else
926 extension = VECTOR2I( m_end.x - m_crossBarEnd.x, 0 );
927
928 extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
929
930 extStart = VECTOR2I( m_crossBarEnd );
931 extStart -= extension.Resize( m_extensionHeight );
932
933 addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
934
935 // Update text after calculating crossbar position but before adding crossbar lines
936 updateText();
937
938 // Now that we have the text updated, we can determine how to draw the crossbar.
939 // First we need to create an appropriate bounding polygon to collide with
941
942 SHAPE_POLY_SET polyBox;
943 polyBox.NewOutline();
944 polyBox.Append( textBox.GetOrigin() );
945 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
946 polyBox.Append( textBox.GetEnd() );
947 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
948 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
949
950 // The ideal crossbar, if the text doesn't collide
951 SEG crossbar( m_crossBarStart, m_crossBarEnd );
952
953 // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
954 bool containsA = polyBox.Contains( crossbar.A );
955 bool containsB = polyBox.Contains( crossbar.B );
956
957 OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
958 OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
959
960 if( endpointA )
961 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
962
963 if( endpointB )
964 m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
965
966 if( !containsA && !containsB && !endpointA && !endpointB )
967 m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
968
969 // Add arrows
970 EDA_ANGLE crossBarAngle( m_crossBarEnd - m_crossBarStart );
971 VECTOR2I arrowEndPos( m_arrowLength, 0 );
972 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
973 RotatePoint( arrowEndPos, -crossBarAngle + s_arrowAngle );
974 RotatePoint( arrowEndNeg, -crossBarAngle - s_arrowAngle );
975
976 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndPos ) );
977 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart, m_crossBarStart + arrowEndNeg ) );
978 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndPos ) );
979 m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd, m_crossBarEnd - arrowEndNeg ) );
980}
981
982
984{
985 VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
986
987 if( m_textPosition == DIM_TEXT_POSITION::OUTSIDE )
988 {
989 int textOffsetDistance = GetEffectiveTextPenWidth() + GetTextHeight();
990
991 VECTOR2I textOffset;
992
994 textOffset.y = -textOffsetDistance;
995 else
996 textOffset.x = -textOffsetDistance;
997
998 textOffset += crossbarCenter;
999
1000 SetTextPos( m_crossBarStart + textOffset );
1001 }
1002 else if( m_textPosition == DIM_TEXT_POSITION::INLINE )
1003 {
1004 SetTextPos( m_crossBarStart + crossbarCenter );
1005 }
1006
1007 if( m_keepTextAligned )
1008 {
1009 if( abs( crossbarCenter.x ) > abs( crossbarCenter.y ) )
1011 else
1013 }
1014
1016}
1017
1018
1019void PCB_DIM_ORTHOGONAL::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
1020{
1021 EDA_ANGLE angle( aAngle );
1022
1023 // restrict angle to -179.9 to 180.0 degrees
1024 angle.Normalize180();
1025
1026 // adjust orientation and height to new angle
1027 // we can only handle the cases of -90, 0, 90, 180 degrees exactly;
1028 // in the other cases we will use the nearest 90 degree angle to
1029 // choose at least an approximate axis for the target orientation
1030 // In case of exactly 45 or 135 degrees, we will round towards zero for consistency
1031 if( angle > ANGLE_45 && angle <= ANGLE_135 )
1032 {
1033 // about 90 degree
1035 {
1037 }
1038 else
1039 {
1041 m_height = -m_height;
1042 }
1043 }
1044 else if( angle < -ANGLE_45 && angle >= -ANGLE_135 )
1045 {
1046 // about -90 degree
1048 {
1050 m_height = -m_height;
1051 }
1052 else
1053 {
1055 }
1056 }
1057 else if( angle > ANGLE_135 || angle < -ANGLE_135 )
1058 {
1059 // about 180 degree
1060 m_height = -m_height;
1061 }
1062
1063 // this will update m_crossBarStart and m_crossbarEnd
1064 PCB_DIMENSION_BASE::Rotate( aRotCentre, angle );
1065}
1066
1067
1070 m_textBorder( DIM_TEXT_BORDER::NONE )
1071{
1072 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1073 m_overrideTextEnabled = true;
1074 m_keepTextAligned = false;
1075
1076 SetOverrideText( _( "Leader" ) );
1077}
1078
1079
1081{
1082 return new PCB_DIM_LEADER( *this );
1083}
1084
1085
1087{
1088 wxASSERT( aImage->Type() == Type() );
1089
1090 m_shapes.clear();
1091 static_cast<PCB_DIM_LEADER*>( aImage )->m_shapes.clear();
1092
1093 std::swap( *static_cast<PCB_DIM_LEADER*>( this ), *static_cast<PCB_DIM_LEADER*>( aImage ) );
1094
1095 Update();
1096}
1097
1098
1100{
1101 return BITMAPS::add_leader;
1102}
1103
1104
1106{
1107 // Our geometry is dependent on the size of the text, so just update the whole shebang
1109}
1110
1111
1113{
1114 m_shapes.clear();
1115
1117
1118 // Now that we have the text updated, we can determine how to draw the second line
1119 // First we need to create an appropriate bounding polygon to collide with
1120 BOX2I textBox = GetTextBox().Inflate( GetTextWidth() / 2, GetEffectiveTextPenWidth() * 2 );
1121
1122 SHAPE_POLY_SET polyBox;
1123 polyBox.NewOutline();
1124 polyBox.Append( textBox.GetOrigin() );
1125 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1126 polyBox.Append( textBox.GetEnd() );
1127 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1128 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1129
1130 VECTOR2I firstLine( m_end - m_start );
1131 VECTOR2I start( m_start );
1132 start += firstLine.Resize( m_extensionOffset );
1133
1134 SEG arrowSeg( m_start, m_end );
1135 SEG textSeg( m_end, GetTextPos() );
1136 OPT_VECTOR2I arrowSegEnd;
1137 OPT_VECTOR2I textSegEnd;
1138
1139 if( m_textBorder == DIM_TEXT_BORDER::CIRCLE )
1140 {
1141 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1142 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1143 CIRCLE circle( textBox.GetCenter(), radius );
1144
1145 arrowSegEnd = segCircleIntersection( circle, arrowSeg );
1146 textSegEnd = segCircleIntersection( circle, textSeg );
1147 }
1148 else
1149 {
1150 arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1151 textSegEnd = segPolyIntersection( polyBox, textSeg );
1152 }
1153
1154 if( !arrowSegEnd )
1155 arrowSegEnd = m_end;
1156
1157 m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
1158
1159 // Add arrows
1160 VECTOR2I arrowEndPos( m_arrowLength, 0 );
1161 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
1162 RotatePoint( arrowEndPos, -EDA_ANGLE( firstLine ) + s_arrowAngle );
1163 RotatePoint( arrowEndNeg, -EDA_ANGLE( firstLine ) - s_arrowAngle );
1164
1165 m_shapes.emplace_back( new SHAPE_SEGMENT( start, start + arrowEndPos ) );
1166 m_shapes.emplace_back( new SHAPE_SEGMENT( start, start + arrowEndNeg ) );
1167
1168
1169 if( !GetText().IsEmpty() )
1170 {
1171 switch( m_textBorder )
1172 {
1173 case DIM_TEXT_BORDER::RECTANGLE:
1174 {
1175 for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
1176 m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
1177
1178 break;
1179 }
1180
1181 case DIM_TEXT_BORDER::CIRCLE:
1182 {
1183 double penWidth = GetEffectiveTextPenWidth() / 2.0;
1184 double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1185 m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
1186
1187 break;
1188 }
1189
1190 default:
1191 break;
1192 }
1193 }
1194
1195 if( textSegEnd && *arrowSegEnd == m_end )
1196 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textSegEnd ) );
1197}
1198
1199
1200void PCB_DIM_LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1201{
1202 // Don't use GetShownText(); we want to see the variable references here
1203 aList.emplace_back( _( "Leader" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
1204
1205 ORIGIN_TRANSFORMS& originTransforms = aFrame->GetOriginTransforms();
1206
1207 VECTOR2I startCoord = originTransforms.ToDisplayAbs( GetStart() );
1208 wxString start = wxString::Format( wxT( "@(%s, %s)" ),
1209 aFrame->MessageTextFromValue( startCoord.x ),
1210 aFrame->MessageTextFromValue( startCoord.y ) );
1211
1212 aList.emplace_back( start, wxEmptyString );
1213
1214 aList.emplace_back( _( "Layer" ), GetLayerName() );
1215}
1216
1217
1220{
1221 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1222 m_overrideTextEnabled = false;
1223 m_keepTextAligned = true;
1224 m_isDiameter = false;
1225 m_prefix = "R ";
1227}
1228
1229
1231{
1232 return new PCB_DIM_RADIAL( *this );
1233}
1234
1235
1237{
1238 wxASSERT( aImage->Type() == Type() );
1239
1240 m_shapes.clear();
1241 static_cast<PCB_DIM_RADIAL*>( aImage )->m_shapes.clear();
1242
1243 std::swap( *static_cast<PCB_DIM_RADIAL*>( this ), *static_cast<PCB_DIM_RADIAL*>( aImage ) );
1244
1245 Update();
1246}
1247
1248
1250{
1251 return BITMAPS::add_radial_dimension;
1252}
1253
1254
1256{
1257 VECTOR2I radial( m_end - m_start );
1258
1259 return m_end + radial.Resize( m_leaderLength );
1260}
1261
1262
1264{
1265 if( m_keepTextAligned )
1266 {
1267 VECTOR2I textLine( GetTextPos() - GetKnee() );
1268 EDA_ANGLE textAngle = FULL_CIRCLE - EDA_ANGLE( textLine );
1269
1270 textAngle.Normalize();
1271
1272 if( textAngle > ANGLE_90 && textAngle <= ANGLE_270 )
1273 textAngle -= ANGLE_180;
1274
1275 // Round to nearest degree
1276 textAngle = EDA_ANGLE( KiROUND( textAngle.AsDegrees() ), DEGREES_T );
1277
1278 SetTextAngle( textAngle );
1279 }
1280
1282}
1283
1284
1286{
1287 m_shapes.clear();
1288
1289 VECTOR2I center( m_start );
1290 VECTOR2I centerArm( 0, m_arrowLength );
1291
1292 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1293
1294 RotatePoint( centerArm, -ANGLE_90 );
1295
1296 m_shapes.emplace_back( new SHAPE_SEGMENT( center - centerArm, center + centerArm ) );
1297
1298 VECTOR2I radius( m_end - m_start );
1299
1300 if( m_isDiameter )
1301 m_measuredValue = KiROUND( radius.EuclideanNorm() * 2 );
1302 else
1304
1305 updateText();
1306
1307 // Now that we have the text updated, we can determine how to draw the second line
1308 // First we need to create an appropriate bounding polygon to collide with
1310
1311 SHAPE_POLY_SET polyBox;
1312 polyBox.NewOutline();
1313 polyBox.Append( textBox.GetOrigin() );
1314 polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
1315 polyBox.Append( textBox.GetEnd() );
1316 polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
1317 polyBox.Rotate( GetTextAngle(), textBox.GetCenter() );
1318
1319 VECTOR2I radial( m_end - m_start );
1320 radial = radial.Resize( m_leaderLength );
1321
1322 SEG arrowSeg( m_end, m_end + radial );
1323 SEG textSeg( arrowSeg.B, GetTextPos() );
1324
1325 OPT_VECTOR2I arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1326 OPT_VECTOR2I textSegEnd = segPolyIntersection( polyBox, textSeg );
1327
1328 if( arrowSegEnd )
1329 arrowSeg.B = *arrowSegEnd;
1330
1331 if( textSegEnd )
1332 textSeg.B = *textSegEnd;
1333
1334 m_shapes.emplace_back( new SHAPE_SEGMENT( arrowSeg ) );
1335
1336 // Add arrows
1337 VECTOR2I arrowEndPos( m_arrowLength, 0 );
1338 VECTOR2I arrowEndNeg( m_arrowLength, 0 );
1339 RotatePoint( arrowEndPos, -EDA_ANGLE( radial ) + s_arrowAngle );
1340 RotatePoint( arrowEndNeg, -EDA_ANGLE( radial ) - s_arrowAngle );
1341
1342 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, m_end + arrowEndPos ) );
1343 m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, m_end + arrowEndNeg ) );
1344
1345 m_shapes.emplace_back( new SHAPE_SEGMENT( textSeg ) );
1346}
1347
1348
1351{
1352 m_unitsFormat = DIM_UNITS_FORMAT::NO_SUFFIX;
1353 m_overrideTextEnabled = true;
1354}
1355
1356
1358{
1359 return new PCB_DIM_CENTER( *this );
1360}
1361
1362
1364{
1365 wxASSERT( aImage->Type() == Type() );
1366
1367 std::swap( *static_cast<PCB_DIM_CENTER*>( this ), *static_cast<PCB_DIM_CENTER*>( aImage ) );
1368}
1369
1370
1372{
1373 return BITMAPS::add_center_dimension;
1374}
1375
1376
1378{
1379 int halfWidth = VECTOR2I( m_end - m_start ).x + ( m_lineThickness / 2.0 );
1380
1381 BOX2I bBox;
1382
1383 bBox.SetX( m_start.x - halfWidth );
1384 bBox.SetY( m_start.y - halfWidth );
1385 bBox.SetWidth( halfWidth * 2 );
1386 bBox.SetHeight( halfWidth * 2 );
1387
1388 bBox.Normalize();
1389
1390 return bBox;
1391}
1392
1393
1395{
1397 VECTOR2I( GetBoundingBox().GetSize() ) );
1398}
1399
1400
1402{
1403 m_shapes.clear();
1404
1405 VECTOR2I center( m_start );
1406 VECTOR2I arm( m_end - m_start );
1407
1408 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1409
1410 RotatePoint( arm, -ANGLE_90 );
1411
1412 m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1413}
1414
1415
1416static struct DIMENSION_DESC
1417{
1419 {
1421 .Map( DIM_PRECISION::X, _HKI( "0" ) )
1422 .Map( DIM_PRECISION::X_X, _HKI( "0.0" ) )
1423 .Map( DIM_PRECISION::X_XX, _HKI( "0.00" ) )
1424 .Map( DIM_PRECISION::X_XXX, _HKI( "0.000" ) )
1425 .Map( DIM_PRECISION::X_XXXX, _HKI( "0.0000" ) )
1426 .Map( DIM_PRECISION::X_XXXXX, _HKI( "0.00000" ) )
1427 .Map( DIM_PRECISION::V_VV, _HKI( "0.00 in / 0 mils / 0.0 mm" ) )
1428 .Map( DIM_PRECISION::V_VVV, _HKI( "0.000 / 0 / 0.00" ) )
1429 .Map( DIM_PRECISION::V_VVVV, _HKI( "0.0000 / 0.0 / 0.000" ) )
1430 .Map( DIM_PRECISION::V_VVVVV, _HKI( "0.00000 / 0.00 / 0.0000" ) );
1431
1433 .Map( DIM_UNITS_FORMAT::NO_SUFFIX, _HKI( "1234.0" ) )
1434 .Map( DIM_UNITS_FORMAT::BARE_SUFFIX, _HKI( "1234.0 mm" ) )
1435 .Map( DIM_UNITS_FORMAT::PAREN_SUFFIX, _HKI( "1234.0 (mm)" ) );
1436
1438 .Map( DIM_UNITS_MODE::INCHES, _HKI( "Inches" ) )
1439 .Map( DIM_UNITS_MODE::MILS, _HKI( "Mils" ) )
1440 .Map( DIM_UNITS_MODE::MILLIMETRES, _HKI( "Millimeters" ) )
1441 .Map( DIM_UNITS_MODE::AUTOMATIC, _HKI( "Automatic" ) );
1442
1451
1452 propMgr.Mask( TYPE_HASH( PCB_DIMENSION_BASE ), TYPE_HASH( EDA_TEXT ), _HKI( "Orientation" ) );
1453
1454 const wxString groupDimension = _HKI( "Dimension Properties" );
1455
1456 auto isLeader =
1457 []( INSPECTABLE* aItem ) -> bool
1458 {
1459 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) != nullptr;
1460 };
1461
1462 auto isNotLeader =
1463 []( INSPECTABLE* aItem ) -> bool
1464 {
1465 return dynamic_cast<PCB_DIM_LEADER*>( aItem ) == nullptr;
1466 };
1467
1470 groupDimension )
1471 .SetAvailableFunc( isNotLeader );
1474 groupDimension )
1475 .SetAvailableFunc( isNotLeader );
1476 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, wxString>( _HKI( "Override Text" ),
1478 groupDimension )
1479 .SetAvailableFunc( isNotLeader );
1480
1483 groupDimension )
1484 .SetAvailableFunc( isLeader );
1485
1488 groupDimension )
1489 .SetAvailableFunc( isNotLeader );
1492 groupDimension )
1493 .SetAvailableFunc( isNotLeader );
1496 groupDimension )
1497 .SetAvailableFunc( isNotLeader );
1498 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Suppress Trailing Zeroes" ),
1500 groupDimension )
1501 .SetAvailableFunc( isNotLeader );
1502
1503 const wxString groupText = _HKI( "Text Properties" );
1504
1505 const auto isTextOrientationWriteable =
1506 []( INSPECTABLE* aItem ) -> bool
1507 {
1508 return !static_cast<PCB_DIMENSION_BASE*>( aItem )->GetKeepTextAligned();
1509 };
1510
1511 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, bool>( _HKI( "Keep Aligned with Dimension" ),
1514 groupText );
1515
1516 propMgr.AddProperty( new PROPERTY<PCB_DIMENSION_BASE, double>( _HKI( "Orientation" ),
1519 PROPERTY_DISPLAY::PT_DEGREE ),
1520 groupText )
1521 .SetWriteableFunc( isTextOrientationWriteable );
1522 }
1524
1528
1529
1531{
1533 {
1544
1545 const wxString groupDimension = _HKI( "Dimension Properties" );
1546
1547 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Crossbar Height" ),
1550 groupDimension );
1551 propMgr.AddProperty( new PROPERTY<PCB_DIM_ALIGNED, int>( _HKI( "Extension Line Overshoot" ),
1554 groupDimension );
1555
1557 _HKI( "Visible" ),
1558 []( INSPECTABLE* aItem ) { return false; } );
1560 _HKI( "Text" ),
1561 []( INSPECTABLE* aItem ) { return false; } );
1563 _HKI( "Vertical Justification" ),
1564 []( INSPECTABLE* aItem ) { return false; } );
1566 _HKI( "Hyperlink" ),
1567 []( INSPECTABLE* aItem ) { return false; } );
1569 _HKI( "Knockout" ),
1570 []( INSPECTABLE* aItem ) { return false; } );
1571 }
1573
1574
1576{
1578 {
1591
1593 _HKI( "Visible" ),
1594 []( INSPECTABLE* aItem ) { return false; } );
1596 _HKI( "Text" ),
1597 []( INSPECTABLE* aItem ) { return false; } );
1599 _HKI( "Vertical Justification" ),
1600 []( INSPECTABLE* aItem ) { return false; } );
1602 _HKI( "Hyperlink" ),
1603 []( INSPECTABLE* aItem ) { return false; } );
1605 _HKI( "Knockout" ),
1606 []( INSPECTABLE* aItem ) { return false; } );
1607 }
1609
1610
1612{
1614 {
1625
1626 const wxString groupDimension = _HKI( "Dimension Properties" );
1627
1628 propMgr.AddProperty( new PROPERTY<PCB_DIM_RADIAL, int>( _HKI( "Leader Length" ),
1630 PROPERTY_DISPLAY::PT_SIZE ),
1631 groupDimension );
1632
1634 _HKI( "Visible" ),
1635 []( INSPECTABLE* aItem ) { return false; } );
1637 _HKI( "Text" ),
1638 []( INSPECTABLE* aItem ) { return false; } );
1640 _HKI( "Vertical Justification" ),
1641 []( INSPECTABLE* aItem ) { return false; } );
1643 _HKI( "Hyperlink" ),
1644 []( INSPECTABLE* aItem ) { return false; } );
1646 _HKI( "Knockout" ),
1647 []( INSPECTABLE* aItem ) { return false; } );
1648 }
1650
1651
1653{
1655 {
1657 .Map( DIM_TEXT_BORDER::NONE, _HKI( "None" ) )
1658 .Map( DIM_TEXT_BORDER::RECTANGLE, _HKI( "Rectangle" ) )
1659 .Map( DIM_TEXT_BORDER::CIRCLE, _HKI( "Circle" ) );
1660
1671
1672 const wxString groupDimension = _HKI( "Dimension Properties" );
1673
1676 groupDimension );
1677
1679 _HKI( "Visible" ),
1680 []( INSPECTABLE* aItem ) { return false; } );
1682 _HKI( "Text" ),
1683 []( INSPECTABLE* aItem ) { return false; } );
1685 _HKI( "Vertical Justification" ),
1686 []( INSPECTABLE* aItem ) { return false; } );
1688 _HKI( "Hyperlink" ),
1689 []( INSPECTABLE* aItem ) { return false; } );
1691 _HKI( "Knockout" ),
1692 []( INSPECTABLE* aItem ) { return false; } );
1693 }
1695
1697
1698
1700{
1702 {
1713
1714
1716 _HKI( "Visible" ),
1717 []( INSPECTABLE* aItem ) { return false; } );
1719 _HKI( "Text" ),
1720 []( INSPECTABLE* aItem ) { return false; } );
1722 _HKI( "Vertical Justification" ),
1723 []( INSPECTABLE* aItem ) { return false; } );
1725 _HKI( "Hyperlink" ),
1726 []( INSPECTABLE* aItem ) { return false; } );
1728 _HKI( "Knockout" ),
1729 []( INSPECTABLE* aItem ) { return false; } );
1730 }
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:231
PCB_LAYER_ID m_layer
Definition: board_item.h:398
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:265
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:236
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:569
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:1141
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:982
void SetTextAngleDegrees(double aOrientation)
Definition: eda_text.h:137
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:357
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 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)
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 ChangeKeepTextAligned(bool aKeepAligned)
void ChangeUnitsFormat(const DIM_UNITS_FORMAT aFormat)
void ChangeSuppressZeroes(bool aSuppress)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
virtual void Mirror(const VECTOR2I &axis_pos, bool aMirrorLeftRight=false)
Mirror the dimension relative to a given horizontal axis.
double GetTextAngleDegreesProp() const
bool GetOverrideTextEnabled() const
void SetUnitsMode(DIM_UNITS_MODE aMode)
int m_arrowLength
Length of arrow shapes.
virtual const VECTOR2I & GetEnd() const
VECTOR2I m_end
Internal cache of drawn shapes.
void ChangeUnitsMode(DIM_UNITS_MODE aMode)
void SetKeepTextAligned(bool aKeepAligned)
VECTOR2I GetPosition() const override
For better understanding of the points that make a dimension:
int GetHeight() const
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
int m_height
Perpendicular distance from features to crossbar.
void ChangeExtensionHeight(int aHeight)
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
VECTOR2I m_crossBarStart
Crossbar start control point.
void UpdateHeight(const VECTOR2I &aCrossbarStart, const VECTOR2I &aCrossbarEnd)
Update the stored height basing on points coordinates.
virtual void swapData(BOARD_ITEM *aImage) override
int m_extensionHeight
Length of extension lines past the crossbar.
VECTOR2I m_crossBarEnd
Crossbar end control point.
void Mirror(const VECTOR2I &axis_pos, bool aMirrorLeftRight=false) override
Mirror the dimension relative to a given horizontal axis.
PCB_DIM_ALIGNED(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIM_ALIGNED_T)
void ChangeHeight(int aHeight)
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
int GetExtensionHeight() const
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
Mark the center of a circle or arc with a cross shape.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
virtual void swapData(BOARD_ITEM *aImage) override
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
PCB_DIM_CENTER(BOARD_ITEM *aParent)
A leader is a dimension-like object pointing to a specific point.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
DIM_TEXT_BORDER m_textBorder
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
DIM_TEXT_BORDER GetTextBorder() const
virtual void swapData(BOARD_ITEM *aImage) override
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
PCB_DIM_LEADER(BOARD_ITEM *aParent)
void ChangeTextBorder(DIM_TEXT_BORDER aBorder)
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
void swapData(BOARD_ITEM *aImage) override
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
DIR m_orientation
What axis to lock the dimension line to.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
PCB_DIM_ORTHOGONAL(BOARD_ITEM *aParent)
A radial dimension indicates either the radius or diameter of an arc or circle.
int GetLeaderLength() const
PCB_DIM_RADIAL(BOARD_ITEM *aParent)
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
virtual void swapData(BOARD_ITEM *aImage) override
void updateGeometry() override
Update the cached geometry of the dimension after changing any of its properties.
void ChangeLeaderLength(int aLength)
VECTOR2I GetKnee() const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: pcb_text.cpp:249
bool TextHitTest(const VECTOR2I &aPoint, int aAccuracy=0) const override
Test if aPoint is within the bounds of this object.
Definition: pcb_text.cpp:408
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: pcb_text.cpp:511
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition: property.h:257
PROPERTY_BASE & SetWriteableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Definition: property.h:268
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:85
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:87
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int GetRadius() const
Definition: shape_circle.h:118
const VECTOR2I GetCenter() const
Definition: shape_circle.h:123
Base class for iterating over all segments in a given SHAPE_POLY_SET.
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
SEGMENT_ITERATOR IterateSegments(int aFirst, int aLast, bool aIterateHoles=false)
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
const SEG & GetSeg() const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
void SetUserUnits(EDA_UNITS aUnits)
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h: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