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, [email protected]
5  * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6  * Copyright (C) 2012 Wayne Stambaugh <[email protected]>
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>
32 #include <pcb_dimension.h>
33 #include <pcb_text.h>
35 #include <geometry/shape_circle.h>
36 #include <geometry/shape_segment.h>
39 #include <trigo.h>
40 #include <i18n_utility.h>
41 
42 
44  BOARD_ITEM( aParent, aType ),
45  m_overrideTextEnabled( false ),
46  m_units( EDA_UNITS::INCHES ),
47  m_autoUnits( false ),
48  m_unitsFormat( DIM_UNITS_FORMAT::BARE_SUFFIX ),
49  m_precision( 4 ),
50  m_suppressZeroes( false ),
51  m_lineThickness( Millimeter2iu( 0.2 ) ),
52  m_arrowLength( Mils2iu( 50 ) ),
53  m_extensionOffset( 0 ),
54  m_textPosition( DIM_TEXT_POSITION::OUTSIDE ),
55  m_keepTextAligned( true ),
56  m_text( aParent ),
57  m_measuredValue( 0 )
58 {
60 }
61 
62 
64 {
65  BOARD_ITEM::SetParent( aParent );
66  m_text.SetParent( aParent );
67 }
68 
69 
71 {
73 
74  switch( m_unitsFormat )
75  {
76  case DIM_UNITS_FORMAT::NO_SUFFIX: // no units
77  break;
78 
79  case DIM_UNITS_FORMAT::BARE_SUFFIX: // normal
80  text += wxS( " " );
82  break;
83 
84  case DIM_UNITS_FORMAT::PAREN_SUFFIX: // parenthetical
85  text += wxT( " (" );
87  text += wxT( ")" );
88  break;
89  }
90 
91  text.Prepend( m_prefix );
92  text.Append( m_suffix );
93 
94  m_text.SetText( text );
95 }
96 
97 
98 template<typename ShapeType>
99 void PCB_DIMENSION_BASE::addShape( const ShapeType& aShape )
100 {
101  m_shapes.push_back( std::make_shared<ShapeType>( aShape ) );
102 }
103 
104 
106 {
107  struct lconv* lc = localeconv();
108  wxChar sep = lc->decimal_point[0];
109 
110  int val = GetMeasuredValue();
111  wxString text;
112  wxString format = wxT( "%." ) + wxString::Format( wxT( "%i" ), m_precision ) + wxT( "f" );
113 
114  text.Printf( format, To_User_Unit( m_units, val ) );
115 
116  if( m_suppressZeroes )
117  {
118  while( text.Last() == '0' )
119  {
120  text.RemoveLast();
121 
122  if( text.Last() == '.' || text.Last() == sep )
123  {
124  text.RemoveLast();
125  break;
126  }
127  }
128  }
129 
130  return text;
131 }
132 
133 
134 void PCB_DIMENSION_BASE::SetPrefix( const wxString& aPrefix )
135 {
136  m_prefix = aPrefix;
137 }
138 
139 
140 void PCB_DIMENSION_BASE::SetSuffix( const wxString& aSuffix )
141 {
142  m_suffix = aSuffix;
143 }
144 
145 
147 {
148  m_units = aUnits;
149 }
150 
151 
153 {
154  if( m_autoUnits )
155  {
157  }
158  else
159  {
160  switch( m_units )
161  {
164 
165  case EDA_UNITS::MILS:
166  return DIM_UNITS_MODE::MILS;
167 
168  default:
169  case EDA_UNITS::INCHES:
170  return DIM_UNITS_MODE::INCHES;
171  }
172  }
173 }
174 
175 
177 {
178  m_autoUnits = false;
179 
180  switch( aMode )
181  {
184  break;
185 
188  break;
189 
192  break;
193 
195  m_autoUnits = true;
196  break;
197  }
198 }
199 
200 
201 void PCB_DIMENSION_BASE::SetText( const wxString& aNewText )
202 {
203  m_valueString = aNewText;
204  updateText();
205 }
206 
207 
208 const wxString PCB_DIMENSION_BASE::GetText() const
209 {
210  return m_text.GetText();
211 }
212 
213 
215 {
216  m_layer = aLayer;
217  m_text.SetLayer( aLayer );
218 }
219 
220 
221 void PCB_DIMENSION_BASE::Move( const wxPoint& offset )
222 {
223  m_text.Offset( offset );
224 
225  m_start += offset;
226  m_end += offset;
227 
228  Update();
229 }
230 
231 
232 void PCB_DIMENSION_BASE::Rotate( const wxPoint& aRotCentre, double aAngle )
233 {
234  double newAngle = m_text.GetTextAngle() + aAngle;
235 
236  if( newAngle >= 3600 )
237  newAngle -= 3600;
238 
239  m_text.SetTextAngle( newAngle );
240 
241  wxPoint pt = m_text.GetTextPos();
242  RotatePoint( &pt, aRotCentre, aAngle );
243  m_text.SetTextPos( pt );
244 
245  RotatePoint( &m_start, aRotCentre, aAngle );
246  RotatePoint( &m_end, aRotCentre, aAngle );
247 
248  Update();
249 }
250 
251 
252 void PCB_DIMENSION_BASE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
253 {
254  Mirror( aCentre );
255 
256  SetLayer( FlipLayer( GetLayer(), GetBoard()->GetCopperLayerCount() ) );
257 }
258 
259 
260 void PCB_DIMENSION_BASE::Mirror( const wxPoint& axis_pos, bool aMirrorLeftRight )
261 {
262  int axis = aMirrorLeftRight ? axis_pos.x : axis_pos.y;
263  wxPoint newPos = m_text.GetTextPos();
264 
265 #define INVERT( pos ) ( ( pos ) = axis - ( ( pos ) - axis ) )
266  if( aMirrorLeftRight )
267  INVERT( newPos.x );
268  else
269  INVERT( newPos.y );
270 
271  m_text.SetTextPos( newPos );
272 
273  // invert angle
275 
276  if( aMirrorLeftRight )
277  {
278  INVERT( m_start.x );
279  INVERT( m_end.x );
280  }
281  else
282  {
283  INVERT( m_start.y );
284  INVERT( m_end.y );
285  }
286 
288 
289  Update();
290 }
291 
292 
294  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 != nullptr, 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 = wxT( "%" ) + wxString::Format( wxT( "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( wxT( "@(%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( wxT( "@(%s, %s)" ),
340  MessageTextFromValue( units, startCoord.x ),
341  MessageTextFromValue( units, startCoord.y ) );
342  wxPoint endCoord = originTransforms.ToDisplayAbs( GetEnd() );
343  wxString end = wxString::Format( wxT( "@(%s, %s)" ),
344  MessageTextFromValue( units, endCoord.x ),
345  MessageTextFromValue( units, endCoord.y ) );
346 
347  aList.emplace_back( start, end );
348  }
349 
350  if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
351  aList.emplace_back( _( "Status" ), _( "Locked" ) );
352 
353  aList.emplace_back( _( "Layer" ), GetLayerName() );
354 }
355 
356 
357 std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
358 {
359  std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();
360 
361  effectiveShape->AddShape( Text().GetEffectiveTextShape()->Clone() );
362 
363  for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
364  effectiveShape->AddShape( shape->Clone() );
365 
366  return effectiveShape;
367 }
368 
369 
370 bool PCB_DIMENSION_BASE::HitTest( const wxPoint& aPosition, int aAccuracy ) const
371 {
372  if( m_text.TextHitTest( aPosition ) )
373  return true;
374 
375  int dist_max = aAccuracy + ( m_lineThickness / 2 );
376 
377  // Locate SEGMENTS
378 
379  for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
380  {
381  if( shape->Collide( aPosition, dist_max ) )
382  return true;
383  }
384 
385  return false;
386 }
387 
388 
389 bool PCB_DIMENSION_BASE::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const
390 {
391  EDA_RECT arect = aRect;
392  arect.Inflate( aAccuracy );
393 
394  EDA_RECT rect = GetBoundingBox();
395 
396  if( aAccuracy )
397  rect.Inflate( aAccuracy );
398 
399  if( aContained )
400  return arect.Contains( rect );
401 
402  return arect.Intersects( rect );
403 }
404 
405 
407 {
408  EDA_RECT bBox;
409  int xmin, xmax, ymin, ymax;
410 
411  bBox = m_text.GetTextBox();
412  xmin = bBox.GetX();
413  xmax = bBox.GetRight();
414  ymin = bBox.GetY();
415  ymax = bBox.GetBottom();
416 
417  for( const std::shared_ptr<SHAPE>& shape : GetShapes() )
418  {
419  BOX2I shapeBox = shape->BBox();
420  shapeBox.Inflate( m_lineThickness / 2 );
421 
422  xmin = std::min( xmin, shapeBox.GetOrigin().x );
423  xmax = std::max( xmax, shapeBox.GetEnd().x );
424  ymin = std::min( ymin, shapeBox.GetOrigin().y );
425  ymax = std::max( ymax, shapeBox.GetEnd().y );
426  }
427 
428  bBox.SetX( xmin );
429  bBox.SetY( ymin );
430  bBox.SetWidth( xmax - xmin + 1 );
431  bBox.SetHeight( ymax - ymin + 1 );
432 
433  bBox.Normalize();
434 
435  return bBox;
436 }
437 
438 
440 {
441  return wxString::Format( _( "Dimension '%s' on %s" ), GetText(), GetLayerName() );
442 }
443 
444 
445 
447 {
448  BOX2I dimBBox = BOX2I( VECTOR2I( GetBoundingBox().GetPosition() ),
449  VECTOR2I( GetBoundingBox().GetSize() ) );
450  dimBBox.Merge( m_text.ViewBBox() );
451 
452  return dimBBox;
453 }
454 
455 
457  bool aStart )
458 {
459  VECTOR2I start( aStart ? aSeg.A : aSeg.B );
460  VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
461 
462  if( aPoly.Contains( start ) )
463  return NULLOPT;
464 
465  for( SHAPE_POLY_SET::CONST_SEGMENT_ITERATOR seg = aPoly.CIterateSegments(); seg; ++seg )
466  {
467  if( OPT_VECTOR2I intersection = ( *seg ).Intersect( aSeg ) )
468  {
469  if( ( *intersection - start ).SquaredEuclideanNorm() <
470  ( endpoint - start ).SquaredEuclideanNorm() )
471  endpoint = *intersection;
472  }
473  }
474 
475  if( start == endpoint )
476  return NULLOPT;
477 
478  return OPT_VECTOR2I( endpoint );
479 }
480 
481 
483 {
484  VECTOR2I start( aStart ? aSeg.A : aSeg.B );
485  VECTOR2I endpoint( aStart ? aSeg.B : aSeg.A );
486 
487  if( aCircle.Contains( start ) )
488  return NULLOPT;
489 
490  std::vector<VECTOR2I> intersections = aCircle.Intersect( aSeg );
491 
492  for( VECTOR2I& intersection : aCircle.Intersect( aSeg ) )
493  {
494  if( ( intersection - start ).SquaredEuclideanNorm() <
495  ( endpoint - start ).SquaredEuclideanNorm() )
496  endpoint = intersection;
497  }
498 
499  if( start == endpoint )
500  return NULLOPT;
501 
502  return OPT_VECTOR2I( endpoint );
503 }
504 
505 
507  PCB_LAYER_ID aLayer, int aClearance,
508  int aError, ERROR_LOC aErrorLoc,
509  bool aIgnoreLineWidth ) const
510 {
511  wxASSERT_MSG( !aIgnoreLineWidth, wxT( "IgnoreLineWidth has no meaning for dimensions." ) );
512 
513  for( const std::shared_ptr<SHAPE>& shape : m_shapes )
514  {
515  const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
516  const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
517 
518  if( circle )
519  {
520  TransformCircleToPolygon( aCornerBuffer, (wxPoint) circle->GetCenter(),
521  circle->GetRadius() + m_lineThickness / 2 + aClearance,
522  aError, aErrorLoc );
523  }
524  else if( seg )
525  {
526  TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A,
527  (wxPoint) seg->GetSeg().B, m_lineThickness + 2 * aClearance,
528  aError, aErrorLoc );
529  }
530  else
531  {
532  wxFAIL_MSG( wxT( "PCB_DIMENSION_BASE::TransformShapeWithClearanceToPolygon unexpected "
533  "shape type." ) );
534  }
535  }
536 }
537 
538 
540  PCB_DIMENSION_BASE( aParent, aType ),
541  m_height( 0 )
542 {
543  // To preserve look of old dimensions, initialize extension height based on default arrow length
544  m_extensionHeight = static_cast<int>( m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) ) );
545 }
546 
547 
549 {
550  return new PCB_DIM_ALIGNED( *this );
551 }
552 
553 
555 {
556  assert( aImage->Type() == PCB_DIM_ALIGNED_T );
557 
558  m_shapes.clear();
559  static_cast<PCB_DIM_ALIGNED*>( aImage )->m_shapes.clear();
560 
561  std::swap( *static_cast<PCB_DIM_ALIGNED*>( this ), *static_cast<PCB_DIM_ALIGNED*>( aImage ) );
562 
563  Update();
564 }
565 
566 
568 {
570 }
571 
572 
573 void PCB_DIM_ALIGNED::UpdateHeight( const wxPoint& aCrossbarStart, const wxPoint& aCrossbarEnd )
574 {
575  VECTOR2D height( aCrossbarStart - GetStart() );
576  VECTOR2D crossBar( aCrossbarEnd - aCrossbarStart );
577 
578  if( height.Cross( crossBar ) > 0 )
579  m_height = -height.EuclideanNorm();
580  else
581  m_height = height.EuclideanNorm();
582 
583  Update();
584 }
585 
586 
588 {
589  m_shapes.clear();
590 
591  VECTOR2I dimension( m_end - m_start );
592 
593  m_measuredValue = KiROUND( dimension.EuclideanNorm() );
594 
595  VECTOR2I extension;
596 
597  if( m_height > 0 )
598  extension = VECTOR2I( -dimension.y, dimension.x );
599  else
600  extension = VECTOR2I( dimension.y, -dimension.x );
601 
602  // Add extension lines
603  int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
604 
605  VECTOR2I extStart( m_start );
606  extStart += extension.Resize( m_extensionOffset );
607 
608  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
609 
610  extStart = VECTOR2I( m_end );
611  extStart += extension.Resize( m_extensionOffset );
612 
613  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
614 
615  // Add crossbar
616  VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
617  m_crossBarStart = m_start + wxPoint( crossBarDistance );
618  m_crossBarEnd = m_end + wxPoint( crossBarDistance );
619 
620  // Update text after calculating crossbar position but before adding crossbar lines
621  updateText();
622 
623  // Now that we have the text updated, we can determine how to draw the crossbar.
624  // First we need to create an appropriate bounding polygon to collide with
625  EDA_RECT textBox = m_text.GetTextBox().Inflate( m_text.GetTextWidth() / 2, 0 );
626 
627  SHAPE_POLY_SET polyBox;
628  polyBox.NewOutline();
629  polyBox.Append( textBox.GetOrigin() );
630  polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
631  polyBox.Append( textBox.GetEnd() );
632  polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
633  polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
634 
635  // The ideal crossbar, if the text doesn't collide
636  SEG crossbar( m_crossBarStart, m_crossBarEnd );
637 
638  // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
639  bool containsA = polyBox.Contains( crossbar.A );
640  bool containsB = polyBox.Contains( crossbar.B );
641 
642  OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
643  OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
644 
645  if( endpointA )
646  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
647 
648  if( endpointB )
649  m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
650 
651  if( !containsA && !containsB && !endpointA && !endpointB )
652  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
653 
654  // Add arrows
655  VECTOR2I arrowEnd( m_arrowLength, 0 );
656 
657  double arrowRotPos = dimension.Angle() + DEG2RAD( s_arrowAngle );
658  double arrowRotNeg = dimension.Angle() - DEG2RAD( s_arrowAngle );
659 
660  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
661  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
662 
663  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
664  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
665 
666  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
667  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
668 
669  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
670  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
671 }
672 
673 
675 {
676  VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
677 
679  {
680  int textOffsetDistance = m_text.GetEffectiveTextPenWidth() + m_text.GetTextHeight();
681 
682  double rotation;
683  if( crossbarCenter.x == 0 )
684  rotation = sign( crossbarCenter.y ) * DEG2RAD( 90 );
685  else
686  rotation = -std::copysign( DEG2RAD( 90 ), crossbarCenter.x );
687 
688  VECTOR2I textOffset = crossbarCenter.Rotate( rotation ).Resize( textOffsetDistance );
689  textOffset += crossbarCenter;
690 
691  m_text.SetTextPos( m_crossBarStart + wxPoint( textOffset ) );
692  }
694  {
695  m_text.SetTextPos( m_crossBarStart + wxPoint( crossbarCenter ) );
696  }
697 
698  if( m_keepTextAligned )
699  {
700  double textAngle = 3600 - RAD2DECIDEG( crossbarCenter.Angle() );
701 
702  NORMALIZE_ANGLE_POS( textAngle );
703 
704  if( textAngle > 900 && textAngle <= 2700 )
705  textAngle -= 1800;
706 
707  m_text.SetTextAngle( textAngle );
708  }
709 
711 }
712 
713 
714 void PCB_DIM_ALIGNED::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
715 {
716  PCB_DIMENSION_BASE::GetMsgPanelInfo( aFrame, aList );
717 
718  aList.emplace_back( _( "Height" ), MessageTextFromValue( aFrame->GetUserUnits(), m_height ) );
719 }
720 
721 
724 {
725  // To preserve look of old dimensions, initialize extension height based on default arrow length
726  m_extensionHeight = static_cast<int>( m_arrowLength * std::sin( DEG2RAD( s_arrowAngle ) ) );
728 }
729 
730 
732 {
733  return new PCB_DIM_ORTHOGONAL( *this );
734 }
735 
736 
738 {
739  assert( aImage->Type() == PCB_DIM_ORTHOGONAL_T );
740 
741  m_shapes.clear();
742  static_cast<PCB_DIM_ORTHOGONAL*>( aImage )->m_shapes.clear();
743 
744  std::swap( *static_cast<PCB_DIM_ORTHOGONAL*>( this ),
745  *static_cast<PCB_DIM_ORTHOGONAL*>( aImage ) );
746 
747  Update();
748 }
749 
750 
752 {
754 }
755 
756 
758 {
759  m_shapes.clear();
760 
762  m_end.y - m_start.y );
763  m_measuredValue = KiROUND( std::abs( measurement ) );
764 
765  VECTOR2I extension;
766 
768  extension = VECTOR2I( 0, m_height );
769  else
770  extension = VECTOR2I( m_height, 0 );
771 
772  // Add first extension line
773  int extensionHeight = std::abs( m_height ) - m_extensionOffset + m_extensionHeight;
774 
775  VECTOR2I extStart( m_start );
776  extStart += extension.Resize( m_extensionOffset );
777 
778  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
779 
780  // Add crossbar
781  VECTOR2I crossBarDistance = sign( m_height ) * extension.Resize( m_height );
782  m_crossBarStart = m_start + wxPoint( crossBarDistance );
783 
785  m_crossBarEnd = wxPoint( m_end.x, m_crossBarStart.y );
786  else
787  m_crossBarEnd = wxPoint( m_crossBarStart.x, m_end.y );
788 
789  // Add second extension line (m_end to crossbar end)
791  extension = VECTOR2I( 0, m_end.y - m_crossBarEnd.y );
792  else
793  extension = VECTOR2I( m_end.x - m_crossBarEnd.x, 0 );
794 
795  extensionHeight = extension.EuclideanNorm() - m_extensionOffset + m_extensionHeight;
796 
797  extStart = VECTOR2I( m_crossBarEnd );
798  extStart -= extension.Resize( m_extensionHeight );
799 
800  addShape( SHAPE_SEGMENT( extStart, extStart + extension.Resize( extensionHeight ) ) );
801 
802  // Update text after calculating crossbar position but before adding crossbar lines
803  updateText();
804 
805  // Now that we have the text updated, we can determine how to draw the crossbar.
806  // First we need to create an appropriate bounding polygon to collide with
807  EDA_RECT textBox = m_text.GetTextBox().Inflate( m_text.GetTextWidth() / 2, 0 );
808 
809  SHAPE_POLY_SET polyBox;
810  polyBox.NewOutline();
811  polyBox.Append( textBox.GetOrigin() );
812  polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
813  polyBox.Append( textBox.GetEnd() );
814  polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
815  polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
816 
817  // The ideal crossbar, if the text doesn't collide
818  SEG crossbar( m_crossBarStart, m_crossBarEnd );
819 
820  // Now we can draw 0, 1, or 2 crossbar lines depending on how the polygon collides
821  bool containsA = polyBox.Contains( crossbar.A );
822  bool containsB = polyBox.Contains( crossbar.B );
823 
824  OPT_VECTOR2I endpointA = segPolyIntersection( polyBox, crossbar );
825  OPT_VECTOR2I endpointB = segPolyIntersection( polyBox, crossbar, false );
826 
827  if( endpointA )
828  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar.A, *endpointA ) );
829 
830  if( endpointB )
831  m_shapes.emplace_back( new SHAPE_SEGMENT( *endpointB, crossbar.B ) );
832 
833  if( !containsA && !containsB && !endpointA && !endpointB )
834  m_shapes.emplace_back( new SHAPE_SEGMENT( crossbar ) );
835 
836  // Add arrows
837  VECTOR2I crossBarAngle( m_crossBarEnd - m_crossBarStart );
838  VECTOR2I arrowEnd( m_arrowLength, 0 );
839 
840  double arrowRotPos = crossBarAngle.Angle() + DEG2RAD( s_arrowAngle );
841  double arrowRotNeg = crossBarAngle.Angle() - DEG2RAD( s_arrowAngle );
842 
843  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
844  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
845 
846  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarStart,
847  m_crossBarStart + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
848 
849  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
850  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
851 
852  m_shapes.emplace_back( new SHAPE_SEGMENT( m_crossBarEnd,
853  m_crossBarEnd - wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
854 }
855 
856 
858 {
859  VECTOR2I crossbarCenter( ( m_crossBarEnd - m_crossBarStart ) / 2 );
860 
862  {
863  int textOffsetDistance = m_text.GetEffectiveTextPenWidth() + m_text.GetTextHeight();
864 
865  VECTOR2I textOffset;
866 
868  textOffset.y = -textOffsetDistance;
869  else
870  textOffset.x = -textOffsetDistance;
871 
872  textOffset += crossbarCenter;
873 
874  m_text.SetTextPos( m_crossBarStart + wxPoint( textOffset ) );
875  }
877  {
878  m_text.SetTextPos( m_crossBarStart + wxPoint( crossbarCenter ) );
879  }
880 
881  if( m_keepTextAligned )
882  {
883  double textAngle;
884 
885  if( abs( crossbarCenter.x ) > abs( crossbarCenter.y ) )
886  textAngle = 0;
887  else
888  textAngle = 900;
889 
890  m_text.SetTextAngle( textAngle );
891  }
892 
894 }
895 
896 
897 void PCB_DIM_ORTHOGONAL::Rotate( const wxPoint& aRotCentre, double aAngle )
898 {
899  // restrict angle to -179.9 to 180.0 degrees
900  if( aAngle > 1800 )
901  {
902  aAngle -= 3600;
903  }
904  else if( aAngle <= -1800 )
905  {
906  aAngle += 3600;
907  }
908 
909  // adjust orientation and height to new angle
910  // we can only handle the cases of -90, 0, 90, 180 degrees exactly;
911  // in the other cases we will use the nearest 90 degree angle to
912  // choose at least an approximate axis for the target orientation
913  // In case of exactly 45 or 135 degrees, we will round towards zero for consistency
914  if( aAngle > 450 && aAngle <= 1350 )
915  {
916  // about 90 degree
918  {
920  }
921  else
922  {
924  m_height = -m_height;
925  }
926  }
927  else if( aAngle < -450 && aAngle >= -1350 )
928  {
929  // about -90 degree
931  {
933  m_height = -m_height;
934  }
935  else
936  {
938  }
939  }
940  else if( aAngle > 1350 || aAngle < -1350 )
941  {
942  // about 180 degree
943  m_height = -m_height;
944  }
945 
946  // this will update m_crossBarStart and m_crossbarEnd
947  PCB_DIMENSION_BASE::Rotate( aRotCentre, aAngle );
948 }
949 
950 
953  m_textFrame( DIM_TEXT_FRAME::NONE )
954 {
956  m_overrideTextEnabled = true;
957  m_keepTextAligned = false;
958 }
959 
960 
962 {
963  return new PCB_DIM_LEADER( *this );
964 }
965 
966 
968 {
969  assert( aImage->Type() == PCB_DIM_LEADER_T );
970 
971  std::swap( *static_cast<PCB_DIM_LEADER*>( this ), *static_cast<PCB_DIM_LEADER*>( aImage ) );
972 }
973 
974 
976 {
977  return BITMAPS::add_leader;
978 }
979 
980 
982 {
983  m_shapes.clear();
984 
985  updateText();
986 
987  // Now that we have the text updated, we can determine how to draw the second line
988  // First we need to create an appropriate bounding polygon to collide with
989  EDA_RECT textBox = m_text.GetTextBox().Inflate( m_text.GetTextWidth() / 2, 0 );
990 
991  SHAPE_POLY_SET polyBox;
992  polyBox.NewOutline();
993  polyBox.Append( textBox.GetOrigin() );
994  polyBox.Append( textBox.GetOrigin().x, textBox.GetEnd().y );
995  polyBox.Append( textBox.GetEnd() );
996  polyBox.Append( textBox.GetEnd().x, textBox.GetOrigin().y );
997  polyBox.Rotate( -m_text.GetTextAngleRadians(), textBox.GetCenter() );
998 
999  VECTOR2I firstLine( m_end - m_start );
1000  VECTOR2I start( m_start );
1001  start += firstLine.Resize( m_extensionOffset );
1002 
1003  SEG arrowSeg( m_start, m_end );
1004  SEG textSeg( m_end, m_text.GetPosition() );
1005  OPT_VECTOR2I arrowSegEnd = boost::make_optional( false, VECTOR2I() );;
1006  OPT_VECTOR2I textSegEnd = boost::make_optional( false, VECTOR2I() );
1007 
1009  {
1010  double penWidth = m_text.GetEffectiveTextPenWidth() / 2.0;
1011  double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1012  CIRCLE circle( textBox.GetCenter(), radius );
1013 
1014  arrowSegEnd = segCircleIntersection( circle, arrowSeg );
1015  textSegEnd = segCircleIntersection( circle, textSeg );
1016  }
1017  else
1018  {
1019  arrowSegEnd = segPolyIntersection( polyBox, arrowSeg );
1020  textSegEnd = segPolyIntersection( polyBox, textSeg );
1021  }
1022 
1023  if( !arrowSegEnd )
1024  arrowSegEnd = m_end;
1025 
1026  m_shapes.emplace_back( new SHAPE_SEGMENT( start, *arrowSegEnd ) );
1027 
1028  // Add arrows
1029  VECTOR2I arrowEnd( m_arrowLength, 0 );
1030 
1031  double arrowRotPos = firstLine.Angle() + DEG2RAD( s_arrowAngle );
1032  double arrowRotNeg = firstLine.Angle() - DEG2RAD( s_arrowAngle );
1033 
1034  m_shapes.emplace_back( new SHAPE_SEGMENT( start,
1035  start + wxPoint( arrowEnd.Rotate( arrowRotPos ) ) ) );
1036  m_shapes.emplace_back( new SHAPE_SEGMENT( start,
1037  start + wxPoint( arrowEnd.Rotate( arrowRotNeg ) ) ) );
1038 
1039 
1040  if( !GetText().IsEmpty() )
1041  {
1042  switch( m_textFrame )
1043  {
1045  {
1046  for( SHAPE_POLY_SET::SEGMENT_ITERATOR seg = polyBox.IterateSegments(); seg; seg++ )
1047  m_shapes.emplace_back( new SHAPE_SEGMENT( *seg ) );
1048 
1049  break;
1050  }
1051 
1053  {
1054  double penWidth = m_text.GetEffectiveTextPenWidth() / 2.0;
1055  double radius = ( textBox.GetWidth() / 2.0 ) - penWidth;
1056  m_shapes.emplace_back( new SHAPE_CIRCLE( textBox.GetCenter(), radius ) );
1057 
1058  break;
1059  }
1060 
1061  default:
1062  break;
1063  }
1064  }
1065 
1066  if( textSegEnd && *arrowSegEnd == m_end )
1067  m_shapes.emplace_back( new SHAPE_SEGMENT( m_end, *textSegEnd ) );
1068 }
1069 
1070 
1071 void PCB_DIM_LEADER::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1072 {
1073  wxString msg;
1074 
1075  aList.emplace_back( _( "Leader" ), m_text.GetShownText() );
1076 
1077  ORIGIN_TRANSFORMS originTransforms = aFrame->GetOriginTransforms();
1078  EDA_UNITS units = aFrame->GetUserUnits();
1079 
1080  wxPoint startCoord = originTransforms.ToDisplayAbs( GetStart() );
1081  wxString start = wxString::Format( wxT( "@(%s, %s)" ),
1082  MessageTextFromValue( units, startCoord.x ),
1083  MessageTextFromValue( units, startCoord.y ) );
1084 
1085  aList.emplace_back( start, wxEmptyString );
1086 
1087  aList.emplace_back( _( "Layer" ), GetLayerName() );
1088 }
1089 
1090 
1093 {
1095  m_overrideTextEnabled = true;
1096 }
1097 
1098 
1100 {
1101  return new PCB_DIM_CENTER( *this );
1102 }
1103 
1104 
1106 {
1107  assert( aImage->Type() == PCB_DIM_CENTER_T );
1108 
1109  std::swap( *static_cast<PCB_DIM_CENTER*>( this ), *static_cast<PCB_DIM_CENTER*>( aImage ) );
1110 }
1111 
1112 
1114 {
1116 }
1117 
1118 
1120 {
1121  int halfWidth = VECTOR2I( m_end - m_start ).x + ( m_lineThickness / 2.0 );
1122 
1123  EDA_RECT bBox;
1124 
1125  bBox.SetX( m_start.x - halfWidth );
1126  bBox.SetY( m_start.y - halfWidth );
1127  bBox.SetWidth( halfWidth * 2 );
1128  bBox.SetHeight( halfWidth * 2 );
1129 
1130  bBox.Normalize();
1131 
1132  return bBox;
1133 }
1134 
1135 
1137 {
1138  return BOX2I( VECTOR2I( GetBoundingBox().GetPosition() ),
1139  VECTOR2I( GetBoundingBox().GetSize() ) );
1140 }
1141 
1142 
1144 {
1145  m_shapes.clear();
1146 
1147  VECTOR2I center( m_start );
1148  VECTOR2I arm( m_end - m_start );
1149 
1150  m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1151 
1152  arm = arm.Rotate( DEG2RAD( 90 ) );
1153 
1154  m_shapes.emplace_back( new SHAPE_SEGMENT( center - arm, center + arm ) );
1155 }
1156 
1157 
1158 static struct DIMENSION_DESC
1159 {
1161  {
1165  // TODO: add dimension properties:
1166  //propMgr.AddProperty( new PROPERTY<DIMENSION, int>( _HKI( "Height" ),
1167  //&DIMENSION::SetHeight, &DIMENSION::GetHeight, PROPERTY_DISPLAY::DISTANCE ) );
1168  }
1169 } _DIMENSION_DESC;
1170 
1171 
void SetMirrored(bool isMirrored)
Definition: eda_text.h:209
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)
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
int sign(T val)
Definition: util.h:104
void Offset(const wxPoint &aOffset)
Definition: eda_text.h:273
void SetUnits(EDA_UNITS aUnits)
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:478
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:210
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.
int GetRadius() const
Definition: shape_circle.h:107
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:164
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:49
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:107
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:530
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:239
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:267
int GetWidth() const
Definition: eda_rect.h:118
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:195
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
const VECTOR2I GetCenter() const
Definition: shape_circle.h:112
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:622
void updateText() override
Update the text field value from the current geometry (called by updateGeometry normally).
virtual bool IsLocked() const
Definition: board_item.cpp:64
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:115
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:159
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
int GetBottom() const
Definition: eda_rect.h:123
int GetTextHeight() const
Definition: eda_text.h:265
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:112
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:124
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:185
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:110
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)
int GetRight() const
Definition: eda_rect.h:120
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aCornerBuffer, const wxPoint &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
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:167
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:179
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.
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition: layer_ids.h:153
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
void SetY(int val)
Definition: eda_rect.h:173
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:198
void Normalize()
Ensures that the height ant width are positive.
Definition: eda_rect.cpp:35
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth) const override
Convert the item shape to a closed polygon.
void UpdateHeight(const wxPoint &aCrossbarStart, const wxPoint &aCrossbarEnd)
Update the stored height basing on points coordinates.
No updates are required.
Definition: view_item.h:46
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:262
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:65
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
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aStart, const wxPoint &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
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:108
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
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:313
DIM_TEXT_FRAME m_textFrame
const wxPoint & GetTextPos() const
Definition: eda_text.h:268
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:36
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.
#define PCB_EDIT_FRAME_NAME
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:113
PCB_DIM_ALIGNED(BOARD_ITEM *aParent, KICAD_T aType=PCB_DIM_ALIGNED_T)
void SetUnitsMode(DIM_UNITS_MODE aMode)
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: eda_item.cpp:257
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:75
static constexpr int Millimeter2iu(double mm)
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:143
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:154
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 inside or on the boundary of this 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:112
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.