KiCad PCB EDA Suite
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, jean-pierre.charras@ujf-grenoble.fr
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
6  * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
7  * Copyright (C) 1992-2020 KiCad Developers, see AUTHORS.txt for contributors.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
27 #include <bitmaps.h>
28 #include <pcb_edit_frame.h>
29 #include <base_units.h>
30 #include <board.h>
31 #include <dimension.h>
32 #include <pcb_text.h>
33 #include <geometry/shape_circle.h>
34 #include <geometry/shape_segment.h>
37 #include <trigo.h>
38 #include <i18n_utility.h>
39 
40 
42  BOARD_ITEM( aParent, aType ),
43  m_overrideTextEnabled( false ),
44  m_units( EDA_UNITS::INCHES ),
45  m_autoUnits( false ),
46  m_unitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX ),
47  m_precision( 4 ),
48  m_suppressZeroes( false ),
49  m_lineThickness( Millimeter2iu( 0.2 ) ),
50  m_arrowLength( Mils2iu( 50 ) ),
51  m_extensionOffset( 0 ),
52  m_textPosition( DIM_TEXT_POSITION::OUTSIDE ),
53  m_keepTextAligned( true ),
54  m_text( aParent ),
55  m_measuredValue( 0 )
56 {
58 }
59 
60 
62 {
63  BOARD_ITEM::SetParent( aParent );
64  m_text.SetParent( aParent );
65 }
66 
67 
69 {
70  wxString text = m_overrideTextEnabled ? m_valueString : GetValueText();
71 
72  switch( m_unitsFormat )
73  {
74  case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
75  break;
76 
77  case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
78  text += " ";
80  break;
81 
82  case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
83  text += " (";
85  text += ")";
86  break;
87  }
88 
89  text.Prepend( m_prefix );
90  text.Append( m_suffix );
91 
92  m_text.SetText( text );
93 }
94 
95 
96 template<typename ShapeType>
97 void DIMENSION_BASE::addShape( const ShapeType& aShape )
98 {
99  m_shapes.push_back( std::make_shared<ShapeType>( aShape ) );
100 }
101 
102 
104 {
105  struct lconv* lc = localeconv();
106  wxChar sep = lc->decimal_point[0];
107 
108  int val = GetMeasuredValue();
109  wxString text;
110  wxString format = wxT( "%." ) + wxString::Format( "%i", m_precision ) + wxT( "f" );
111 
112  text.Printf( format, To_User_Unit( m_units, val ) );
113 
114  if( m_suppressZeroes )
115  {
116  while( text.Last() == '0' )
117  {
118  text.RemoveLast();
119 
120  if( text.Last() == '.' || text.Last() == sep )
121  {
122  text.RemoveLast();
123  break;
124  }
125  }
126  }
127 
128  return text;
129 }
130 
131 
132 void DIMENSION_BASE::SetPrefix( const wxString& aPrefix )
133 {
134  m_prefix = aPrefix;
135 }
136 
137 
138 void DIMENSION_BASE::SetSuffix( const wxString& aSuffix )
139 {
140  m_suffix = aSuffix;
141 }
142 
143 
145 {
146  m_units = aUnits;
147 }
148 
149 
151 {
152  if( m_autoUnits )
153  {
155  }
156  else
157  {
158  switch( m_units )
159  {
162 
163  case EDA_UNITS::MILS:
164  return DIM_UNITS_MODE::MILS;
165 
166  default:
167  case EDA_UNITS::INCHES:
168  return DIM_UNITS_MODE::INCHES;
169  }
170  }
171 }
172 
173 
175 {
176  m_autoUnits = false;
177 
178  switch( aMode )
179  {
182  break;
183 
186  break;
187 
190  break;
191 
193  m_autoUnits = true;
194  break;
195  }
196 }
197 
198 
199 void DIMENSION_BASE::SetText( const wxString& aNewText )
200 {
201  m_valueString = aNewText;
202  updateText();
203 }
204 
205 
206 const wxString DIMENSION_BASE::GetText() const
207 {
208  return m_text.GetText();
209 }
210 
211 
213 {
214  m_layer = aLayer;
215  m_text.SetLayer( aLayer );
216 }
217 
218 
219 void DIMENSION_BASE::Move( const wxPoint& offset )
220 {
221  m_text.Offset( offset );
222 
223  m_start += offset;
224  m_end += offset;
225 
226  Update();
227 }
228 
229 
230 void DIMENSION_BASE::Rotate( const wxPoint& aRotCentre, double aAngle )
231 {
232  if( m_keepTextAligned )
233  m_keepTextAligned = false;
234 
235  double newAngle = m_text.GetTextAngle() + aAngle;
236 
237  if( newAngle >= 3600 )
238  newAngle -= 3600;
239 
240  m_text.SetTextAngle( newAngle );
241 
242  wxPoint pt = m_text.GetTextPos();
243  RotatePoint( &pt, aRotCentre, aAngle );
244  m_text.SetTextPos( pt );
245 
246  RotatePoint( &m_start, aRotCentre, aAngle );
247  RotatePoint( &m_end, aRotCentre, aAngle );
248 
249  Update();
250 }
251 
252 
253 void DIMENSION_BASE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
254 {
255  Mirror( aCentre );
256 
257  SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) );
258 }
259 
260 
261 void DIMENSION_BASE::Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight )
262 {
263  int axis = aMirrorLeftRight ? axis_pos.x : axis_pos.y;
264  wxPoint newPos = m_text.GetTextPos();
265 
266 #define INVERT( pos ) ( ( pos ) = axis - ( ( pos ) - axis ) )
267  if( aMirrorLeftRight )
268  INVERT( newPos.x );
269  else
270  INVERT( newPos.y );
271 
272  m_text.SetTextPos( newPos );
273 
274  // invert angle
276 
277  if( aMirrorLeftRight )
278  {
279  INVERT( m_start.x );
280  INVERT( m_end.x );
281  }
282  else
283  {
284  INVERT( m_start.y );
285  INVERT( m_end.y );
286  }
287 
289 
290  Update();
291 }
292 
293 
294 void DIMENSION_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
295 {
296  // for now, display only the text within the DIMENSION using class PCB_TEXT.
297  wxString msg;
298 
299  wxCHECK_RET( m_parent != NULL, wxT( "PCB_TEXT::GetMsgPanelInfo() m_Parent is NULL." ) );
300 
301  aList.emplace_back( _( "Dimension" ), m_text.GetShownText() );
302 
303  aList.emplace_back( _( "Prefix" ), GetPrefix() );
304 
305  if( GetOverrideTextEnabled() )
306  {
307  aList.emplace_back( _( "Override Text" ), GetOverrideText() );
308  }
309  else
310  {
311  aList.emplace_back( _( "Value" ), GetValueText() );
312 
313  msg = "%" + wxString::Format( "1.%df", GetPrecision() );
314  aList.emplace_back( _( "Precision" ), wxString::Format( msg, 0.0 ) );
315  }
316 
317  aList.emplace_back( _( "Suffix" ), GetSuffix() );
318 
319  EDA_UNITS units;
320 
321  GetUnits( units );
322  aList.emplace_back( _( "Units" ), GetAbbreviatedUnitsLabel( units ) );
323 
324  ORIGIN_TRANSFORMS originTransforms = aFrame->GetOriginTransforms();
325  units = aFrame->GetUserUnits();
326 
327  if( Type() == PCB_DIM_CENTER_T )
328  {
329  wxPoint startCoord = originTransforms.ToDisplayAbs( GetStart() );
330  wxString start = wxString::Format( "@(%s, %s)",
331  MessageTextFromValue( units, startCoord.x ),
332  MessageTextFromValue( units, startCoord.y ) );
333 
334  aList.emplace_back( start, wxEmptyString );
335  }
336  else
337  {
338  wxPoint startCoord = originTransforms.ToDisplayAbs( GetStart() );
339  wxString start = wxString::Format( "@(%s, %s)",
340  MessageTextFromValue( units, startCoord.x ),
341  MessageTextFromValue( units, startCoord.y ) );
342  wxPoint endCoord = originTransforms.ToDisplayAbs( GetEnd() );
343  wxString end = wxString::Format( "@(%s, %s)",
344  MessageTextFromValue( units, endCoord.x ),
345  MessageTextFromValue( units, endCoord.y ) );
346 
347  aList.emplace_back( start, end );
348  }
349 
350  aList.emplace_back( _( "Layer" ), GetLayerName() );
351 }
352 
353 
354 std::shared_ptr<SHAPE> DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
355 {
356  std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
357 
358  effectiveShape->AddShape( Text().GetEffectiveTextShape()->Clone() );
359 
360  for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
361  effectiveShape->AddShape( shape->Clone() );
362 
363  return effectiveShape;
364 }
365 
366 
367 bool DIMENSION_BASE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
368 {
369  if( m_text.TextHitTest( aPosition ) )
370  return true;
371 
372  int dist_max = aAccuracy + ( m_lineThickness / 2 );
373 
374  // Locate SEGMENTS
375 
376  for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
377  {
378  if( shape->Collide( aPosition, dist_max ) )
379  return true;
380  }
381 
382  return false;
383 }
384 
385 
386 bool DIMENSION_BASE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
387 {
388  EDA_RECT arect = aRect;
389  arect.Inflate( aAccuracy );
390 
391  EDA_RECT rect = GetBoundingBox();
392 
393  if( aAccuracy )
394  rect.Inflate( aAccuracy );
395 
396  if( aContained )
397  return arect.Contains( rect );
398 
399  return arect.Intersects( rect );
400 }
401 
402 
404 {
405  EDA_RECT bBox;
406  int xmin, xmax, ymin, ymax;
407 
408  bBox = m_text.GetTextBox();
409  xmin = bBox.GetX();
410  xmax = bBox.GetRight();
411  ymin = bBox.GetY();
412  ymax = bBox.GetBottom();
413 
414  for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
415  {
416  BOX2I shapeBox = shape->BBox();
417  shapeBox.Inflate( m_lineThickness / 2 );
418 
419  xmin = std::min( xmin, shapeBox.GetOrigin().x );
420  xmax = std::max( xmax, shapeBox.GetEnd().x );
421  ymin = std::min( ymin, shapeBox.GetOrigin().y );
422  ymax = std::max( ymax, shapeBox.GetEnd().y );
423  }
424 
425  bBox.SetX( xmin );
426  bBox.SetY( ymin );
427  bBox.SetWidth( xmax - xmin + 1 );
428  bBox.SetHeight( ymax - ymin + 1 );
429 
430  bBox.Normalize();
431 
432  return bBox;
433 }
434 
435 
437 {
438  return wxString::Format( _( "Dimension '%s' on %s" ),
439  GetText(),
440  GetLayerName() );
441 }
442 
443 
444 
446 {
447  BOX2I dimBBox = BOX2I( VECTOR2I( GetBoundingBox().GetPosition() ),
448  VECTOR2I( GetBoundingBox().GetSize() ) );
449  dimBBox.Merge( m_text.ViewBBox() );
450 
451  return dimBBox;
452 }
453 
454 
456 {
457  VECTOR2I start( aStart ? aSeg.A : aSeg.B );
458  VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
459 
460  if( aPoly.Contains( start ) )
461  return NULLOPT;
462 
463  for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = aPoly.IterateSegments(); seg; seg++ )
464  {
465  if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
466  {
467  if( ( *intersection - start ).SquaredEuclideanNorm() <
468  ( endpoint - start ).SquaredEuclideanNorm() )
469  endpoint = *intersection;
470  }
471  }
472  if( start == endpoint )
473  return NULLOPT;
474 
475  return OPT_VECTOR2I( endpoint );
476 }
477 
478 
480 {
481  VECTOR2I start( aStart ? aSeg.A : aSeg.B );
482  VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
483 
484  if( aCircle.Contains( start ) )
485  return NULLOPT;
486 
487  std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
488 
489  for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
490  {
491  if( ( intersection - start ).SquaredEuclideanNorm() <
492  ( endpoint - start ).SquaredEuclideanNorm() )
493  endpoint = intersection;
494  }
495 
496  if( start == endpoint )
497  return NULLOPT;
498 
499  return OPT_VECTOR2I( endpoint );
500 }
501 
502 
504  DIMENSION_BASE( aParent, aType ),
505  m_height( 0 )
506 {
507  // To preserve look of old dimensions, initialize extension height based on default arrow length
508  m_extensionHeight = static_cast<int>( m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) ) );
509 }
510 
511 
513 {
514  return new ALIGNED_DIMENSION( *this );
515 }
516 
517 
519 {
520  assert( aImage->Type() == PCB_DIM_ALIGNED_T );
521 
522  m_shapes.clear();
523  static_cast<ALIGNED_DIMENSION*>( aImage )->m_shapes.clear();
524 
525  std::swap( *static_cast<ALIGNED_DIMENSION*>( this ),
526  *static_cast<ALIGNED_DIMENSION*>( aImage ) );
527 
528  Update();
529 }
530 
532 {
534 }
535 
536 
537 void ALIGNED_DIMENSION::UpdateHeight( const wxPoint& aCrossbarStart, const wxPoint& aCrossbarEnd )
538 {
539  VECTOR2D height( aCrossbarStart - GetStart() );
540  VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
541 
542  if( height.Cross( crossBar ) > 0 )
543  m_height = -height.EuclideanNorm();
544  else
545  m_height = height.EuclideanNorm();
546 
547  Update();
548 }
549 
550 
552 {
553  m_shapes.clear();
554 
555  VECTOR2I dimension( m_end - m_start );
556 
557  m_measuredValue = KiROUND( dimension.EuclideanNorm() );
558 
559  VECTOR2I extension;
560 
561  if( m_height > 0 )
562  extension = VECTOR2I( -dimension.y, dimension.x );
563  else
564  extension = VECTOR2I( dimension.y, -dimension.x );
565 
566  // Add extension lines
567  int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
568 
569  VECTOR2I extStart( m_start );
570  extStart += extension.Resize( m_extensionOffset );
571 
572  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
573 
574  extStart = VECTOR2I( m_end );
575  extStart += extension.Resize( m_extensionOffset );
576 
577  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
578 
579  // Add crossbar
580  VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
581  m_crossBarStart = m_start + wxPoint( crossBarDistance );
582  m_crossBarEnd = m_end + wxPoint( crossBarDistance );
583 
584  // Update text after calculating crossbar position but before adding crossbar lines
585  updateText();
586 
587  // Now that we have the text updated, we can determine how to draw the crossbar.
588  // First we need to create an appropriate bounding polygon to collide with
591 
592  SHAPE_POLY_SET polyBox;
593  polyBox.NewOutline();
594  polyBox.Append( textBox.GetOrigin() );
595  polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
596  polyBox.Append( textBox.GetEnd() );
597  polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
598  polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
599 
600  // The ideal crossbar, if the text doesn't collide
601  SEG crossbar( m_crossBarStart, m_crossBarEnd );
602 
603  // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
604  bool containsA = polyBox.Contains( crossbar.A );
605  bool containsB = polyBox.Contains( crossbar.B );
606 
607  OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
608  OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
609 
610  if( endpointA )
611  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
612 
613  if( endpointB )
614  m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
615 
616  if( !containsA && !containsB && !endpointA && !endpointB )
617  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
618 
619  // Add arrows
620  VECTOR2I arrowEnd( m_arrowLength, 0 );
621 
622  double arrowRotPos = dimension.Angle() + DEG2RAD( s_arrowAngle );
623  double arrowRotNeg = dimension.Angle() - DEG2RAD( s_arrowAngle );
624 
625  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
626  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
627 
628  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
629  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
630 
631  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
632  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
633 
634  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
635  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
636 }
637 
638 
640 {
641  VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
642 
644  {
645  int textOffsetDistance = m_text.GetEffectiveTextPenWidth() + m_text.GetTextHeight();
646 
647  double rotation = std::copysign( DEG2RAD( 90 ), m_height );
648  VECTOR2I textOffset = crossbarCenter.Rotate( rotation ).Resize( textOffsetDistance );
649  textOffset += crossbarCenter;
650 
651  m_text.SetTextPos( m_crossBarStart + wxPoint( textOffset ) );
652  }
654  {
655  m_text.SetTextPos( m_crossBarStart + wxPoint( crossbarCenter ) );
656  }
657 
658  if( m_keepTextAligned )
659  {
660  double textAngle = 3600 - RAD2DECIDEG( crossbarCenter.Angle() );
661 
662  NORMALIZE_ANGLE_POS( textAngle );
663 
664  if( textAngle > 900 && textAngle < 2700 )
665  textAngle -= 1800;
666 
667  m_text.SetTextAngle( textAngle );
668  }
669 
671 }
672 
673 
675  std::vector<MSG_PANEL_ITEM>& aList )
676 {
677  DIMENSION_BASE::GetMsgPanelInfo( aFrame, aList );
678 
679  aList.emplace_back( _( "Height" ), MessageTextFromValue( aFrame->GetUserUnits(), m_height ) );
680 }
681 
682 
685 {
686  // To preserve look of old dimensions, initialize extension height based on default arrow length
687  m_extensionHeight = static_cast<int>( m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) ) );
689 }
690 
691 
693 {
694  return new ORTHOGONAL_DIMENSION( *this );
695 }
696 
697 
699 {
700  assert( aImage->Type() == PCB_DIM_ORTHOGONAL_T );
701 
702  m_shapes.clear();
703  static_cast<ORTHOGONAL_DIMENSION*>( aImage )->m_shapes.clear();
704 
705  std::swap( *static_cast<ORTHOGONAL_DIMENSION*>( this ),
706  *static_cast<ORTHOGONAL_DIMENSION*>( aImage ) );
707 
708  Update();
709 }
710 
711 
713 {
715 }
716 
717 
719 {
720  m_shapes.clear();
721 
722  int measurement = ( m_orientation == DIR::HORIZONTAL ? m_end.x - m_start.x :
723  m_end.y - m_start.y );
724  m_measuredValue = KiROUND( std::abs( measurement ) );
725 
726  VECTOR2I extension;
727 
729  extension = VECTOR2I( 0, m_height );
730  else
731  extension = VECTOR2I( m_height, 0 );
732 
733  // Add first extension line
734  int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
735 
736  VECTOR2I extStart( m_start );
737  extStart += extension.Resize( m_extensionOffset );
738 
739  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
740 
741  // Add crossbar
742  VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
743  m_crossBarStart = m_start + wxPoint( crossBarDistance );
744 
746  m_crossBarEnd = wxPoint( m_end.x, m_crossBarStart.y );
747  else
748  m_crossBarEnd = wxPoint( m_crossBarStart.x, m_end.y );
749 
750  // Add second extension line (m_end to crossbar end)
752  extension = VECTOR2I( 0, m_end.y - m_crossBarEnd.y );
753  else
754  extension = VECTOR2I( m_end.x - m_crossBarEnd.x, 0 );
755 
756  extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
757 
758  extStart = VECTOR2I( m_crossBarEnd );
759  extStart -= extension.Resize( m_extensionHeight );
760 
761  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
762 
763  // Update text after calculating crossbar position but before adding crossbar lines
764  updateText();
765 
766  // Now that we have the text updated, we can determine how to draw the crossbar.
767  // First we need to create an appropriate bounding polygon to collide with
770 
771  SHAPE_POLY_SET polyBox;
772  polyBox.NewOutline();
773  polyBox.Append( textBox.GetOrigin() );
774  polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
775  polyBox.Append( textBox.GetEnd() );
776  polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
777  polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
778 
779  // The ideal crossbar, if the text doesn't collide
780  SEG crossbar( m_crossBarStart, m_crossBarEnd );
781 
782  // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
783  bool containsA = polyBox.Contains( crossbar.A );
784  bool containsB = polyBox.Contains( crossbar.B );
785 
786  OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
787  OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
788 
789  if( endpointA )
790  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
791 
792  if( endpointB )
793  m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
794 
795  if( !containsA && !containsB && !endpointA && !endpointB )
796  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
797 
798  // Add arrows
799  VECTOR2I crossBarAngle( m_crossBarEnd - m_crossBarStart );
800  VECTOR2I arrowEnd( m_arrowLength, 0 );
801 
802  double arrowRotPos = crossBarAngle.Angle() + DEG2RAD( s_arrowAngle );
803  double arrowRotNeg = crossBarAngle.Angle() - DEG2RAD( s_arrowAngle );
804 
805  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
806  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
807 
808  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
809  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
810 
811  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
812  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
813 
814  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
815  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
816 }
817 
818 
820 {
821  VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
822 
824  {
825  int textOffsetDistance = m_text.GetEffectiveTextPenWidth() + m_text.GetTextHeight();
826 
827  VECTOR2D height( m_crossBarStart - GetStart() );
828  VECTOR2D crossBar( m_crossBarEnd - m_crossBarStart );
829 
830  double sign = height.Cross( crossBar ) > 0 ? 1 : -1;
831  double rotation = sign * DEG2RAD( -90 );
832 
833  VECTOR2I textOffset = crossbarCenter.Rotate( rotation ).Resize( textOffsetDistance );
834  textOffset += crossbarCenter;
835 
836  m_text.SetTextPos( m_crossBarStart + wxPoint( textOffset ) );
837  m_text.SetTextAngle(rotation);
838  }
840  {
841  m_text.SetTextPos( m_crossBarStart + wxPoint( crossbarCenter ) );
842  }
843 
844  if( m_keepTextAligned )
845  {
846  double textAngle = 3600 - RAD2DECIDEG( crossbarCenter.Angle() );
847 
848  NORMALIZE_ANGLE_POS( textAngle );
849 
850  if( textAngle > 900 && textAngle < 2700 )
851  textAngle -= 1800;
852 
853  m_text.SetTextAngle( textAngle );
854  }
855 
857 }
858 
859 
861  DIMENSION_BASE( aParent, PCB_DIM_LEADER_T ),
862  m_textFrame( DIM_TEXT_FRAME::NONE )
863 {
865  m_overrideTextEnabled = true;
866  m_keepTextAligned = false;
867 }
868 
869 
871 {
872  return new LEADER( *this );
873 }
874 
875 
877 {
878  assert( aImage->Type() == PCB_DIM_LEADER_T );
879 
880  std::swap( *static_cast<LEADER*>( this ), *static_cast<LEADER*>( aImage ) );
881 }
882 
883 
885 {
886  return add_leader_xpm;
887 }
888 
889 
891 {
892  m_shapes.clear();
893 
894  updateText();
895 
896  // Now that we have the text updated, we can determine how to draw the second line
897  // First we need to create an appropriate bounding polygon to collide with
900 
901  SHAPE_POLY_SET polyBox;
902  polyBox.NewOutline();
903  polyBox.Append( textBox.GetOrigin() );
904  polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
905  polyBox.Append( textBox.GetEnd() );
906  polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
907  polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
908 
909  VECTOR2I firstLine( m_end - m_start );
910  VECTOR2I start( m_start );
911  start += firstLine.Resize( m_extensionOffset );
912 
913  SEG arrowSeg( m_start, m_end );
914  SEG textSeg( m_end, m_text.GetPosition() );
915  OPT_VECTOR2I arrowSegEnd, textSegEnd;
916 
918  {
919  double penWidth = m_text.GetEffectiveTextPenWidth() / 2.0;
920  double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
921  CIRCLE circle( textBox.GetCenter(), radius );
922 
923  arrowSegEnd = segCircleIntersection( circle, arrowSeg );
924  textSegEnd = segCircleIntersection( circle, textSeg );
925  }
926  else
927  {
928  arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
929  textSegEnd = segPolyIntersection( polyBox, textSeg );
930  }
931 
932  if( !arrowSegEnd )
933  arrowSegEnd = m_end;
934 
935  m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
936 
937  // Add arrows
938  VECTOR2I arrowEnd( m_arrowLength, 0 );
939 
940  double arrowRotPos = firstLine.Angle() + DEG2RAD( s_arrowAngle );
941  double arrowRotNeg = firstLine.Angle() - DEG2RAD( s_arrowAngle );
942 
943  m_shapes.emplace_back( new SHAPE_SEGMENT( start,
944  start + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
945  m_shapes.emplace_back( new SHAPE_SEGMENT( start,
946  start + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
947 
948 
949  if( !GetText().IsEmpty() )
950  {
951  switch( m_textFrame )
952  {
954  {
955  for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
956  m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
957 
958  break;
959  }
960 
962  {
963  double penWidth = m_text.GetEffectiveTextPenWidth() / 2.0;
964  double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
965  m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
966 
967  break;
968  }
969 
970  default:
971  break;
972  }
973  }
974 
975  if( textSegEnd && *arrowSegEnd == m_end )
976  m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textSegEnd ) );
977 }
978 
979 
980 void LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
981 {
982  wxString msg;
983 
984  aList.emplace_back( _( "Leader" ), m_text.GetShownText() );
985 
986  ORIGIN_TRANSFORMS originTransforms = aFrame->GetOriginTransforms();
987  EDA_UNITS units = aFrame->GetUserUnits();
988 
989  wxPoint startCoord = originTransforms.ToDisplayAbs( GetStart() );
990  wxString start = wxString::Format( "@(%s, %s)",
991  MessageTextFromValue( units, startCoord.x ),
992  MessageTextFromValue( units, startCoord.y ) );
993 
994  aList.emplace_back( start, wxEmptyString );
995 
996  aList.emplace_back( _( "Layer" ), GetLayerName() );
997 }
998 
999 
1001  DIMENSION_BASE( aParent, PCB_DIM_CENTER_T )
1002 {
1004  m_overrideTextEnabled = true;
1005 }
1006 
1007 
1009 {
1010  return new CENTER_DIMENSION( *this );
1011 }
1012 
1013 
1015 {
1016  assert( aImage->Type() == PCB_DIM_CENTER_T );
1017 
1018  std::swap( *static_cast<CENTER_DIMENSION*>( this ), *static_cast<CENTER_DIMENSION*>( aImage ) );
1019 }
1020 
1021 
1023 {
1024  return add_center_dimension_xpm;
1025 }
1026 
1027 
1029 {
1030  int halfWidth = VECTOR2I( m_end - m_start ).x + ( m_lineThickness / 2.0 );
1031 
1032  EDA_RECT bBox;
1033 
1034  bBox.SetX( m_start.x - halfWidth );
1035  bBox.SetY( m_start.y - halfWidth );
1036  bBox.SetWidth( halfWidth * 2 );
1037  bBox.SetHeight( halfWidth * 2 );
1038 
1039  bBox.Normalize();
1040 
1041  return bBox;
1042 }
1043 
1044 
1046 {
1047  return BOX2I( VECTOR2I( GetBoundingBox().GetPosition() ),
1048  VECTOR2I( GetBoundingBox().GetSize() ) );
1049 }
1050 
1051 
1053 {
1054  m_shapes.clear();
1055 
1056  VECTOR2I center( m_start );
1057  VECTOR2I arm( m_end - m_start );
1058 
1059  m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1060 
1061  arm = arm.Rotate( DEG2RAD( 90 ) );
1062 
1063  m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1064 }
1065 
1066 
1067 static struct DIMENSION_DESC
1068 {
1070  {
1074  // TODO: add dimension properties:
1075  //propMgr.AddProperty( new PROPERTY<DIMENSION, int>( _HKI( "Height" ),
1076  //&DIMENSION::SetHeight, &DIMENSION::GetHeight, PROPERTY_DISPLAY::DISTANCE ) );
1077  }
1078 } _DIMENSION_DESC;
1079 
1080 
void SetMirrored(bool isMirrored)
Definition: eda_text.h:195
CENTER_DIMENSION(BOARD_ITEM *aParent)
Definition: dimension.cpp:1000
int m_extensionHeight
Length of extension lines past the crossbar.
Definition: dimension.h:339
extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition: vector2d.h:513
int sign(T val)
Definition: util.h:101
void Offset(const wxPoint &aOffset)
Definition: eda_text.h:259
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:528
wxString MessageTextFromValue(EDA_UNITS aUnits, int aValue, bool aAddUnitLabel, EDA_DATA_TYPE aType)
Convert a value to a string using double notation.
Definition: base_units.cpp:125
BOX2< VECTOR2I > BOX2I
Definition: box2.h:522
bool GetOverrideTextEnabled() const
Definition: dimension.h:130
static PROPERTY_MANAGER & Instance()
Definition: property_mgr.h:66
#define TYPE_HASH(x)
Definition: property.h:57
class ALIGNED_DIMENSION, a linear dimension (graphic item)
Definition: typeinfo.h:100
class LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:101
bool IsMirrored() const
Definition: eda_text.h:196
BITMAP_DEF GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: dimension.cpp:531
PNG memory record (file in memory).
Definition: bitmap_def.h:29
bool m_suppressZeroes
Suppress trailing zeroes.
Definition: dimension.h:286
static constexpr float s_arrowAngle
Definition: dimension.h:304
void SetParent(EDA_ITEM *aParent) override
Definition: dimension.cpp:61
BITMAP_DEF GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: dimension.cpp:884
wxString GetSelectMenuText(EDA_UNITS aUnits) const override
Return the text to display to be used in the selection clarification context menu when multiple items...
Definition: dimension.cpp:436
const BITMAP_OPAQUE add_leader_xpm[1]
Definition: add_leader.cpp:42
int m_precision
Number of digits to display after decimal.
Definition: dimension.h:285
const Vec GetEnd() const
Definition: box2.h:195
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition: board_item.h:194
Implementation of conversion functions that require both schematic and board internal units.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
wxString m_prefix
String prepended to the value.
Definition: dimension.h:280
DIM_UNITS_MODE GetUnitsMode() const
Definition: dimension.cpp:150
int GetX() const
Definition: eda_rect.h:103
bool m_autoUnits
If true, follow the currently selected UI units.
Definition: dimension.h:283
void SetTextAngle(double aAngle) override
Definition: pcb_text.cpp:102
class CENTER_DIMENSION, a center point marking (graphic item)
Definition: typeinfo.h:102
void updateGeometry() override
Updates the cached geometry of the dimension after changing any of its properties.
Definition: dimension.cpp:1052
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
Definition: dimension.cpp:212
void Flip(const wxPoint &aCentre, bool aFlipLeftRight) override
Flip this object, i.e.
Definition: dimension.cpp:253
bool m_overrideTextEnabled
Manually specify the displayed measurement value.
Definition: dimension.h:278
void updateText() override
Updates the text field value from the current geometry (called by updateGeometry normally)
Definition: dimension.cpp:639
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition: lset.cpp:521
EDA_RECT GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:223
virtual const wxPoint & GetStart() const
The dimension's origin is the first feature point for the dimension.
Definition: dimension.h:121
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:253
int GetWidth() const
Definition: eda_rect.h:114
void SetPrefix(const wxString &aPrefix)
Definition: dimension.cpp:132
double GetTextAngle() const
Definition: eda_text.h:181
double RAD2DECIDEG(double rad)
Definition: trigo.h:236
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: dimension.cpp:876
virtual ORIGIN_TRANSFORMS & GetOriginTransforms()
Return a reference to the default ORIGIN_TRANSFORMS object.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: dimension.cpp:870
Base class for iterating over all segments in a given SHAPE_POLY_SET.
wxPoint m_start
Definition: dimension.h:298
void SetUnits(EDA_UNITS aUnits)
Definition: dimension.cpp:144
wxString GetOverrideText() const
Definition: dimension.h:133
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
int m_extensionOffset
Distance from feature points to extension line start.
Definition: dimension.h:291
wxString GetAbbreviatedUnitsLabel(EDA_UNITS aUnit, EDA_DATA_TYPE aType)
Get the units string for a given units type.
Definition: base_units.cpp:472
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.
void Update()
Updates the dimension's cached text and geometry.
Definition: dimension.h:146
const wxString GetText() const
Retrieves the value text or override text, not including prefix or suffix.
Definition: dimension.cpp:206
void addShape(const ShapeType &aShape)
Definition: dimension.cpp:97
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:228
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:288
The base class for create windows for drawing purpose.
T ToDisplayAbs(const T &aValue) const
const BITMAP_OPAQUE add_aligned_dimension_xpm[1]
LEADER(BOARD_ITEM *aParent)
Definition: dimension.cpp:860
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
int GetPrecision() const
Definition: dimension.h:169
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: dimension.cpp:403
#define REGISTER_TYPE(x)
Definition: property_mgr.h:249
bool Contains(const wxPoint &aPoint) const
Definition: eda_rect.cpp:57
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:165
static OPT_VECTOR2I segCircleIntersection(CIRCLE &aCircle, SEG &aSeg, bool aStart=true)
Definition: dimension.cpp:479
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition: eda_item.cpp:97
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:157
int m_height
Perpendicular distance from features to crossbar.
Definition: dimension.h:338
int GetBottom() const
Definition: eda_rect.h:119
int GetTextHeight() const
Definition: eda_text.h:251
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: dimension.cpp:1014
int m_arrowLength
Length of arrow shapes.
Definition: dimension.h:290
wxString m_suffix
String appended to the value.
Definition: dimension.h:281
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: pcb_text.cpp:53
void updateText() override
Updates the text field value from the current geometry (called by updateGeometry normally)
Definition: dimension.cpp:819
const wxPoint GetEnd() const
Definition: eda_rect.h:108
void SetText(const wxString &aNewText)
Sets the override text - has no effect if m_overrideValue == false.
Definition: dimension.cpp:199
PCB_LAYER_ID
A quick note on layer IDs:
wxString GetSuffix() const
Definition: dimension.h:155
bool m_keepTextAligned
Calculate text orientation to match dimension.
Definition: dimension.h:293
const std::vector< std::shared_ptr< SHAPE > > & GetShapes() const
Definition: dimension.h:215
const BITMAP_OPAQUE add_orthogonal_dimension_xpm[1]
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: dimension.cpp:692
static OPT_VECTOR2I segPolyIntersection(SHAPE_POLY_SET &aPoly, SEG &aSeg, bool aStart=true)
Finds the intersection between a given segment and polygon outline.
Definition: dimension.cpp:455
const auto NULLOPT
Definition: optional.h:9
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:121
wxString GetPrefix() const
Definition: dimension.h:152
#define NULL
virtual wxPoint GetPosition() const override
Definition: pcb_text.h:72
OPT< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
void SetHeight(int val)
Definition: eda_rect.h:181
#define INVERT(pos)
Represent a set of closed polygons.
void updateGeometry() override
Updates the cached geometry of the dimension after changing any of its properties.
Definition: dimension.cpp:890
const wxPoint GetOrigin() const
Definition: eda_rect.h:106
void GetUnits(EDA_UNITS &aUnits) const
Definition: dimension.h:158
EDA_UNITS m_units
0 = inches, 1 = mm
Definition: dimension.h:282
PCB_TEXT & Text()
Definition: dimension.h:209
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
int GetRight() const
Definition: eda_rect.h:116
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
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.
Definition: dimension.cpp:980
PCB_TEXT m_text
The actual text object.
Definition: dimension.h:296
BITMAP_DEF GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: dimension.cpp:1022
void SetX(int val)
Definition: eda_rect.h:163
void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: dimension.cpp:698
void Move(const wxPoint &offset) override
Move this object.
Definition: dimension.cpp:219
Text appears outside the dimension line (default)
Class Circle Represents basic circle geometry with utility geometry functions.
Definition: circle.h:33
void Rotate(const wxPoint &aRotCentre, double aAngle) override
Rotate this object.
Definition: dimension.cpp:230
DIM_TEXT_FRAME
Frame to show around dimension text.
Definition: dimension.h:68
static struct DIMENSION_DESC _DIMENSION_DESC
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect.
Definition: box2.h:386
double Angle() const
Compute the angle of the vector.
Definition: vector2d.h:307
void SetWidth(int val)
Definition: eda_rect.h:175
void SetSuffix(const wxString &aSuffix)
Definition: dimension.cpp:138
int m_measuredValue
value of PCB dimensions
Definition: dimension.h:297
int NewOutline()
Creates a new hole in a given outline.
Text appears in line with the dimension line.
void UpdateHeight(const wxPoint &aCrossbarStart, const wxPoint &aCrossbarEnd)
Updates stored height basing on points coordinates.
Definition: dimension.cpp:537
void SetY(int val)
Definition: eda_rect.h:169
bool Contains(const VECTOR2I &aP)
Function Contains()
Definition: circle.cpp:341
Some functions to handle hotkeys in KiCad.
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Definition: seg.h:41
EDA_UNITS
Definition: eda_units.h:38
int GetMeasuredValue() const
Definition: dimension.h:136
double GetTextAngleRadians() const
Definition: eda_text.h:184
void Normalize()
Ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
No updates are required.
Definition: view_item.h:51
wxPoint GetPosition() const override
Definition: dimension.h:127
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:404
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: dimension.cpp:354
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:302
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371
double To_User_Unit(EDA_UNITS aUnit, double aValue)
Function To_User_Unit convert aValue in internal units to the appropriate user units defined by aUnit...
Definition: base_units.cpp:91
void updateGeometry() override
Updates the cached geometry of the dimension after changing any of its properties.
Definition: dimension.cpp:718
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: dimension.cpp:445
int GetTextWidth() const
Definition: eda_text.h:248
DIM_TEXT_FRAME m_textFrame
Definition: dimension.h:479
double DEG2RAD(double deg)
Definition: trigo.h:231
A class to perform either relative or absolute display origin transforms for a single axis of a point...
ALIGNED_DIMENSION(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIM_ALIGNED_T)
Definition: dimension.cpp:503
std::vector< VECTOR2I > Intersect(const CIRCLE &aCircle) const
Function Intersect()
Definition: circle.cpp:200
#define _(s)
Definition: 3d_actions.cpp:33
const BITMAP_OPAQUE add_center_dimension_xpm[1]
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: dimension.cpp:1028
std::vector< std::shared_ptr< SHAPE > > m_shapes
Definition: dimension.h:302
VECTOR2I A
Definition: seg.h:49
DIM_UNITS_MODE
Used for storing the units selection in the file because EDA_UNITS alone doesn't cut it.
Definition: dimension.h:57
Handle the component boundary box.
Definition: eda_rect.h:42
virtual bool TextHitTest(const wxPoint &aPoint, int aAccuracy=0) const
Test if aPoint is within the bounds of this object.
Definition: eda_text.cpp:376
virtual void SwapData(BOARD_ITEM *aImage) override
Swap data between aItem and aImage.
Definition: dimension.cpp:518
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.
Definition: dimension.cpp:674
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: dimension.cpp:1008
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:68
int GetY() const
Definition: eda_rect.h:104
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:149
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: dimension.cpp:1045
bool Intersects(const EDA_RECT &aRect) const
Test for a common area between rectangles.
Definition: eda_rect.cpp:150
wxString m_valueString
Displayed value when m_overrideValue = true.
Definition: dimension.h:279
bool HitTest(const wxPoint &aPosition, int aAccuracy) const override
Test if aPosition is contained within or on the bounding box of an item.
Definition: dimension.cpp:367
PCB_LAYER_ID m_layer
Definition: board_item.h:363
DIM_TEXT_POSITION
Where to place the text on a dimension.
Definition: dimension.h:47
const wxPoint & GetTextPos() const
Definition: eda_text.h:254
int m_lineThickness
Thickness used for all graphics in the dimension.
Definition: dimension.h:289
Provide class metadata.Helper macro to map type hashes to names.
Definition: property_mgr.h:63
ORTHOGONAL_DIMENSION(BOARD_ITEM *aParent)
Definition: dimension.cpp:683
DIMENSION_BASE(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIMENSION_T)
Definition: dimension.cpp:41
class ORTHOGONAL_DIMENSION, a linear dimension constrained to x/y
Definition: typeinfo.h:103
void Mirror(const wxPoint &axis_pos, bool aMirrorLeftRight=false)
Mirror the Dimension , relative to a given horizontal axis the text is not mirrored.
Definition: dimension.cpp:261
DIM_UNITS_FORMAT m_unitsFormat
How to render the units suffix.
Definition: dimension.h:284
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293
DIM_UNITS_FORMAT
How to display the units in a dimension's text.
Definition: dimension.h:39
virtual void updateText()
Updates the text field value from the current geometry (called by updateGeometry normally)
Definition: dimension.cpp:68
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: dimension.cpp:512
void updateGeometry() override
Updates the cached geometry of the dimension after changing any of its properties.
Definition: dimension.cpp:551
const Vec & GetOrigin() const
Definition: box2.h:193
const wxPoint GetCenter() const
Definition: eda_rect.h:109
For better understanding of the points that make a dimension:
Definition: dimension.h:334
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: eda_item.cpp:206
BITMAP_DEF GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: dimension.cpp:712
wxPoint m_crossBarEnd
Crossbar end control point.
Definition: dimension.h:342
Abstract dimension API.
Definition: dimension.h:95
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
Definition: board_item.cpp:60
static constexpr int Millimeter2iu(double mm)
DIM_TEXT_POSITION m_textPosition
How to position the text.
Definition: dimension.h:292
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.
Definition: dimension.cpp:294
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173
virtual const wxPoint & GetEnd() const
Definition: dimension.h:124
wxPoint m_crossBarStart
Crossbar start control point.
Definition: dimension.h:341
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
void SetUnitsMode(DIM_UNITS_MODE aMode)
Definition: dimension.cpp:174
EDA_UNITS GetUserUnits() const
Return the user units currently in use.
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363
wxString GetValueText() const
Definition: dimension.cpp:103
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...
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
DIR m_orientation
What axis to lock the dimension line to.
Definition: dimension.h:425
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
wxPoint m_end
Internal cache of drawn shapes.
Definition: dimension.h:299
VECTOR2I B
Definition: seg.h:50