KiCad PCB EDA Suite
board_items_to_polygon_shape_transform.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) 2009-2021 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <vector>
26 #include <bezier_curves.h>
27 #include <board_design_settings.h>
28 #include <trigo.h>
29 #include <board.h>
30 #include <pad.h>
31 #include <pcb_dimension.h>
32 #include <pcb_track.h>
33 #include <kicad_string.h>
34 #include <pcb_shape.h>
35 #include <pcb_text.h>
36 #include <zone.h>
37 #include <footprint.h>
38 #include <fp_shape.h>
41 #include <geometry/shape_segment.h>
42 #include <geometry/shape_circle.h>
43 #include <geometry/shape_rect.h>
45 
46 
47 // A helper struct for the callback function
48 // These variables are parameters used in addTextSegmToPoly.
49 // But addTextSegmToPoly is a call-back function,
50 // so we cannot send them as arguments.
52 {
54  int m_error;
56 };
57 
58 
60 
61 
62 // This is a call back function, used by GRText to draw the 3D text shape:
63 static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData )
64 {
65  TSEGM_2_POLY_PRMS* prm = static_cast<TSEGM_2_POLY_PRMS*>( aData );
66  TransformOvalToPolygon( *prm->m_cornerBuffer, wxPoint( x0, y0 ), wxPoint( xf, yf ),
67  prm->m_textWidth, prm->m_error, ERROR_INSIDE );
68 }
69 
70 
72  SHAPE_POLY_SET& aOutlines ) const
73 {
74  int maxError = GetDesignSettings().m_MaxError;
75 
76  // convert tracks and vias:
77  for( const PCB_TRACK* track : m_tracks )
78  {
79  if( !track->IsOnLayer( aLayer ) )
80  continue;
81 
82  track->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
83  ERROR_INSIDE );
84  }
85 
86  // convert pads and other copper items in footprints
87  for( const FOOTPRINT* footprint : m_footprints )
88  {
89  footprint->TransformPadsWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
90  ERROR_INSIDE );
91 
92  // Micro-wave footprints may have items on copper layers
93  footprint->TransformFPShapesWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
95  true, /* include text */
96  true /* include shapes */ );
97 
98  for( const ZONE* zone : footprint->Zones() )
99  {
100  if( zone->GetLayerSet().test( aLayer ) )
101  zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
102  }
103  }
104 
105  // convert copper zones
106  for( const ZONE* zone : Zones() )
107  {
108  if( zone->GetLayerSet().test( aLayer ) )
109  zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
110  }
111 
112  // convert graphic items on copper layers (texts)
113  for( const BOARD_ITEM* item : m_drawings )
114  {
115  if( !item->IsOnLayer( aLayer ) )
116  continue;
117 
118  switch( item->Type() )
119  {
120  case PCB_SHAPE_T:
121  {
122  const PCB_SHAPE* shape = static_cast<const PCB_SHAPE*>( item );
123  shape->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
124  ERROR_INSIDE );
125  break;
126  }
127 
128  case PCB_TEXT_T:
129  {
130  const PCB_TEXT* text = static_cast<const PCB_TEXT*>( item );
131  text->TransformTextShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
132  ERROR_INSIDE );
133  break;
134  }
135 
136  default:
137  break;
138  }
139  }
140 }
141 
142 
144  PCB_LAYER_ID aLayer, int aClearance,
145  int aMaxError, ERROR_LOC aErrorLoc,
146  bool aSkipNPTHPadsWihNoCopper,
147  bool aSkipPlatedPads,
148  bool aSkipNonPlatedPads ) const
149 {
150  for( const PAD* pad : m_pads )
151  {
152  if( aLayer != UNDEFINED_LAYER && !pad->IsOnLayer(aLayer) )
153  continue;
154 
155  if( !pad->FlashLayer( aLayer ) && IsCopperLayer( aLayer ) )
156  continue;
157 
158  // NPTH pads are not drawn on layers if the shape size and pos is the same
159  // as their hole:
160  if( aSkipNPTHPadsWihNoCopper && pad->GetAttribute() == PAD_ATTRIB::NPTH )
161  {
162  if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == wxPoint( 0, 0 ) )
163  {
164  switch( pad->GetShape() )
165  {
166  case PAD_SHAPE::CIRCLE:
167  if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
168  continue;
169 
170  break;
171 
172  case PAD_SHAPE::OVAL:
173  if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
174  continue;
175 
176  break;
177 
178  default:
179  break;
180  }
181  }
182  }
183 
184  const bool isPlated = ( ( aLayer == F_Cu ) && pad->FlashLayer( F_Mask ) ) ||
185  ( ( aLayer == B_Cu ) && pad->FlashLayer( B_Mask ) );
186 
187  if( aSkipPlatedPads && isPlated )
188  continue;
189 
190  if( aSkipNonPlatedPads && !isPlated )
191  continue;
192 
193  wxSize clearance( aClearance, aClearance );
194 
195  switch( aLayer )
196  {
197  case F_Mask:
198  case B_Mask:
199  clearance.x += pad->GetSolderMaskMargin();
200  clearance.y += pad->GetSolderMaskMargin();
201  break;
202 
203  case F_Paste:
204  case B_Paste:
205  clearance += pad->GetSolderPasteMargin();
206  break;
207 
208  default:
209  break;
210  }
211 
212  // Our standard TransformShapeWithClearanceToPolygon() routines can't handle differing
213  // x:y clearance values (which get generated when a relative paste margin is used with
214  // an oblong pad). So we apply this huge hack and fake a larger pad to run the transform
215  // on.
216  // Of course being a hack it falls down when dealing with custom shape pads (where the
217  // size is only the size of the anchor), so for those we punt and just use clearance.x.
218 
219  if( ( clearance.x < 0 || clearance.x != clearance.y )
220  && pad->GetShape() != PAD_SHAPE::CUSTOM )
221  {
222  PAD dummy( *pad );
223  dummy.SetSize( pad->GetSize() + clearance + clearance );
224  dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
225  aMaxError, aErrorLoc );
226  }
227  else
228  {
229  pad->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, clearance.x,
230  aMaxError, aErrorLoc );
231  }
232  }
233 }
234 
244  PCB_LAYER_ID aLayer, int aClearance,
245  int aError, ERROR_LOC aErrorLoc,
246  bool aIncludeText,
247  bool aIncludeShapes ) const
248 {
249  std::vector<FP_TEXT*> texts; // List of FP_TEXT to convert
250 
251  for( BOARD_ITEM* item : GraphicalItems() )
252  {
253  if( item->Type() == PCB_FP_TEXT_T && aIncludeText )
254  {
255  FP_TEXT* text = static_cast<FP_TEXT*>( item );
256 
257  if( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer && text->IsVisible() )
258  texts.push_back( text );
259  }
260 
261  if( item->Type() == PCB_FP_SHAPE_T && aIncludeShapes )
262  {
263  const FP_SHAPE* outline = static_cast<FP_SHAPE*>( item );
264 
265  if( aLayer != UNDEFINED_LAYER && outline->GetLayer() == aLayer )
266  {
267  outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
268  aError, aErrorLoc );
269  }
270  }
271  }
272 
273  if( aIncludeText )
274  {
275  if( Reference().GetLayer() == aLayer && Reference().IsVisible() )
276  texts.push_back( &Reference() );
277 
278  if( Value().GetLayer() == aLayer && Value().IsVisible() )
279  texts.push_back( &Value() );
280  }
281 
282  for( const FP_TEXT* text : texts )
283  {
284  text->TransformTextShapeWithClearanceToPolygon( aCornerBuffer, aLayer, aClearance,
285  aError, aErrorLoc );
286  }
287 }
288 
289 
291  PCB_LAYER_ID aLayer, int aClearance,
292  int aError, ERROR_LOC aErrorLoc ) const
293 {
294  prms.m_cornerBuffer = &aCornerBuffer;
295  prms.m_textWidth = GetEffectiveTextPenWidth() + ( 2 * aClearance );
296  prms.m_error = aError;
297  wxSize size = GetTextSize();
298  int penWidth = GetEffectiveTextPenWidth();
299 
300  if( IsMirrored() )
301  size.x = -size.x;
302 
303  GRText( nullptr, GetTextPos(), BLACK, GetShownText(), GetDrawRotation(), size,
304  GetHorizJustify(), GetVertJustify(), penWidth, IsItalic(), IsBold(),
306 }
307 
308 
310  PCB_LAYER_ID aLayer, int aClearance,
311  int aError, ERROR_LOC aErrorLoc,
312  bool aIgnoreLineWidth ) const
313 {
314  EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( &aCornerBuffer, aClearance );
315 
316  const FOOTPRINT* parentFootprint = static_cast<const FOOTPRINT*>( m_parent );
317 
318  if( parentFootprint )
319  aCornerBuffer.Rotate( DECIDEG2RAD( GetDrawRotation() ), GetTextPos() );
320 }
321 
322 
324  int aError ) const
325 {
326  if( !m_FilledPolysList.count( aLayer ) || m_FilledPolysList.at( aLayer ).IsEmpty() )
327  return;
328 
329  // Just add filled areas if filled polygons outlines have no thickness
331  {
332  const SHAPE_POLY_SET& polys = m_FilledPolysList.at( aLayer );
333  aCornerBuffer.Append( polys );
334  return;
335  }
336 
337  // Filled areas have polygons with outline thickness.
338  // we must create the polygons and add inflated polys
339  SHAPE_POLY_SET polys = m_FilledPolysList.at( aLayer );
340 
341  auto board = GetBoard();
342  int maxError = ARC_HIGH_DEF;
343 
344  if( board )
345  maxError = board->GetDesignSettings().m_MaxError;
346 
347  int numSegs = GetArcToSegmentCount( GetMinThickness(), maxError, 360.0 );
348 
350 
351  aCornerBuffer.Append( polys );
352 }
353 
354 
356  int aClearanceValue ) const
357 {
358  if( GetText().Length() == 0 )
359  return;
360 
361  wxPoint corners[4]; // Buffer of polygon corners
362 
363  EDA_RECT rect = GetTextBox();
364  rect.Inflate( aClearanceValue + Millimeter2iu( DEFAULT_TEXT_WIDTH ) );
365  corners[0].x = rect.GetOrigin().x;
366  corners[0].y = rect.GetOrigin().y;
367  corners[1].y = corners[0].y;
368  corners[1].x = rect.GetRight();
369  corners[2].x = corners[1].x;
370  corners[2].y = rect.GetBottom();
371  corners[3].y = corners[2].y;
372  corners[3].x = corners[0].x;
373 
374  aCornerBuffer->NewOutline();
375 
376  for( wxPoint& corner : corners )
377  {
378  // Rotate polygon
379  RotatePoint( &corner.x, &corner.y, GetTextPos().x, GetTextPos().y, GetTextAngle() );
380  aCornerBuffer->Append( corner.x, corner.y );
381  }
382 }
383 
384 
386  PCB_LAYER_ID aLayer, int aClearanceValue,
387  int aError, ERROR_LOC aErrorLoc ) const
388 {
389  wxSize size = GetTextSize();
390 
391  if( IsMirrored() )
392  size.x = -size.x;
393 
394  int penWidth = GetEffectiveTextPenWidth();
395 
396  prms.m_cornerBuffer = &aCornerBuffer;
397  prms.m_textWidth = GetEffectiveTextPenWidth() + ( 2 * aClearanceValue );
398  prms.m_error = aError;
399  COLOR4D color; // not actually used, but needed by GRText
400 
401  GRText( nullptr, GetTextPos(), color, GetShownText(), GetTextAngle(), size, GetHorizJustify(),
402  GetVertJustify(), penWidth, IsItalic(), IsBold(), addTextSegmToPoly, &prms );
403 }
404 
405 
407  PCB_LAYER_ID aLayer, int aClearance,
408  int aError, ERROR_LOC aErrorLoc,
409  bool aIgnoreLineWidth ) const
410 {
411  EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( &aCornerBuffer, aClearance );
412 }
413 
414 
416  PCB_LAYER_ID aLayer, int aClearanceValue,
417  int aError, ERROR_LOC aErrorLoc,
418  bool ignoreLineWidth ) const
419 {
420  int width = ignoreLineWidth ? 0 : m_width;
421 
422  width += 2 * aClearanceValue;
423 
424  switch( m_shape )
425  {
426  case SHAPE_T::CIRCLE:
427  if( IsFilled() )
428  {
429  TransformCircleToPolygon( aCornerBuffer, GetCenter(), GetRadius() + width / 2, aError,
430  aErrorLoc );
431  }
432  else
433  {
434  TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), width, aError,
435  aErrorLoc );
436  }
437 
438  break;
439 
440  case SHAPE_T::RECT:
441  {
442  std::vector<wxPoint> pts = GetRectCorners();
443 
444  if( IsFilled() )
445  {
446  aCornerBuffer.NewOutline();
447 
448  for( const wxPoint& pt : pts )
449  aCornerBuffer.Append( pt );
450  }
451 
452  if( width > 0 || !IsFilled() )
453  {
454  // Add in segments
455  TransformOvalToPolygon( aCornerBuffer, pts[0], pts[1], width, aError, aErrorLoc );
456  TransformOvalToPolygon( aCornerBuffer, pts[1], pts[2], width, aError, aErrorLoc );
457  TransformOvalToPolygon( aCornerBuffer, pts[2], pts[3], width, aError, aErrorLoc );
458  TransformOvalToPolygon( aCornerBuffer, pts[3], pts[0], width, aError, aErrorLoc );
459  }
460 
461  break;
462  }
463 
464  case SHAPE_T::ARC:
465  TransformArcToPolygon( aCornerBuffer, GetArcStart(), GetArcMid(), GetArcEnd(), width,
466  aError, aErrorLoc );
467  break;
468 
469  case SHAPE_T::SEGMENT:
470  TransformOvalToPolygon( aCornerBuffer, m_start, m_end, width, aError, aErrorLoc );
471  break;
472 
473  case SHAPE_T::POLY:
474  {
475  if( !IsPolyShapeValid() )
476  break;
477 
478  // The polygon is expected to be a simple polygon; not self intersecting, no hole.
479  FOOTPRINT* footprint = GetParentFootprint();
480  double orientation = footprint ? footprint->GetOrientation() : 0.0;
481  wxPoint offset;
482 
483  if( footprint )
484  offset = footprint->GetPosition();
485 
486  // Build the polygon with the actual position and orientation:
487  std::vector<wxPoint> poly;
488  poly = BuildPolyPointsList();
489 
490  for( wxPoint& point : poly )
491  {
492  RotatePoint( &point, orientation );
493  point += offset;
494  }
495 
496  if( IsFilled() )
497  {
498  aCornerBuffer.NewOutline();
499 
500  for( const wxPoint& point : poly )
501  aCornerBuffer.Append( point.x, point.y );
502  }
503 
504  if( width > 0 || !IsFilled() )
505  {
506  wxPoint pt1( poly[ poly.size() - 1] );
507 
508  for( const wxPoint& pt2 : poly )
509  {
510  if( pt2 != pt1 )
511  TransformOvalToPolygon( aCornerBuffer, pt1, pt2, width, aError, aErrorLoc );
512 
513  pt1 = pt2;
514  }
515  }
516 
517  break;
518  }
519 
520  case SHAPE_T::BEZIER: // Bezier curve
521  {
522  std::vector<wxPoint> ctrlPoints = { m_start, m_bezierC1, m_bezierC2, m_end };
523  BEZIER_POLY converter( ctrlPoints );
524  std::vector< wxPoint> poly;
525  converter.GetPoly( poly, m_width );
526 
527  for( unsigned ii = 1; ii < poly.size(); ii++ )
528  {
529  TransformOvalToPolygon( aCornerBuffer, poly[ii - 1], poly[ii], width, aError,
530  aErrorLoc );
531  }
532 
533  break;
534  }
535 
536  default:
537  wxFAIL_MSG( "PCB_SHAPE::TransformShapeWithClearanceToPolygon no implementation for "
538  + SHAPE_T_asString( m_shape ) );
539  break;
540  }
541 }
542 
543 
545  PCB_LAYER_ID aLayer, int aClearanceValue,
546  int aError, ERROR_LOC aErrorLoc,
547  bool ignoreLineWidth ) const
548 {
549  wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." );
550 
551 
552  switch( Type() )
553  {
554  case PCB_VIA_T:
555  {
556  int radius = ( m_Width / 2 ) + aClearanceValue;
557  TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError, aErrorLoc );
558  break;
559  }
560 
561  case PCB_ARC_T:
562  {
563  const PCB_ARC* arc = static_cast<const PCB_ARC*>( this );
564  int width = m_Width + ( 2 * aClearanceValue );
565 
566  TransformArcToPolygon( aCornerBuffer, arc->GetStart(), arc->GetMid(),
567  arc->GetEnd(), width, aError, aErrorLoc );
568  break;
569  }
570 
571  default:
572  {
573  int width = m_Width + ( 2 * aClearanceValue );
574 
575  TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError, aErrorLoc );
576  break;
577  }
578  }
579 }
580 
581 
583  PCB_LAYER_ID aLayer, int aClearanceValue,
584  int aError, ERROR_LOC aErrorLoc,
585  bool ignoreLineWidth ) const
586 {
587  wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." );
588 
589  // minimal segment count to approximate a circle to create the polygonal pad shape
590  // This minimal value is mainly for very small pads, like SM0402.
591  // Most of time pads are using the segment count given by aError value.
592  const int pad_min_seg_per_circle_count = 16;
593  double angle = m_orient;
594  int dx = m_size.x / 2;
595  int dy = m_size.y / 2;
596 
597  wxPoint padShapePos = ShapePos(); // Note: for pad having a shape offset,
598  // the pad position is NOT the shape position
599 
600  switch( GetShape() )
601  {
602  case PAD_SHAPE::CIRCLE:
603  case PAD_SHAPE::OVAL:
604  // Note: dx == dy is not guaranteed for circle pads in legacy boards
605  if( dx == dy || ( GetShape() == PAD_SHAPE::CIRCLE ) )
606  {
607  TransformCircleToPolygon( aCornerBuffer, padShapePos, dx + aClearanceValue, aError,
608  aErrorLoc, pad_min_seg_per_circle_count );
609  }
610  else
611  {
612  int half_width = std::min( dx, dy );
613  wxPoint delta( dx - half_width, dy - half_width );
614 
615  RotatePoint( &delta, angle );
616 
617  TransformOvalToPolygon( aCornerBuffer, padShapePos - delta, padShapePos + delta,
618  ( half_width + aClearanceValue ) * 2, aError, aErrorLoc,
619  pad_min_seg_per_circle_count );
620  }
621 
622  break;
623 
625  case PAD_SHAPE::RECT:
626  {
627  int ddx = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.x / 2 : 0;
628  int ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_deltaSize.y / 2 : 0;
629 
630  SHAPE_POLY_SET outline;
631  TransformTrapezoidToPolygon( outline, padShapePos, m_size, angle, ddx, ddy,
632  aClearanceValue, aError, aErrorLoc );
633  aCornerBuffer.Append( outline );
634  break;
635  }
636 
639  {
640  bool doChamfer = GetShape() == PAD_SHAPE::CHAMFERED_RECT;
641 
642  SHAPE_POLY_SET outline;
643  TransformRoundChamferedRectToPolygon( outline, padShapePos, m_size, angle,
645  doChamfer ? GetChamferRectRatio() : 0,
646  doChamfer ? GetChamferPositions() : 0,
647  aClearanceValue, aError, aErrorLoc );
648  aCornerBuffer.Append( outline );
649  break;
650  }
651 
652  case PAD_SHAPE::CUSTOM:
653  {
654  SHAPE_POLY_SET outline;
655  MergePrimitivesAsPolygon( &outline, aLayer, aErrorLoc );
656  outline.Rotate( -DECIDEG2RAD( m_orient ) );
657  outline.Move( VECTOR2I( m_pos ) );
658 
659  if( aClearanceValue )
660  {
661  int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
662  pad_min_seg_per_circle_count );
663  int clearance = aClearanceValue;
664 
665  if( aErrorLoc == ERROR_OUTSIDE )
666  {
667  int actual_error = CircleToEndSegmentDeltaRadius( clearance, numSegs );
668  clearance += GetCircleToPolyCorrection( actual_error );
669  }
670 
671  outline.Inflate( clearance, numSegs );
674  }
675 
676  aCornerBuffer.Append( outline );
677  break;
678  }
679 
680  default:
681  wxFAIL_MSG( "PAD::TransformShapeWithClearanceToPolygon no implementation for "
683  break;
684  }
685 }
686 
687 
688 
689 bool PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
690  int aError, ERROR_LOC aErrorLoc ) const
691 {
692  wxSize drillsize = GetDrillSize();
693 
694  if( !drillsize.x || !drillsize.y )
695  return false;
696 
697  const SHAPE_SEGMENT* seg = GetEffectiveHoleShape();
698 
699  TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A, (wxPoint) seg->GetSeg().B,
700  seg->GetWidth() + aInflateValue * 2, aError, aErrorLoc );
701 
702  return true;
703 }
704 
705 
707  PCB_LAYER_ID aLayer, int aClearance, int aError,
708  ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
709 {
710  wxASSERT_MSG( !aIgnoreLineWidth, "IgnoreLineWidth has no meaning for zones." );
711 
712  if( !m_FilledPolysList.count( aLayer ) )
713  return;
714 
715  aCornerBuffer = m_FilledPolysList.at( aLayer );
716 
717  int numSegs = GetArcToSegmentCount( aClearance, aError, 360.0 );
718  aCornerBuffer.Inflate( aClearance, numSegs );
720 }
721 
722 
724  PCB_LAYER_ID aLayer, int aClearance,
725  int aError, ERROR_LOC aErrorLoc,
726  bool aIgnoreLineWidth ) const
727 {
728  wxASSERT_MSG( !aIgnoreLineWidth, "IgnoreLineWidth has no meaning for dimensions." );
729 
730  for( const std::shared_ptr<SHAPE>& shape : m_shapes )
731  {
732  const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
733  const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
734 
735  if( circle )
736  {
737  TransformCircleToPolygon( aCornerBuffer, (wxPoint) circle->GetCenter(),
738  circle->GetRadius() + m_lineThickness / 2 + aClearance,
739  aError, aErrorLoc );
740  }
741  else if( seg )
742  {
743  TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A,
744  (wxPoint) seg->GetSeg().B, m_lineThickness + 2 * aClearance,
745  aError, aErrorLoc );
746  }
747  else
748  {
749  wxFAIL_MSG( "PCB_DIMENSION_BASE::TransformShapeWithClearanceToPolygon unexpected "
750  "shape type." );
751  }
752  }
753 }
754 
bool TransformHoleWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aInflateValue, int aError, ERROR_LOC aErrorLoc) const
Build the corner list of the polygonal drill shape in the board coordinate system.
virtual double GetDrawRotation() const override
Definition: fp_text.cpp:239
wxPoint GetArcEnd() const
Definition: pcb_shape.cpp:417
bool IsPolyShapeValid() const
Definition: pcb_shape.cpp:1294
bool IsBold() const
Definition: eda_text.h:183
EDA_ITEM * m_parent
Linked list: Link (parent struct)
Definition: eda_item.h:479
wxPoint m_Start
Line start point.
Definition: pcb_track.h:240
Arcs (with rounded ends)
bool IsFilled() const
Definition: pcb_shape.h:75
Bezier Curve.
void TransformTextShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc) const
wxPoint m_end
Definition: pcb_shape.h:346
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:199
bool IsMirrored() const
Definition: eda_text.h:189
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
ZONES & Zones()
Definition: board.h:239
int CircleToEndSegmentDeltaRadius(int aInnerCircleRadius, int aSegCount)
polygon (not yet used for tracks, but could be in microwave apps)
int GetRadius() const
Definition: shape_circle.h:107
const wxPoint & GetEnd() const
Definition: pcb_track.h:105
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines) const
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
static void addTextSegmToPoly(int x0, int y0, int xf, int yf, void *aData)
wxSize m_deltaSize
Definition: pad.h:737
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
void TransformTextShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc) const
Function TransformTextShapeWithClearanceToPolygon Convert the text to a polygonSet describing the act...
void GetPoly(std::vector< wxPoint > &aOutput, int aMinSegLen=0)
Convert a Bezier curve to a polygon.
int GetRadius() const
Return the radius of this item.
Definition: pcb_shape.cpp:487
int color
Definition: DXF_plotter.cpp:60
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
std::vector< wxPoint > GetRectCorners() const
Definition: pcb_shape.cpp:1048
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
usual segment : line with rounded ends
double GetOrientation() const
Definition: footprint.h:181
static void isPlated(LIBEVAL::CONTEXT *aCtx, void *self)
double GetTextAngle() const
Definition: eda_text.h:174
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
Definition: pad.cpp:292
void GRText(wxDC *aDC, const wxPoint &aPos, const COLOR4D &aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, void(*aCallback)(int x0, int y0, int xf, int yf, void *aData), void *aCallbackData, PLOTTER *aPlotter)
Draw a graphic text (like footprint texts).
Definition: gr_text.cpp:130
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
wxPoint m_pos
Definition: pad.h:678
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the track shape to a closed polygon Used in fil...
const VECTOR2I GetCenter() const
Definition: shape_circle.h:112
Definition: color4d.h:44
void TransformBoundingBoxWithClearanceToPolygon(SHAPE_POLY_SET *aCornerBuffer, int aClearanceValue) const
Convert the text bounding box to a rectangular polygon depending on the text orientation,...
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
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.
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
TRACKS m_tracks
Definition: board.h:1114
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.cpp:588
const SEG & GetSeg() const
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:149
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:114
wxPoint GetArcStart() const
Definition: pcb_shape.h:156
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:457
wxPoint m_End
Line end point.
Definition: pcb_track.h:241
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
bool IsItalic() const
Definition: eda_text.h:180
FP_TEXT & Reference()
Definition: footprint.h:458
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:71
#define DEFAULT_TEXT_WIDTH
wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: pcb_text.cpp:56
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint>
Definition: pcb_shape.cpp:1277
const wxSize & GetDrillSize() const
Definition: pad.h:239
wxPoint ShapePos() const
Definition: pad.cpp:659
like PAD_PTH, but not plated
PCB_LAYER_ID
A quick note on layer IDs:
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:198
int GetMinThickness() const
Definition: zone.h:245
void Move(const VECTOR2I &aVector) override
Represent a set of closed polygons.
const wxPoint GetOrigin() const
Definition: eda_rect.h:101
TSEGM_2_POLY_PRMS prms
const wxSize & GetTextSize() const
Definition: eda_text.h:238
wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.cpp:385
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 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 TransformTrapezoidToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aDeltaX, int aDeltaY, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle or trapezoid to a polygon.
static wxString SHAPE_T_asString(SHAPE_T a)
Definition: board_item.h:57
double m_orient
Definition: pad.h:748
PAD_SHAPE GetShape() const
Definition: pad.h:166
DRAWINGS & GraphicalItems()
Definition: footprint.h:162
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
int GetCircleToPolyCorrection(int aMaxError)
void TransformSolidAreasShapesToPolygon(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aCornerBuffer, int aError=ARC_HIGH_DEF) const
Convert solid areas full shapes to polygon set (the full shape is the polygon area with a thick outli...
DRAWINGS m_drawings
Definition: board.h:1112
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, PCB_LAYER_ID aLayer, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Merge all basic shapes to a SHAPE_POLY_SET.
int NewOutline()
Creates a new hole in a given outline.
void TransformPadsWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aSkipNPTHPadsWihNoCopper=false, bool aSkipPlatedPads=false, bool aSkipNonPlatedPads=false) const
Generate pads shapes on layer aLayer as polygons and adds these polygons to aCornerBuffer.
void Fracture(POLYGON_MODE aFastMode)
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
void Inflate(int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Perform outline inflation/deflation.
int GetRoundRectCornerRadius() const
Definition: pad.cpp:243
wxSize m_size
Definition: pad.h:712
wxPoint m_start
Definition: pcb_shape.h:345
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 TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aMaxError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the pad shape to a closed polygon.
int m_Width
Thickness of track, or via diameter.
Definition: pcb_track.h:239
Bezier curves to polygon converter.
Definition: bezier_curves.h:36
double GetChamferRectRatio() const
Definition: pad.h:529
int m_width
Definition: pcb_shape.h:343
FOOTPRINT * GetParentFootprint() const
Return the parent footprint or NULL if PCB_SHAPE does not belong to a footprint.
Definition: pcb_shape.cpp:532
void TransformFPShapesWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIncludeText=true, bool aIncludeShapes=true) const
Generate shapes of graphic items (outlines) on layer aLayer as polygons and adds these polygons to aC...
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
VECTOR2I A
Definition: seg.h:48
Handle the component boundary box.
Definition: eda_rect.h:42
double DECIDEG2RAD(double deg)
Definition: trigo.h:233
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.
static std::string PAD_SHAPE_T_asString(PAD_SHAPE a)
Definition: pad_shapes.h:47
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
int m_lineThickness
Thickness used for all graphics in the dimension.
wxPoint GetPosition() const override
Definition: footprint.h:177
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
int GetChamferPositions() const
Definition: pad.h:539
const wxPoint & GetTextPos() const
Definition: eda_text.h:247
void TransformArcToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aStart, const wxPoint &aMid, const wxPoint &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arc to multiple straight segments.
wxPoint m_bezierC1
Definition: pcb_shape.h:351
FOOTPRINTS m_footprints
Definition: board.h:1113
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
wxPoint GetArcMid() const
Definition: pcb_shape.cpp:435
segment with non rounded ends
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the zone shape to a closed polygon Used in filling zones calculations Circles and arcs are ap...
Definition: pad.h:57
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, PCB_LAYER_ID aLayer, int aClearanceValue, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the draw segment to a closed polygon.
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:414
wxPoint m_bezierC2
Definition: pcb_shape.h:352
int GetWidth() const
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
SHAPE_T m_shape
Definition: pcb_shape.h:349
static constexpr int Millimeter2iu(double mm)
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_FilledPolysList
Definition: zone.h:918
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:171
const wxPoint & GetMid() const
Definition: pcb_track.h:273
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133
void TransformRingToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aCentre, int aRadius, int aWidth, int aError, ERROR_LOC aErrorLoc)
Convert arcs to multiple straight segments.
PADS m_pads
Definition: footprint.h:678
const wxPoint & GetStart() const
Definition: pcb_track.h:108
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:364
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
bool GetFilledPolysUseThickness() const
Definition: zone.h:690
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...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103
VECTOR2I B
Definition: seg.h:49