KiCad PCB EDA Suite
zones_convert_brd_items_to_polygons_with_Boost.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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 1992-2016 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 /* Functions to convert some board items to polygons
26  * (pads, tracks ..)
27  * This is used to calculate filled areas in copper zones.
28  * Filled areas are areas remainder of the full zone area after removed all polygons
29  * calculated from these items shapes and the clearance area
30  *
31  * Important note:
32  * Because filled areas must have a minimum thickness to match with Design rule, they are
33  * draw in 2 step:
34  * 1 - filled polygons are drawn
35  * 2 - polygon outlines are drawn with a "minimum thickness width" ( or with a minimum
36  * thickness pen )
37  * So outlines of filled polygons are calculated with the constraint they match with clearance,
38  * taking in account outlines have thickness
39  * This ensures:
40  * - areas meet the minimum thickness requirement.
41  * - shapes are smoothed.
42  */
43 
44 // Polygon calculations can use fast mode or force strickly simple polygons after calculations
45 // Forcing strickly simple polygons is time consuming, and we have not see issues in fast mode
46 // so we use fast mode when possible (intermediate calculations)
47 // (choice is SHAPE_POLY_SET::PM_STRICTLY_SIMPLE or SHAPE_POLY_SET::PM_FAST)
48 #define POLY_CALC_MODE SHAPE_POLY_SET::PM_FAST
49 
50 #include <cmath>
51 #include <sstream>
52 
53 #include <fctsys.h>
54 #include <wxPcbStruct.h>
55 #include <trigo.h>
56 
57 #include <class_board.h>
58 #include <class_module.h>
59 #include <class_track.h>
60 #include <class_edge_mod.h>
61 #include <class_drawsegment.h>
62 #include <class_pcb_text.h>
63 #include <class_zone.h>
64 #include <project.h>
65 
66 #include <pcbnew.h>
67 #include <zones.h>
69 
71 #include <geometry/shape_file_io.h>
72 
73 /* DEBUG OPTION:
74  * To emit zone data to a file when filling zones for the debugging purposes,
75  * set this 'true' and build.
76  */
77 static const bool g_DumpZonesWhenFilling = false;
78 
80  BOARD* aPcb, ZONE_CONTAINER* aZone,
81  double aArcCorrection,
82  double aRoundPadThermalRotation);
83 
84 extern void Test_For_Copper_Island_And_Remove( BOARD* aPcb,
85  ZONE_CONTAINER* aZone_container );
86 
87 extern void CreateThermalReliefPadPolygon( SHAPE_POLY_SET& aCornerBuffer,
88  D_PAD& aPad,
89  int aThermalGap,
90  int aCopperThickness,
91  int aMinThicknessValue,
92  int aCircleToSegmentsCount,
93  double aCorrectionFactor,
94  double aThermalRot );
95 
96 // Local Variables:
97 static double s_thermalRot = 450; // angle of stubs in thermal reliefs for round pads
98 
100 {
101  int segsPerCircle;
102  double correctionFactor;
103 
104  // Set the number of segments in arc approximations
106  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
107  else
108  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
109 
110  /* calculates the coeff to compensate radius reduction of holes clearance
111  * due to the segment approx.
112  * For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2)
113  * s_Correction is 1 /cos( PI/s_CircleToSegmentsCount )
114  */
115  correctionFactor = 1.0 / cos( M_PI / (double) segsPerCircle );
116 
117  aFeatures.RemoveAllContours();
118 
119  int outline_half_thickness = m_ZoneMinThickness / 2;
120 
121  int zone_clearance = std::max( m_ZoneClearance, GetClearance() );
122  zone_clearance += outline_half_thickness;
123 
124  /* store holes (i.e. tracks and pads areas as polygons outlines)
125  * in a polygon list
126  */
127 
128  /* items ouside the zone bounding box are skipped
129  * the bounding box is the zone bounding box + the biggest clearance found in Netclass list
130  */
131  EDA_RECT item_boundingbox;
132  EDA_RECT zone_boundingbox = GetBoundingBox();
133  int biggest_clearance = aPcb->GetDesignSettings().GetBiggestClearanceValue();
134  biggest_clearance = std::max( biggest_clearance, zone_clearance );
135  zone_boundingbox.Inflate( biggest_clearance );
136 
137  /*
138  * First : Add pads. Note: pads having the same net as zone are left in zone.
139  * Thermal shapes will be created later if necessary
140  */
141  int item_clearance;
142 
143  /* Use a dummy pad to calculate hole clerance when a pad is not on all copper layers
144  * and this pad has a hole
145  * This dummy pad has the size and shape of the hole
146  * Therefore, this dummy pad is a circle or an oval.
147  * A pad must have a parent because some functions expect a non null parent
148  * to find the parent board, and some other data
149  */
150  MODULE dummymodule( aPcb ); // Creates a dummy parent
151  D_PAD dummypad( &dummymodule );
152 
153  for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
154  {
155  D_PAD* nextpad;
156 
157  for( D_PAD* pad = module->Pads(); pad != NULL; pad = nextpad )
158  {
159  nextpad = pad->Next(); // pad pointer can be modified by next code, so
160  // calculate the next pad here
161 
162  if( !pad->IsOnLayer( GetLayer() ) )
163  {
164  /* Test for pads that are on top or bottom only and have a hole.
165  * There are curious pads but they can be used for some components that are
166  * inside the board (in fact inside the hole. Some photo diodes and Leds are
167  * like this)
168  */
169  if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
170  continue;
171 
172  // Use a dummy pad to calculate a hole shape that have the same dimension as
173  // the pad hole
174  dummypad.SetSize( pad->GetDrillSize() );
175  dummypad.SetOrientation( pad->GetOrientation() );
176  dummypad.SetShape( pad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG ?
178  dummypad.SetPosition( pad->GetPosition() );
179 
180  pad = &dummypad;
181  }
182 
183  // Note: netcode <=0 means not connected item
184  if( ( pad->GetNetCode() != GetNetCode() ) || ( pad->GetNetCode() <= 0 ) )
185  {
186  item_clearance = pad->GetClearance() + outline_half_thickness;
187  item_boundingbox = pad->GetBoundingBox();
188  item_boundingbox.Inflate( item_clearance );
189 
190  if( item_boundingbox.Intersects( zone_boundingbox ) )
191  {
192  int clearance = std::max( zone_clearance, item_clearance );
193  pad->TransformShapeWithClearanceToPolygon( aFeatures,
194  clearance,
195  segsPerCircle,
196  correctionFactor );
197  }
198 
199  continue;
200  }
201 
202  // Pads are removed from zone if the setup is PAD_ZONE_CONN_NONE
203  if( GetPadConnection( pad ) == PAD_ZONE_CONN_NONE )
204  {
205  int gap = zone_clearance;
206  int thermalGap = GetThermalReliefGap( pad );
207  gap = std::max( gap, thermalGap );
208  item_boundingbox = pad->GetBoundingBox();
209  item_boundingbox.Inflate( gap );
210 
211  if( item_boundingbox.Intersects( zone_boundingbox ) )
212  {
213  pad->TransformShapeWithClearanceToPolygon( aFeatures,
214  gap,
215  segsPerCircle,
216  correctionFactor );
217  }
218  }
219  }
220  }
221 
222  /* Add holes (i.e. tracks and vias areas as polygons outlines)
223  * in cornerBufferPolysToSubstract
224  */
225  for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
226  {
227  if( !track->IsOnLayer( GetLayer() ) )
228  continue;
229 
230  if( track->GetNetCode() == GetNetCode() && (GetNetCode() != 0) )
231  continue;
232 
233  item_clearance = track->GetClearance() + outline_half_thickness;
234  item_boundingbox = track->GetBoundingBox();
235 
236  if( item_boundingbox.Intersects( zone_boundingbox ) )
237  {
238  int clearance = std::max( zone_clearance, item_clearance );
239  track->TransformShapeWithClearanceToPolygon( aFeatures,
240  clearance,
241  segsPerCircle,
242  correctionFactor );
243  }
244  }
245 
246  /* Add module edge items that are on copper layers
247  * Pcbnew allows these items to be on copper layers in microwave applictions
248  * This is a bad thing, but must be handled here, until a better way is found
249  */
250  for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
251  {
252  for( BOARD_ITEM* item = module->GraphicalItems(); item; item = item->Next() )
253  {
254  if( !item->IsOnLayer( GetLayer() ) && !item->IsOnLayer( Edge_Cuts ) )
255  continue;
256 
257  if( item->Type() != PCB_MODULE_EDGE_T )
258  continue;
259 
260  item_boundingbox = item->GetBoundingBox();
261 
262  if( item_boundingbox.Intersects( zone_boundingbox ) )
263  {
264  ( (EDGE_MODULE*) item )->TransformShapeWithClearanceToPolygon(
265  aFeatures, zone_clearance,
266  segsPerCircle, correctionFactor );
267  }
268  }
269  }
270 
271  // Add graphic items (copper texts) and board edges
272  for( BOARD_ITEM* item = aPcb->m_Drawings; item; item = item->Next() )
273  {
274  if( item->GetLayer() != GetLayer() && item->GetLayer() != Edge_Cuts )
275  continue;
276 
277  switch( item->Type() )
278  {
279  case PCB_LINE_T:
280  ( (DRAWSEGMENT*) item )->TransformShapeWithClearanceToPolygon(
281  aFeatures,
282  zone_clearance, segsPerCircle, correctionFactor );
283  break;
284 
285  case PCB_TEXT_T:
286  ( (TEXTE_PCB*) item )->TransformBoundingBoxWithClearanceToPolygon(
287  aFeatures, zone_clearance );
288  break;
289 
290  default:
291  break;
292  }
293  }
294 
295  // Add zones outlines having an higher priority and keepout
296  for( int ii = 0; ii < GetBoard()->GetAreaCount(); ii++ )
297  {
298  ZONE_CONTAINER* zone = GetBoard()->GetArea( ii );
299  if( zone->GetLayer() != GetLayer() )
300  continue;
301 
302  if( !zone->GetIsKeepout() && zone->GetPriority() <= GetPriority() )
303  continue;
304 
305  if( zone->GetIsKeepout() && ! zone->GetDoNotAllowCopperPour() )
306  continue;
307 
308  // A highter priority zone or keepout area is found: remove this area
309  item_boundingbox = zone->GetBoundingBox();
310  if( !item_boundingbox.Intersects( zone_boundingbox ) )
311  continue;
312 
313  // Add the zone outline area.
314  // However if the zone has the same net as the current zone,
315  // do not add any clearance.
316  // the zone will be connected to the current zone, but filled areas
317  // will use different parameters (clearance, thermal shapes )
318  bool same_net = GetNetCode() == zone->GetNetCode();
319  bool use_net_clearance = true;
320  int min_clearance = zone_clearance;
321 
322  // Do not forget to make room to draw the thick outlines
323  // of the hole created by the area of the zone to remove
324  int holeclearance = zone->GetClearance() + outline_half_thickness;
325 
326  // The final clearance is obviously the max value of each zone clearance
327  min_clearance = std::max( min_clearance, holeclearance );
328 
329  if( zone->GetIsKeepout() || same_net )
330  {
331  // Just take in account the fact the outline has a thickness, so
332  // the actual area to substract is inflated to take in account this fact
333  min_clearance = outline_half_thickness;
334  use_net_clearance = false;
335  }
336 
338  aFeatures,
339  min_clearance, use_net_clearance );
340  }
341 
342  // Remove thermal symbols
343  for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
344  {
345  for( D_PAD* pad = module->Pads(); pad != NULL; pad = pad->Next() )
346  {
347  // Rejects non-standard pads with tht-only thermal reliefs
349  && pad->GetAttribute() != PAD_ATTRIB_STANDARD )
350  continue;
351 
354  continue;
355 
356  if( !pad->IsOnLayer( GetLayer() ) )
357  continue;
358 
359  if( pad->GetNetCode() != GetNetCode() )
360  continue;
361  item_boundingbox = pad->GetBoundingBox();
362  int thermalGap = GetThermalReliefGap( pad );
363  item_boundingbox.Inflate( thermalGap, thermalGap );
364 
365  if( item_boundingbox.Intersects( zone_boundingbox ) )
366  {
368  *pad, thermalGap,
371  segsPerCircle,
372  correctionFactor, s_thermalRot );
373  }
374  }
375  }
376 
377 }
378 
379 
411 {
412  int segsPerCircle;
413  double correctionFactor;
414  int outline_half_thickness = m_ZoneMinThickness / 2;
415 
416 
417  std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO(
418  g_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) );
419 
420  // Set the number of segments in arc approximations
422  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF;
423  else
424  segsPerCircle = ARC_APPROX_SEGMENTS_COUNT_LOW_DEF;
425 
426  /* calculates the coeff to compensate radius reduction of holes clearance
427  * due to the segment approx.
428  * For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2)
429  * s_Correction is 1 /cos( PI/s_CircleToSegmentsCount )
430  */
431  correctionFactor = 1.0 / cos( M_PI / (double) segsPerCircle );
432 
433  CPOLYGONS_LIST tmp;
434 
436  dumper->BeginGroup("clipper-zone");
437 
438  SHAPE_POLY_SET solidAreas = *m_smoothedPoly;
439 
440  solidAreas.Inflate( -outline_half_thickness, segsPerCircle );
441  solidAreas.Simplify( POLY_CALC_MODE );
442 
443  SHAPE_POLY_SET holes;
444 
446  dumper->Write( &solidAreas, "solid-areas" );
447 
448  tmp.RemoveAllContours();
449  buildFeatureHoleList( aPcb, holes );
450 
452  dumper->Write( &holes, "feature-holes" );
453 
454  holes.Simplify( POLY_CALC_MODE );
455 
457  dumper->Write( &holes, "feature-holes-postsimplify" );
458 
459  // Generate the filled areas (currently, without thermal shapes, which will
460  // be created later).
461  // Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to generate strictly simple polygons
462  // needed by Gerber files and Fracture()
464 
466  dumper->Write( &solidAreas, "solid-areas-minus-holes" );
467 
468  SHAPE_POLY_SET areas_fractured = solidAreas;
469  areas_fractured.Fracture( POLY_CALC_MODE );
470 
472  dumper->Write( &areas_fractured, "areas_fractured" );
473 
474  m_FilledPolysList = areas_fractured;
475 
476  // Remove insulated islands:
477  if( GetNetCode() > 0 )
479 
480  SHAPE_POLY_SET thermalHoles;
481 
482  // Test thermal stubs connections and add polygons to remove unconnected stubs.
483  // (this is a refinement for thermal relief shapes)
484  if( GetNetCode() > 0 )
485  BuildUnconnectedThermalStubsPolygonList( thermalHoles, aPcb, this,
486  correctionFactor, s_thermalRot );
487 
488  // remove copper areas corresponding to not connected stubs
489  if( !thermalHoles.IsEmpty() )
490  {
491  thermalHoles.Simplify( POLY_CALC_MODE );
492  // Remove unconnected stubs. Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to
493  // generate strictly simple polygons
494  // needed by Gerber files and Fracture()
495  solidAreas.BooleanSubtract( thermalHoles, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
496 
498  dumper->Write( &thermalHoles, "thermal-holes" );
499 
500  // put these areas in m_FilledPolysList
501  SHAPE_POLY_SET th_fractured = solidAreas;
502  th_fractured.Fracture( POLY_CALC_MODE );
503 
505  dumper->Write ( &th_fractured, "th_fractured" );
506 
507  m_FilledPolysList = th_fractured;
508 
509  if( GetNetCode() > 0 )
511  }
512 
514  dumper->EndGroup();
515 }
516 
518 {
519 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
#define ARC_APPROX_SEGMENTS_COUNT_HIGHT_DEF
Definition: pcbnew.h:42
int m_ZoneClearance
Clearance value in internal units.
Definition: class_zone.h:749
Class SHAPE_FILE_IO.
Definition: shape_file_io.h:38
TEXTE_PCB class definition.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:655
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:349
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
#define ARC_APPROX_SEGMENTS_COUNT_LOW_DEF
Definition: pcbnew.h:41
Class BOARD to handle a board.
MODULE * Next() const
Definition: class_module.h:99
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:169
Classes to handle copper zones.
void buildFeatureHoleList(BOARD *aPcb, SHAPE_POLY_SET &aFeatures)
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:466
void TransformOutlinesShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance)
Function TransformOutlinesShapeWithClearanceToPolygon Convert the outlines shape to a polygon with no...
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:106
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in 1/10000 inches.
Definition: class_zone.cpp:609
Functions relatives to tracks, vias and segments used to fill zones.
Pads are not covered.
Definition: zones.h:57
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:654
BOARD_ITEM * Next() const
SHAPE_POLY_SET * m_smoothedPoly
Definition: class_zone.h:726
int m_ArcToSegmentsCount
The number of segments to convert a circle to a polygon.
Definition: class_zone.h:754
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:814
void Test_For_Copper_Island_And_Remove(BOARD *aPcb, ZONE_CONTAINER *aZone_container)
void Inflate(int aFactor, int aCircleSegmentsCount)
Performs outline inflation/deflation, using round corners.
void TestForCopperIslandAndRemoveInsulatedIslands(BOARD *aPcb)
Function TestForCopperIslandAndRemoveInsulatedIslands Remove insulated copper islands found in m_Fill...
Class SHAPE_POLY_SET.
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:457
D_PAD * Next() const
Definition: class_pad.h:106
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:530
void SetSize(const wxSize &aSize)
Definition: class_pad.h:181
DLIST< BOARD_ITEM > m_Drawings
Definition: class_board.h:242
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1051
SHAPE_POLY_SET m_FilledPolysList
Definition: class_zone.h:788
Thermal relief only for THT pads.
Definition: zones.h:60
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
void AddClearanceAreasPolygonsToPolysList_NG(BOARD *aPcb)
Function AddClearanceAreasPolygonsToPolysList Supports a min thickness area constraint.
int GetNetCode() const
Function GetNetCode.
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
void BuildUnconnectedThermalStubsPolygonList(SHAPE_POLY_SET &aCornerBuffer, BOARD *aPcb, ZONE_CONTAINER *aZone, double aArcCorrection, double aRoundPadThermalRotation)
Function BuildUnconnectedThermalStubsPolygonList Creates a set of polygons corresponding to stubs cre...
int m_ZoneMinThickness
Minimum thickness value in filled areas.
Definition: class_zone.h:750
TRACK * Next() const
Definition: class_track.h:98
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:1022
Class to handle a graphic segment.
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:166
DLIST< MODULE > m_Modules
Definition: class_board.h:243
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
void RemoveAllContours(void)
Definition: PolyLine.h:143
Class EDA_RECT handles the component boundary box.
Usual pad.
Definition: pad_shapes.h:58
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_pad.cpp:506
void SetShape(PAD_SHAPE_T aShape)
Definition: class_pad.h:167
void SetOrientation(double aAngle)
Function SetOrientation sets the rotation angle of the pad.
Definition: class_pad.cpp:357
virtual BOARD * GetBoard() const
Function GetBoard returns the BOARD in which this BOARD_ITEM resides, or NULL if none.
static const bool g_DumpZonesWhenFilling
DLIST< TRACK > m_Track
Definition: class_board.h:244
void AddClearanceAreasPolygonsToPolysList(BOARD *aPcb)
Function AddClearanceAreasPolygonsToPolysList Add non copper areas polygons (pads and tracks with cle...
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp ...
Module description (excepted pads)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
CPOLYGONS_LIST handle a list of contours (polygons corners).
Definition: PolyLine.h:114
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:119
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
Use thermal relief for pads.
Definition: zones.h:58
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
void CreateThermalReliefPadPolygon(SHAPE_POLY_SET &aCornerBuffer, D_PAD &aPad, int aThermalGap, int aCopperThickness, int aMinThicknessValue, int aCircleToSegmentsCount, double aCorrectionFactor, double aThermalRot)
Function CreateThermalReliefPadPolygon Add holes around a pad to create a thermal relief copper thick...