KiCad PCB EDA Suite
zones_convert_to_polygons_aux_functions.cpp File Reference
#include <fctsys.h>
#include <PolyLine.h>
#include <wxPcbStruct.h>
#include <trigo.h>
#include <class_board.h>
#include <class_module.h>
#include <class_zone.h>
#include <pcbnew.h>
#include <zones.h>

Go to the source code of this file.

Functions

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 created by thermal shapes on pads which are not connected to a zone (dangling bridges) More...
 

Function Documentation

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 created by thermal shapes on pads which are not connected to a zone (dangling bridges)

Parameters
aCornerBuffer= a SHAPE_POLY_SET where to store polygons
aPcb= the board.
aZone= a pointer to the ZONE_CONTAINER to examine.
aArcCorrection= a pointer to the ZONE_CONTAINER to examine.
aRoundPadThermalRotation= the rotation in 1.0 degree for thermal stubs in round pads

Definition at line 88 of file zones_convert_to_polygons_aux_functions.cpp.

References SHAPE_POLY_SET::Append(), BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue(), ZONE_CONTAINER::GetBoundingBox(), BOARD::GetDesignSettings(), BOARD_ITEM::GetLayer(), ZONE_CONTAINER::GetMinThickness(), BOARD_CONNECTED_ITEM::GetNetCode(), ZONE_CONTAINER::GetPadConnection(), ZONE_CONTAINER::GetThermalReliefCopperBridge(), ZONE_CONTAINER::GetThermalReliefGap(), ZONE_CONTAINER::GetZoneClearance(), ZONE_CONTAINER::HitTestFilledArea(), EDA_RECT::Inflate(), EDA_RECT::Intersects(), KiROUND(), BOARD::m_Modules, max, min, SHAPE_POLY_SET::NewOutline(), MODULE::Next(), D_PAD::Next(), PAD_ATTRIB_STANDARD, PAD_SHAPE_CIRCLE, PAD_ZONE_CONN_THERMAL, PAD_ZONE_CONN_THT_THERMAL, RotatePoint(), wxPoint::x, and wxPoint::y.

Referenced by ZONE_CONTAINER::AddClearanceAreasPolygonsToPolysList_NG().

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 }
static int KiROUND(double v)
KiROUND rounds a floating point number to an int using "round halfway cases away from zero"...
Definition: common.h:107
int GetMinThickness() const
Definition: class_zone.h:209
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:353
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
MODULE * Next() const
Definition: class_module.h:100
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:317
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:472
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:820
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:463
D_PAD * Next() const
Definition: class_pad.h:145
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
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.
#define max(a, b)
Definition: auxiliary.h:86
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:642
Class EDA_RECT handles the component boundary box.
Usual pad.
Definition: pad_shapes.h:60
Use thermal relief for pads.
Definition: zones.h:58
int GetZoneClearance() const
Definition: class_zone.h:203
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) ...