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