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