KiCad PCB EDA Suite
zones_convert_to_polygons_aux_functions.cpp
Go to the documentation of this file.
1 
5 /*
6  * This program source code file is part of KiCad, a free EDA CAD application.
7  *
8  * Copyright (C) 2013 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
9  * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, you may find one here:
23  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
24  * or you may search the http://www.gnu.org website for the version 2 license,
25  * or you may write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
27  */
28 
29 #include <fctsys.h>
30 #include <PolyLine.h>
31 #include <wxPcbStruct.h>
32 #include <trigo.h>
33 
34 #include <class_board.h>
35 #include <class_module.h>
36 #include <class_zone.h>
37 
38 #include <pcbnew.h>
39 #include <zones.h>
40 
41  /* Function TransformOutlinesShapeWithClearanceToPolygon
42  * Convert the zone filled areas polygons to polygons
43  * inflated (optional) by max( aClearanceValue, the zone clearance)
44  * and copy them in aCornerBuffer
45  * param aClearanceValue = the clearance around polygons
46  * param aAddClearance = true to add a clearance area to the polygon
47  * false to create the outline polygon.
48  */
50  SHAPE_POLY_SET& aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance )
51 {
52  // Creates the zone outline polygon (with holes if any)
53  SHAPE_POLY_SET polybuffer;
54  BuildFilledSolidAreasPolygons( NULL, &polybuffer );
55 
56  // add clearance to outline
57  int clearance = aMinClearanceValue;
58 
59  if( aUseNetClearance && IsOnCopperLayer() )
60  {
61  clearance = GetClearance();
62  if( aMinClearanceValue > clearance )
63  clearance = aMinClearanceValue;
64  }
65 
66  // Calculate the polygon with clearance
67  // holes are linked to the main outline, so only one polygon is created.
68  if( clearance )
69  polybuffer.Inflate( clearance, 16 );
70 
71  polybuffer.Fracture( SHAPE_POLY_SET::PM_FAST );
72  aCornerBuffer.Append( polybuffer );
73 }
74 
75 
76 
89  BOARD* aPcb,
90  ZONE_CONTAINER* aZone,
91  double aArcCorrection,
92  double aRoundPadThermalRotation )
93 {
94  std::vector<wxPoint> corners_buffer; // a local polygon buffer to store one stub
95  corners_buffer.reserve( 4 );
96  wxPoint ptTest[4];
97 
98  int zone_clearance = aZone->GetZoneClearance();
99 
100  EDA_RECT item_boundingbox;
101  EDA_RECT zone_boundingbox = aZone->GetBoundingBox();
102  int biggest_clearance = aPcb->GetDesignSettings().GetBiggestClearanceValue();
103  biggest_clearance = std::max( biggest_clearance, zone_clearance );
104  zone_boundingbox.Inflate( biggest_clearance );
105 
106  // half size of the pen used to draw/plot zones outlines
107  int pen_radius = aZone->GetMinThickness() / 2;
108 
109  for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
110  {
111  for( D_PAD* pad = module->PadsList(); pad != NULL; pad = pad->Next() )
112  {
113  // Rejects non-standard pads with tht-only thermal reliefs
114  if( aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_THT_THERMAL
115  && pad->GetAttribute() != PAD_ATTRIB_STANDARD )
116  continue;
117 
118  if( aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THERMAL
119  && aZone->GetPadConnection( pad ) != PAD_ZONE_CONN_THT_THERMAL )
120  continue;
121 
122  // check
123  if( !pad->IsOnLayer( aZone->GetLayer() ) )
124  continue;
125 
126  if( pad->GetNetCode() != aZone->GetNetCode() )
127  continue;
128 
129  // Calculate thermal bridge half width
130  int thermalBridgeWidth = aZone->GetThermalReliefCopperBridge( pad )
131  - aZone->GetMinThickness();
132  if( thermalBridgeWidth <= 0 )
133  continue;
134 
135  // we need the thermal bridge half width
136  // with a small extra size to be sure we create a stub
137  // slightly larger than the actual stub
138  thermalBridgeWidth = ( thermalBridgeWidth + 4 ) / 2;
139 
140  int thermalReliefGap = aZone->GetThermalReliefGap( pad );
141 
142  item_boundingbox = pad->GetBoundingBox();
143  item_boundingbox.Inflate( thermalReliefGap );
144  if( !( item_boundingbox.Intersects( zone_boundingbox ) ) )
145  continue;
146 
147  // Thermal bridges are like a segment from a starting point inside the pad
148  // to an ending point outside the pad
149 
150  // calculate the ending point of the thermal pad, outside the pad
151  wxPoint endpoint;
152  endpoint.x = ( pad->GetSize().x / 2 ) + thermalReliefGap;
153  endpoint.y = ( pad->GetSize().y / 2 ) + thermalReliefGap;
154 
155  // Calculate the starting point of the thermal stub
156  // inside the pad
157  wxPoint startpoint;
158  int copperThickness = aZone->GetThermalReliefCopperBridge( pad )
159  - aZone->GetMinThickness();
160 
161  if( copperThickness < 0 )
162  copperThickness = 0;
163 
164  // Leave a small extra size to the copper area inside to pad
165  copperThickness += KiROUND( IU_PER_MM * 0.04 );
166 
167  startpoint.x = std::min( pad->GetSize().x, copperThickness );
168  startpoint.y = std::min( pad->GetSize().y, copperThickness );
169 
170  startpoint.x /= 2;
171  startpoint.y /= 2;
172 
173  // This is a CIRCLE pad tweak
174  // for circle pads, the thermal stubs orientation is 45 deg
175  double fAngle = pad->GetOrientation();
176  if( pad->GetShape() == PAD_SHAPE_CIRCLE )
177  {
178  endpoint.x = KiROUND( endpoint.x * aArcCorrection );
179  endpoint.y = endpoint.x;
180  fAngle = aRoundPadThermalRotation;
181  }
182 
183  // contour line width has to be taken into calculation to avoid "thermal stub bleed"
184  endpoint.x += pen_radius;
185  endpoint.y += pen_radius;
186  // compute north, south, west and east points for zone connection.
187  ptTest[0] = wxPoint( 0, endpoint.y ); // lower point
188  ptTest[1] = wxPoint( 0, -endpoint.y ); // upper point
189  ptTest[2] = wxPoint( endpoint.x, 0 ); // right point
190  ptTest[3] = wxPoint( -endpoint.x, 0 ); // left point
191 
192  // Test all sides
193  for( int i = 0; i < 4; i++ )
194  {
195  // rotate point
196  RotatePoint( &ptTest[i], fAngle );
197 
198  // translate point
199  ptTest[i] += pad->ShapePos();
200 
201  if( aZone->HitTestFilledArea( ptTest[i] ) )
202  continue;
203 
204  corners_buffer.clear();
205 
206  // polygons are rectangles with width of copper bridge value
207  switch( i )
208  {
209  case 0: // lower stub
210  corners_buffer.push_back( wxPoint( -thermalBridgeWidth, endpoint.y ) );
211  corners_buffer.push_back( wxPoint( +thermalBridgeWidth, endpoint.y ) );
212  corners_buffer.push_back( wxPoint( +thermalBridgeWidth, startpoint.y ) );
213  corners_buffer.push_back( wxPoint( -thermalBridgeWidth, startpoint.y ) );
214  break;
215 
216  case 1: // upper stub
217  corners_buffer.push_back( wxPoint( -thermalBridgeWidth, -endpoint.y ) );
218  corners_buffer.push_back( wxPoint( +thermalBridgeWidth, -endpoint.y ) );
219  corners_buffer.push_back( wxPoint( +thermalBridgeWidth, -startpoint.y ) );
220  corners_buffer.push_back( wxPoint( -thermalBridgeWidth, -startpoint.y ) );
221  break;
222 
223  case 2: // right stub
224  corners_buffer.push_back( wxPoint( endpoint.x, -thermalBridgeWidth ) );
225  corners_buffer.push_back( wxPoint( endpoint.x, thermalBridgeWidth ) );
226  corners_buffer.push_back( wxPoint( +startpoint.x, thermalBridgeWidth ) );
227  corners_buffer.push_back( wxPoint( +startpoint.x, -thermalBridgeWidth ) );
228  break;
229 
230  case 3: // left stub
231  corners_buffer.push_back( wxPoint( -endpoint.x, -thermalBridgeWidth ) );
232  corners_buffer.push_back( wxPoint( -endpoint.x, thermalBridgeWidth ) );
233  corners_buffer.push_back( wxPoint( -startpoint.x, thermalBridgeWidth ) );
234  corners_buffer.push_back( wxPoint( -startpoint.x, -thermalBridgeWidth ) );
235  break;
236  }
237 
238  aCornerBuffer.NewOutline();
239 
240  // add computed polygon to list
241  for( unsigned ic = 0; ic < corners_buffer.size(); ic++ )
242  {
243  wxPoint cpos = corners_buffer[ic];
244  RotatePoint( &cpos, fAngle ); // Rotate according to module orientation
245  cpos += pad->ShapePos(); // Shift origin to position
246  aCornerBuffer.Append( cpos.x, cpos.y );
247  }
248  }
249  }
250  }
251 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:106
int GetMinThickness() const
Definition: class_zone.h:224
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:525
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
bool BuildFilledSolidAreasPolygons(BOARD *aPcb, SHAPE_POLY_SET *aOutlineBuffer=NULL)
Build the filled solid areas polygons from zone outlines (stored in m_Poly) The solid areas can be mo...
Class BOARD to handle a board.
MODULE * Next() const
Definition: class_module.h:120
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:182
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...
Classes to handle copper zones.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:644
void TransformOutlinesShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aMinClearanceValue, bool aUseNetClearance)
Function TransformOutlinesShapeWithClearanceToPolygon Convert the outlines shape to a polygon with no...
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:787
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
void Inflate(int aFactor, int aCircleSegmentsCount)
Performs outline inflation/deflation, using round corners.
Class SHAPE_POLY_SET.
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:635
D_PAD * Next() const
Definition: class_pad.h:160
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
int NewOutline()
Creates a new empty polygon in the set and returns its index
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...
int GetNetCode() const
Function GetNetCode.
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
bool IsOnCopperLayer() const
Function IsOnCopperLayer.
Definition: class_zone.cpp:188
#define max(a, b)
Definition: auxiliary.h:86
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
DLIST< MODULE > m_Modules
Definition: class_board.h:245
bool HitTestFilledArea(const wxPoint &aRefPos) const
Function HitTestFilledArea tests if the given wxPoint is within the bounds of a filled area of this z...
Definition: class_zone.cpp:814
Class EDA_RECT handles the component boundary box.
Usual pad.
Definition: pad_shapes.h:60
Module description (excepted pads)
Use thermal relief for pads.
Definition: zones.h:58
int GetZoneClearance() const
Definition: class_zone.h:218
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
#define min(a, b)
Definition: auxiliary.h:85
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) ...