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-2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2019 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 <trigo.h>
28 #include <board.h>
29 #include <pad.h>
30 #include <dimension.h>
31 #include <track.h>
32 #include <kicad_string.h>
33 #include <pcb_shape.h>
34 #include <pcb_text.h>
35 #include <zone.h>
36 #include <footprint.h>
37 #include <fp_shape.h>
40 #include <geometry/shape_segment.h>
41 #include <geometry/shape_circle.h>
42 #include <geometry/shape_rect.h>
44 
45 
46 // A helper struct for the callback function
47 // These variables are parameters used in addTextSegmToPoly.
48 // But addTextSegmToPoly is a call-back function,
49 // so we cannot send them as arguments.
51 {
53  int m_error;
55 };
56 
58 
59 
60 // This is a call back function, used by GRText to draw the 3D text shape:
61 static void addTextSegmToPoly( int x0, int y0, int xf, int yf, void* aData )
62 {
63  TSEGM_2_POLY_PRMS* prm = static_cast<TSEGM_2_POLY_PRMS*>( aData );
64  TransformOvalToPolygon( *prm->m_cornerBuffer, wxPoint( x0, y0 ), wxPoint( xf, yf ),
65  prm->m_textWidth, prm->m_error, ERROR_INSIDE );
66 }
67 
68 
70 {
71  int maxError = GetDesignSettings().m_MaxError;
72 
73  // convert tracks and vias:
74  for( TRACK* track : m_tracks )
75  {
76  if( !track->IsOnLayer( aLayer ) )
77  continue;
78 
79  track->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
80  ERROR_INSIDE );
81  }
82 
83  // convert pads and other copper items in footprints
84  for( FOOTPRINT* footprint : m_footprints )
85  {
86  footprint->TransformPadsWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
87  ERROR_INSIDE );
88 
89  // Micro-wave footprints may have items on copper layers
90  footprint->TransformFPShapesWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
92  true, /* include text */
93  true /* include shapes */ );
94 
95  for( ZONE* zone : footprint->Zones() )
96  {
97  if( zone->GetLayerSet().test( aLayer ) )
98  zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
99  }
100  }
101 
102  // convert copper zones
103  for( ZONE* zone : Zones() )
104  {
105  if( zone->GetLayerSet().test( aLayer ) )
106  zone->TransformSolidAreasShapesToPolygon( aLayer, aOutlines );
107  }
108 
109  // convert graphic items on copper layers (texts)
110  for( BOARD_ITEM* item : m_drawings )
111  {
112  if( !item->IsOnLayer( aLayer ) )
113  continue;
114 
115  switch( item->Type() )
116  {
117  case PCB_SHAPE_T:
118  {
119  PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
120  shape->TransformShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
121  ERROR_INSIDE );
122  }
123  break;
124 
125  case PCB_TEXT_T:
126  {
127  PCB_TEXT* text = static_cast<PCB_TEXT*>( item );
128  text->TransformTextShapeWithClearanceToPolygon( aOutlines, aLayer, 0, maxError,
129  ERROR_INSIDE );
130  }
131  break;
132 
133  default:
134  break;
135  }
136  }
137 }
138 
139 
141  PCB_LAYER_ID aLayer, int aClearance,
142  int aMaxError, ERROR_LOC aErrorLoc,
143  bool aSkipNPTHPadsWihNoCopper,
144  bool aSkipPlatedPads,
145  bool aSkipNonPlatedPads ) const
146 {
147  for( PAD* pad : m_pads )
148  {
149  if( aLayer != UNDEFINED_LAYER && !pad->IsOnLayer(aLayer) )
150  continue;
151 
152  if( !pad->FlashLayer( aLayer ) && IsCopperLayer( aLayer ) )
153  continue;
154 
155  // NPTH pads are not drawn on layers if the shape size and pos is the same
156  // as their hole:
157  if( aSkipNPTHPadsWihNoCopper && pad->GetAttribute() == PAD_ATTRIB_NPTH )
158  {
159  if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == wxPoint( 0, 0 ) )
160  {
161  switch( pad->GetShape() )
162  {
163  case PAD_SHAPE_CIRCLE:
164  if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
165  continue;
166  break;
167 
168  case PAD_SHAPE_OVAL:
169  if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
170  continue;
171  break;
172 
173  default:
174  break;
175  }
176  }
177  }
178 
179  const bool isPlated = ( ( aLayer == F_Cu ) && pad->FlashLayer( F_Mask ) ) ||
180  ( ( aLayer == B_Cu ) && pad->FlashLayer( B_Mask ) );
181 
182  if( aSkipPlatedPads && isPlated )
183  continue;
184 
185  if( aSkipNonPlatedPads && !isPlated )
186  continue;
187 
188  wxSize clearance( aClearance, aClearance );
189 
190  switch( aLayer )
191  {
192  case F_Mask:
193  case B_Mask:
194  clearance.x += pad->GetSolderMaskMargin();
195  clearance.y += pad->GetSolderMaskMargin();
196  break;
197 
198  case F_Paste:
199  case B_Paste:
200  clearance += pad->GetSolderPasteMargin();
201  break;
202 
203  default:
204  break;
205  }
206 
207  // Our standard TransformShapeWithClearanceToPolygon() routines can't handle differing
208  // x:y clearance values (which get generated when a relative paste margin is used with
209  // an oblong pad). So we apply this huge hack and fake a larger pad to run the transform
210  // on.
211  // Of course being a hack it falls down when dealing with custom shape pads (where the
212  // size is only the size of the anchor), so for those we punt and just use clearance.x.
213 
214  if( ( clearance.x < 0 || clearance.x != clearance.y )
215  && pad->GetShape() != PAD_SHAPE_CUSTOM )
216  {
217  PAD dummy( *pad );
218  dummy.SetSize( pad->GetSize() + clearance + clearance );
219  dummy.TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
220  aMaxError, aErrorLoc );
221  }
222  else
223  {
224  pad->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, clearance.x,
225  aMaxError, aErrorLoc );
226  }
227  }
228 }
229 
239  PCB_LAYER_ID aLayer, int aClearance,
240  int aError, ERROR_LOC aErrorLoc,
241  bool aIncludeText,
242  bool aIncludeShapes ) const
243 {
244  std::vector<FP_TEXT*> texts; // List of FP_TEXT to convert
245 
246  for( BOARD_ITEM* item : GraphicalItems() )
247  {
248  if( item->Type() == PCB_FP_TEXT_T && aIncludeText )
249  {
250  FP_TEXT* text = static_cast<FP_TEXT*>( item );
251 
252  if( aLayer != UNDEFINED_LAYER && text->GetLayer() == aLayer && text->IsVisible() )
253  texts.push_back( text );
254  }
255 
256  if( item->Type() == PCB_FP_SHAPE_T && aIncludeShapes )
257  {
258  FP_SHAPE* outline = static_cast<FP_SHAPE*>( item );
259 
260  if( aLayer != UNDEFINED_LAYER && outline->GetLayer() == aLayer )
261  {
262  outline->TransformShapeWithClearanceToPolygon( aCornerBuffer, aLayer, 0,
263  aError, aErrorLoc );
264  }
265  }
266  }
267 
268  if( aIncludeText )
269  {
270  if( Reference().GetLayer() == aLayer && Reference().IsVisible() )
271  texts.push_back( &Reference() );
272 
273  if( Value().GetLayer() == aLayer && Value().IsVisible() )
274  texts.push_back( &Value() );
275  }
276 
277  for( FP_TEXT* text : texts )
278  {
279  text->TransformTextShapeWithClearanceToPolygon( aCornerBuffer, aLayer, aClearance,
280  aError, aErrorLoc );
281  }
282 }
283 
284 
293  PCB_LAYER_ID aLayer, int aClearance,
294  int aError, ERROR_LOC aErrorLoc ) const
295 {
296  bool forceBold = true;
297  int penWidth = 0; // force max width for bold text
298 
299  prms.m_cornerBuffer = &aCornerBuffer;
300  prms.m_textWidth = GetEffectiveTextPenWidth() + ( 2 * aClearance );
301  prms.m_error = aError;
302  wxSize size = GetTextSize();
303 
304  if( IsMirrored() )
305  size.x = -size.x;
306 
308  GetVertJustify(), penWidth, IsItalic(), forceBold, addTextSegmToPoly, &prms );
309 }
310 
311 
313  PCB_LAYER_ID aLayer, int aClearance,
314  int aError, ERROR_LOC aErrorLoc,
315  bool aIgnoreLineWidth ) const
316 {
317  EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( &aCornerBuffer, aClearance );
318 }
319 
320 
322  int aError ) const
323 {
324  if( !m_FilledPolysList.count( aLayer ) || m_FilledPolysList.at( aLayer ).IsEmpty() )
325  return;
326 
327  // Just add filled areas if filled polygons outlines have no thickness
329  {
330  const SHAPE_POLY_SET& polys = m_FilledPolysList.at( aLayer );
331  aCornerBuffer.Append( polys );
332  return;
333  }
334 
335  // Filled areas have polygons with outline thickness.
336  // we must create the polygons and add inflated polys
337  SHAPE_POLY_SET polys = m_FilledPolysList.at( aLayer );
338 
339  auto board = GetBoard();
340  int maxError = ARC_HIGH_DEF;
341 
342  if( board )
343  maxError = board->GetDesignSettings().m_MaxError;
344 
345  int numSegs = GetArcToSegmentCount( GetMinThickness(), maxError, 360.0 );
346 
348 
349  aCornerBuffer.Append( polys );
350 }
351 
352 
354  int aClearanceValue ) const
355 {
356  if( GetText().Length() == 0 )
357  return;
358 
359  wxPoint corners[4]; // Buffer of polygon corners
360 
361  EDA_RECT rect = GetTextBox();
362  rect.Inflate( aClearanceValue + Millimeter2iu( DEFAULT_TEXT_WIDTH ) );
363  corners[0].x = rect.GetOrigin().x;
364  corners[0].y = rect.GetOrigin().y;
365  corners[1].y = corners[0].y;
366  corners[1].x = rect.GetRight();
367  corners[2].x = corners[1].x;
368  corners[2].y = rect.GetBottom();
369  corners[3].y = corners[2].y;
370  corners[3].x = corners[0].x;
371 
372  aCornerBuffer->NewOutline();
373 
374  for( wxPoint& corner : corners )
375  {
376  // Rotate polygon
377  RotatePoint( &corner.x, &corner.y, GetTextPos().x, GetTextPos().y, GetTextAngle() );
378  aCornerBuffer->Append( corner.x, corner.y );
379  }
380 }
381 
382 
391  PCB_LAYER_ID aLayer, int aClearanceValue,
392  int aError, ERROR_LOC aErrorLoc ) const
393 {
394  wxSize size = GetTextSize();
395 
396  if( IsMirrored() )
397  size.x = -size.x;
398 
399  bool forceBold = true;
400  int penWidth = GetEffectiveTextPenWidth();
401 
402  prms.m_cornerBuffer = &aCornerBuffer;
403  prms.m_textWidth = GetEffectiveTextPenWidth() + ( 2 * aClearanceValue );
404  prms.m_error = aError;
405  COLOR4D color = COLOR4D::BLACK; // not actually used, but needed by GRText
406 
407  if( IsMultilineAllowed() )
408  {
409  wxArrayString strings_list;
410  wxStringSplit( GetShownText(), strings_list, '\n' );
411  std::vector<wxPoint> positions;
412  positions.reserve( strings_list.Count() );
413  GetLinePositions( positions, strings_list.Count() );
414 
415  for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
416  {
417  wxString txt = strings_list.Item( ii );
418  GRText( NULL, positions[ii], color, txt, GetTextAngle(), size, GetHorizJustify(),
419  GetVertJustify(), penWidth, IsItalic(), forceBold, addTextSegmToPoly, &prms );
420  }
421  }
422  else
423  {
425  GetVertJustify(), penWidth, IsItalic(), forceBold, addTextSegmToPoly, &prms );
426  }
427 }
428 
429 
431  PCB_LAYER_ID aLayer, int aClearance,
432  int aError, ERROR_LOC aErrorLoc,
433  bool aIgnoreLineWidth ) const
434 {
435  EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon( &aCornerBuffer, aClearance );
436 }
437 
438 
440  PCB_LAYER_ID aLayer, int aClearanceValue,
441  int aError, ERROR_LOC aErrorLoc,
442  bool ignoreLineWidth ) const
443 {
444  int width = ignoreLineWidth ? 0 : m_width;
445 
446  width += 2 * aClearanceValue;
447 
448  switch( m_shape )
449  {
450  case S_CIRCLE:
451  if( IsFilled() )
452  {
453  TransformCircleToPolygon( aCornerBuffer, GetCenter(), GetRadius() + width / 2, aError,
454  aErrorLoc );
455  }
456  else
457  {
458  TransformRingToPolygon( aCornerBuffer, GetCenter(), GetRadius(), width, aError,
459  aErrorLoc );
460  }
461  break;
462 
463  case S_RECT:
464  {
465  std::vector<wxPoint> pts = GetRectCorners();
466 
467  if( IsFilled() )
468  {
469  aCornerBuffer.NewOutline();
470 
471  for( const wxPoint& pt : pts )
472  aCornerBuffer.Append( pt );
473  }
474 
475  if( width > 0 || !IsFilled() )
476  {
477  // Add in segments
478  TransformOvalToPolygon( aCornerBuffer, pts[0], pts[1], width, aError, aErrorLoc );
479  TransformOvalToPolygon( aCornerBuffer, pts[1], pts[2], width, aError, aErrorLoc );
480  TransformOvalToPolygon( aCornerBuffer, pts[2], pts[3], width, aError, aErrorLoc );
481  TransformOvalToPolygon( aCornerBuffer, pts[3], pts[0], width, aError, aErrorLoc );
482  }
483  }
484  break;
485 
486  case S_ARC:
487  TransformArcToPolygon( aCornerBuffer, GetArcStart(), GetArcMid(), GetArcEnd(), width,
488  aError, aErrorLoc );
489  break;
490 
491  case S_SEGMENT:
492  TransformOvalToPolygon( aCornerBuffer, m_start, m_end, width, aError, aErrorLoc );
493  break;
494 
495  case S_POLYGON:
496  {
497  if( !IsPolyShapeValid() )
498  break;
499 
500  // The polygon is expected to be a simple polygon; not self intersecting, no hole.
501  FOOTPRINT* footprint = GetParentFootprint();
502  double orientation = footprint ? footprint->GetOrientation() : 0.0;
503  wxPoint offset;
504 
505  if( footprint )
506  offset = footprint->GetPosition();
507 
508  // Build the polygon with the actual position and orientation:
509  std::vector< wxPoint> poly;
510  poly = BuildPolyPointsList();
511 
512  for( wxPoint& point : poly )
513  {
514  RotatePoint( &point, orientation );
515  point += offset;
516  }
517 
518  if( IsFilled() )
519  {
520  aCornerBuffer.NewOutline();
521 
522  for( wxPoint& point : poly )
523  aCornerBuffer.Append( point.x, point.y );
524  }
525 
526  if( width > 0 || !IsFilled() )
527  {
528  wxPoint pt1( poly[ poly.size() - 1] );
529 
530  for( wxPoint pt2 : poly )
531  {
532  if( pt2 != pt1 )
533  TransformOvalToPolygon( aCornerBuffer, pt1, pt2, width, aError, aErrorLoc );
534 
535  pt1 = pt2;
536  }
537  }
538  }
539  break;
540 
541  case S_CURVE: // Bezier curve
542  {
543  std::vector<wxPoint> ctrlPoints = { m_start, m_bezierC1, m_bezierC2, m_end };
544  BEZIER_POLY converter( ctrlPoints );
545  std::vector< wxPoint> poly;
546  converter.GetPoly( poly, m_width );
547 
548  for( unsigned ii = 1; ii < poly.size(); ii++ )
549  {
550  TransformOvalToPolygon( aCornerBuffer, poly[ii-1], poly[ii], width, aError, aErrorLoc );
551  }
552  }
553  break;
554 
555  default:
556  wxFAIL_MSG( "PCB_SHAPE::TransformShapeWithClearanceToPolygon no implementation for "
558  break;
559  }
560 }
561 
562 
564  PCB_LAYER_ID aLayer, int aClearanceValue,
565  int aError, ERROR_LOC aErrorLoc,
566  bool ignoreLineWidth ) const
567 {
568  wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for tracks." );
569 
570 
571  switch( Type() )
572  {
573  case PCB_VIA_T:
574  {
575  int radius = ( m_Width / 2 ) + aClearanceValue;
576  TransformCircleToPolygon( aCornerBuffer, m_Start, radius, aError, aErrorLoc );
577  }
578  break;
579 
580  case PCB_ARC_T:
581  {
582  const ARC* arc = static_cast<const ARC*>( this );
583  int width = m_Width + ( 2 * aClearanceValue );
584 
585  TransformArcToPolygon( aCornerBuffer, (wxPoint) arc->GetStart(), (wxPoint) arc->GetMid(),
586  (wxPoint) arc->GetEnd(), width, aError, aErrorLoc );
587  }
588  break;
589 
590  default:
591  {
592  int width = m_Width + ( 2 * aClearanceValue );
593 
594  TransformOvalToPolygon( aCornerBuffer, m_Start, m_End, width, aError, aErrorLoc );
595  }
596  break;
597  }
598 }
599 
600 
602  PCB_LAYER_ID aLayer, int aClearanceValue,
603  int aError, ERROR_LOC aErrorLoc,
604  bool ignoreLineWidth ) const
605 {
606  wxASSERT_MSG( !ignoreLineWidth, "IgnoreLineWidth has no meaning for pads." );
607 
608  // minimal segment count to approximate a circle to create the polygonal pad shape
609  // This minimal value is mainly for very small pads, like SM0402.
610  // Most of time pads are using the segment count given by aError value.
611  const int pad_min_seg_per_circle_count = 16;
612  double angle = m_orient;
613  int dx = m_size.x / 2;
614  int dy = m_size.y / 2;
615 
616  wxPoint padShapePos = ShapePos(); // Note: for pad having a shape offset,
617  // the pad position is NOT the shape position
618 
619  switch( GetShape() )
620  {
621  case PAD_SHAPE_CIRCLE:
622  case PAD_SHAPE_OVAL:
623  if( dx == dy )
624  {
625  TransformCircleToPolygon( aCornerBuffer, padShapePos, dx + aClearanceValue, aError,
626  aErrorLoc );
627  }
628  else
629  {
630  int half_width = std::min( dx, dy );
631  wxPoint delta( dx - half_width, dy - half_width );
632 
633  RotatePoint( &delta, angle );
634 
635  TransformOvalToPolygon( aCornerBuffer, padShapePos - delta, padShapePos + delta,
636  ( half_width + aClearanceValue ) * 2, aError, aErrorLoc );
637  }
638 
639  break;
640 
641  case PAD_SHAPE_TRAPEZOID:
642  case PAD_SHAPE_RECT:
643  {
644  int ddx = GetShape() == PAD_SHAPE_TRAPEZOID ? m_deltaSize.x / 2 : 0;
645  int ddy = GetShape() == PAD_SHAPE_TRAPEZOID ? m_deltaSize.y / 2 : 0;
646 
647  wxPoint corners[4];
648  corners[0] = wxPoint( -dx - ddy, dy + ddx );
649  corners[1] = wxPoint( dx + ddy, dy - ddx );
650  corners[2] = wxPoint( dx - ddy, -dy + ddx );
651  corners[3] = wxPoint( -dx + ddy, -dy - ddx );
652 
653  SHAPE_POLY_SET outline;
654  outline.NewOutline();
655 
656  for( wxPoint& corner : corners )
657  {
658  RotatePoint( &corner, angle );
659  corner += padShapePos;
660  outline.Append( corner.x, corner.y );
661  }
662 
663  if( aClearanceValue )
664  {
665  int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
666  pad_min_seg_per_circle_count );
667  int clearance = aClearanceValue;
668 
669  if( aErrorLoc == ERROR_OUTSIDE )
670  clearance += GetCircleToPolyCorrection( aError );
671 
672  outline.Inflate( clearance, numSegs );
673  }
674 
675  aCornerBuffer.Append( outline );
676  }
677  break;
678 
680  case PAD_SHAPE_ROUNDRECT:
681  {
682  int radius = GetRoundRectCornerRadius();
683  wxSize shapesize( m_size );
684  bool doChamfer = GetShape() == PAD_SHAPE_CHAMFERED_RECT;
685 
686  double chamferRatio = doChamfer ? GetChamferRectRatio() : 0.0;
687 
688  if( aClearanceValue )
689  {
690  radius += aClearanceValue;
691  shapesize.x += aClearanceValue * 2;
692  shapesize.y += aClearanceValue * 2;
693 
694  // The chamfer position (the 45 deg line on corner) must be
695  // offsetted by aClearanceValue from the base shape chamfer pos
696  // So we recalculate the chamferRatio to do that
697  //
698  // the chamfered shape is square with widet = w, and a corner dist from center
699  // is w*1.414 / 2 = w*0.707
700  // the distance from corner to chamfer line is ch = chamfer_size/707
701  // the distance from center to chamfer line is
702  // d = w*707 - ch/707
703  // so we have:
704  // base shape: d1 = w1*707 - ch1/707 = 0.707 * ( w1 - w1*chamferRatio)
705  // shape with clearance: d2 = w2*707 - ch2/707 = d1 + aClearanceValue
706  const double rootsq_2 = 1.41421356237/2;
707  int d1 = rootsq_2 * std::min( m_size.x, m_size.y ) * ( 1 - GetChamferRectRatio() );
708  int d2 = d1 + aClearanceValue;
709  // d2 = 0.707 * w2 * ( 1 - chamferRatio2 )
710  // 1 - d2 / ( 0.707 * w2 ) = chamferRatio2
711  chamferRatio = 1.0 - d2 / ( rootsq_2 * std::min( shapesize.x, shapesize.y ) );
712 
713  // Ensure chamferRatio = 0.0 ... 0.5
714  if( chamferRatio < 0.0 )
715  chamferRatio = 0.0;
716 
717  if( chamferRatio > 0.5 )
718  chamferRatio = 0.5;
719  }
720 
721  SHAPE_POLY_SET outline;
722  TransformRoundChamferedRectToPolygon( outline, padShapePos, shapesize, angle, radius,
723  chamferRatio,
724  doChamfer ? GetChamferPositions() : 0,
725  aError, aErrorLoc );
726 
727  aCornerBuffer.Append( outline );
728  }
729  break;
730 
731  case PAD_SHAPE_CUSTOM:
732  {
733  SHAPE_POLY_SET outline;
734  MergePrimitivesAsPolygon( &outline, aLayer );
735  outline.Rotate( -DECIDEG2RAD( m_orient ) );
736  outline.Move( VECTOR2I( m_pos ) );
737 
738  if( aClearanceValue )
739  {
740  int numSegs = std::max( GetArcToSegmentCount( aClearanceValue, aError, 360.0 ),
741  pad_min_seg_per_circle_count );
742  int clearance = aClearanceValue;
743 
744  if( aErrorLoc == ERROR_OUTSIDE )
745  clearance += GetCircleToPolyCorrection( aError );
746 
747  outline.Inflate( clearance, numSegs );
750  }
751 
752  aCornerBuffer.Append( outline );
753  }
754  break;
755 
756  default:
757  wxFAIL_MSG( "PAD::TransformShapeWithClearanceToPolygon no implementation for "
759  break;
760  }
761 }
762 
763 
764 
765 bool PAD::TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
766  int aError, ERROR_LOC aErrorLoc ) const
767 {
768  wxSize drillsize = GetDrillSize();
769 
770  if( !drillsize.x || !drillsize.y )
771  return false;
772 
773  const SHAPE_SEGMENT* seg = GetEffectiveHoleShape();
774 
775  TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A, (wxPoint) seg->GetSeg().B,
776  seg->GetWidth() + aInflateValue * 2, aError, aErrorLoc );
777 
778  return true;
779 }
780 
781 
783  PCB_LAYER_ID aLayer, int aClearance, int aError,
784  ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
785 {
786  wxASSERT_MSG( !aIgnoreLineWidth, "IgnoreLineWidth has no meaning for zones." );
787 
788  if( !m_FilledPolysList.count( aLayer ) )
789  return;
790 
791  aCornerBuffer = m_FilledPolysList.at( aLayer );
792 
793  int numSegs = GetArcToSegmentCount( aClearance, aError, 360.0 );
794  aCornerBuffer.Inflate( aClearance, numSegs );
796 }
797 
798 
800  PCB_LAYER_ID aLayer, int aClearance,
801  int aError, ERROR_LOC aErrorLoc,
802  bool aIgnoreLineWidth ) const
803 {
804  wxASSERT_MSG( !aIgnoreLineWidth, "IgnoreLineWidth has no meaning for dimensions." );
805 
806  for( const std::shared_ptr<SHAPE>& shape : m_shapes )
807  {
808  const SHAPE_CIRCLE* circle = dynamic_cast<const SHAPE_CIRCLE*>( shape.get() );
809  const SHAPE_SEGMENT* seg = dynamic_cast<const SHAPE_SEGMENT*>( shape.get() );
810 
811  if( circle )
812  {
813  TransformCircleToPolygon( aCornerBuffer, (wxPoint) circle->GetCenter(),
814  circle->GetRadius() + m_lineThickness / 2 + aClearance,
815  aError, aErrorLoc );
816  }
817  else if( seg )
818  {
819  TransformOvalToPolygon( aCornerBuffer, (wxPoint) seg->GetSeg().A,
820  (wxPoint) seg->GetSeg().B, m_lineThickness + 2 * aClearance,
821  aError, aErrorLoc );
822  }
823  else
824  {
825  wxFAIL_MSG( "DIMENSION::TransformShapeWithClearanceToPolygon unexpected shape type." );
826  }
827  }
828 }
829 
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:248
wxPoint GetArcEnd() const
Definition: pcb_shape.cpp:373
bool IsPolyShapeValid() const
Definition: pcb_shape.cpp:1223
bool IsFilled() const
Definition: pcb_shape.h:96
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...
wxPoint m_end
Definition: pcb_shape.h:49
wxPoint m_Start
Line start point.
Definition: track.h:256
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:206
bool IsMirrored() const
Definition: eda_text.h:196
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
ZONES & Zones()
Definition: board.h:309
int GetRadius() const
Definition: shape_circle.h:102
static std::string PAD_SHAPE_T_asString(PAD_SHAPE_T a)
Definition: pad_shapes.h:46
static void addTextSegmToPoly(int x0, int y0, int xf, int yf, void *aData)
wxSize m_deltaSize
Definition: pad.h:732
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
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...
const wxPoint & GetStart() const
Definition: track.h:116
PCB_SHAPE_TYPE_T m_shape
Definition: pcb_shape.h:52
void GetPoly(std::vector< wxPoint > &aOutput, int aMinSegLen=0)
Convert a Bezier curve to a polygon.
bool IsVisible() const
Definition: eda_text.h:193
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
Definition: pcb_shape.h:201
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:970
EDA_RECT GetTextBox(int aLine=-1, bool aInvertY=false) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition: eda_text.cpp:223
polygon (not yet used for tracks, but could be in microwave apps)
Definition: board_item.h:54
double GetOrientation() const
Definition: footprint.h:186
static void isPlated(LIBEVAL::CONTEXT *aCtx, void *self)
double GetTextAngle() const
Definition: eda_text.h:181
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aError, ERROR_LOC aErrorLoc)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
usual segment : line with rounded ends
Definition: board_item.h:50
static LIB_PART * dummy()
Used to draw a dummy shape when a LIB_PART is not found in library.
Definition: sch_symbol.cpp:69
const SHAPE_SEGMENT * GetEffectiveHoleShape() const
Return a SHAPE object representing the pad's hole.
Definition: pcbnew/pad.cpp:286
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: board.h:591
Arcs (with rounded ends)
Definition: board_item.h:52
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
PAD_SHAPE_T GetShape() const
Definition: pad.h:169
wxPoint m_pos
Definition: pad.h:673
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
const VECTOR2I GetCenter() const
Definition: shape_circle.h:107
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:228
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Perform outline inflation/deflation.
like PAD_PTH, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:85
segment with non rounded ends
Definition: board_item.h:51
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:203
const SEG & GetSeg() const
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:157
int m_Width
Thickness of track, or via diameter.
Definition: track.h:255
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:119
wxPoint GetArcStart() const
Definition: pcb_shape.h:179
FP_TEXT & Value()
read/write accessors:
Definition: footprint.h:459
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...
bool IsItalic() const
Definition: eda_text.h:187
FP_TEXT & Reference()
Definition: footprint.h:460
void TransformOvalToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
convert a oblong shape to a polygon, using multiple segments It is similar to TransformRoundedEndsSeg...
#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:53
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.
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
Definition: pcb_shape.cpp:1206
const wxSize & GetDrillSize() const
Definition: pad.h:242
wxPoint ShapePos() const
Definition: pcbnew/pad.cpp:657
PCB_LAYER_ID
A quick note on layer IDs:
const wxPoint & GetMid() const
Definition: track.h:292
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:205
int GetMinThickness() const
Definition: zone.h:247
#define NULL
void Move(const VECTOR2I &aVector) override
Represent a set of closed polygons.
const wxPoint GetOrigin() const
Definition: eda_rect.h:106
TSEGM_2_POLY_PRMS prms
const wxSize & GetTextSize() const
Definition: eda_text.h:245
static wxString PCB_SHAPE_TYPE_T_asString(PCB_SHAPE_TYPE_T a)
Definition: board_item.h:59
wxPoint m_End
Line end point.
Definition: track.h:257
wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.cpp:341
virtual BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Definition: board_item.cpp:46
int GetRight() const
Definition: eda_rect.h:116
double m_orient
Definition: pad.h:743
void ConvertBrdLayerToPolygonalContours(PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aOutlines)
Build a set of polygons which are the outlines of copper items (pads, tracks, vias,...
DRAWINGS & GraphicalItems()
Definition: footprint.h:167
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
ZONE handles 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
Function TransformSolidAreasShapesToPolygon Convert solid areas full shapes to polygon set (the full ...
DRAWINGS m_drawings
Definition: board.h:201
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.
bool IsMultilineAllowed() const
Definition: eda_text.h:203
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
Definition: string.cpp:807
void GRText(wxDC *aDC, const wxPoint &aPos, 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)
Function GRText Draw a graphic text (like footprint texts)
Definition: gr_text.cpp:131
int GetRoundRectCornerRadius() const
Definition: pcbnew/pad.cpp:237
wxSize m_size
Definition: pad.h:707
wxPoint m_start
Definition: pcb_shape.h:48
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.
Bezier curves to polygon converter.
Definition: bezier_curves.h:36
double GetChamferRectRatio() const
Definition: pad.h:524
int m_width
Definition: pcb_shape.h:46
FOOTPRINT * GetParentFootprint() const
Function GetParentFootprint returns a pointer to the parent footprint, or NULL if PCB_SHAPE does not ...
Definition: pcb_shape.cpp:478
void MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon, PCB_LAYER_ID aLayer) const
Merge all basic shapes to a SHAPE_POLY_SET.
Definition: track.h:262
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)
std::vector< std::shared_ptr< SHAPE > > m_shapes
Definition: dimension.h:301
VECTOR2I A
Definition: seg.h:49
Handle the component boundary box.
Definition: eda_rect.h:42
double DECIDEG2RAD(double deg)
Definition: trigo.h:235
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aCornerBuffer, wxPoint aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc)
Function TransformCircleToPolygon convert a circle to a polygon, using multiple straight lines.
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Perform outline inflation/deflation, using round corners.
wxPoint GetPosition() const override
Definition: footprint.h:182
const wxPoint & GetEnd() const
Definition: track.h:113
void GetLinePositions(std::vector< wxPoint > &aPositions, int aLineCount) const
Populate aPositions with the position of each line of a multiline text, according to the vertical jus...
Definition: eda_text.cpp:424
bool IsCopperLayer(LAYER_NUM aLayerId)
Tests whether a layer is a copper layer.
ring
Definition: board_item.h:53
int GetChamferPositions() const
Definition: pad.h:534
const wxPoint & GetTextPos() const
Definition: eda_text.h:254
wxPoint m_bezierC1
Definition: pcb_shape.h:54
FOOTPRINTS m_footprints
Definition: board.h:202
int m_lineThickness
Thickness used for all graphics in the dimension.
Definition: dimension.h:288
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
wxPoint GetArcMid() const
Definition: pcb_shape.cpp:391
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 zone shape to a closed polygon Used in fill...
Definition: pad.h:60
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 draw segment to a closed polygon Used in fi...
virtual wxString GetShownText(int aDepth=0) const override
Return the string actually shown after processing of the base text.
Definition: fp_text.cpp:410
wxPoint m_bezierC2
Definition: pcb_shape.h:55
int GetWidth() const
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
Bezier Curve.
Definition: board_item.h:55
static constexpr int Millimeter2iu(double mm)
std::map< PCB_LAYER_ID, SHAPE_POLY_SET > m_FilledPolysList
Definition: zone.h:936
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:173
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
PADS m_pads
Definition: footprint.h:680
void TransformArcToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aStart, wxPoint aMid, wxPoint aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc)
Function TransformArcToPolygon Creates a polygon from an Arc Convert arcs to multiple straight segmen...
Definition: track.h:83
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
Definition: eda_rect.cpp:363
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
void TransformRingToPolygon(SHAPE_POLY_SET &aCornerBuffer, wxPoint aCentre, int aRadius, int aWidth, int aError, ERROR_LOC aErrorLoc)
Function TransformRingToPolygon Creates a polygon from a ring Convert arcs to multiple straight segme...
bool GetFilledPolysUseThickness() const
Definition: zone.h:712
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:98
VECTOR2I B
Definition: seg.h:50