KiCad PCB EDA Suite
ZONE_FILLER Class Reference

#include <zone_filler.h>

Public Member Functions

 ZONE_FILLER (BOARD *aBoard, COMMIT *aCommit=nullptr)
 
 ~ZONE_FILLER ()
 
void InstallNewProgressReporter (wxWindow *aParent, const wxString &aTitle, int aNumPhases)
 
bool Fill (const std::vector< ZONE_CONTAINER * > &aZones, bool aCheck=false)
 

Private Member Functions

void addKnockout (D_PAD *aPad, int aGap, SHAPE_POLY_SET &aHoles)
 Add a knockout for a pad. More...
 
void addKnockout (BOARD_ITEM *aItem, int aGap, bool aIgnoreLineWidth, SHAPE_POLY_SET &aHoles)
 Add a knockout for a graphic item. More...
 
void knockoutThermalReliefs (const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aFill)
 Removes thermal reliefs from the shape for any pads connected to the zone. More...
 
void buildCopperItemClearances (const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aHoles)
 Removes clearance from the shape for copper items which share the zone's layer but are not connected to it. More...
 
void computeRawFilledArea (const ZONE_CONTAINER *aZone, const SHAPE_POLY_SET &aSmoothedOutline, std::set< VECTOR2I > *aPreserveCorners, SHAPE_POLY_SET &aRawPolys, SHAPE_POLY_SET &aFinalPolys)
 Function computeRawFilledArea Add non copper areas polygons (pads and tracks with clearance) to a filled copper area used in BuildFilledSolidAreasPolygons when calculating filled areas in a zone Non copper areas are pads and track and their clearance area The filled copper area must be computed before BuildFilledSolidAreasPolygons() call this function just after creating the filled copper area polygon (without clearance areas. More...
 
void buildThermalSpokes (const ZONE_CONTAINER *aZone, std::deque< SHAPE_LINE_CHAIN > &aSpokes)
 Function buildThermalSpokes Constructs a list of all thermal spokes for the given zone. More...
 
bool fillSingleZone (ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aRawPolys, SHAPE_POLY_SET &aFinalPolys)
 Build the filled solid areas polygons from zone outlines (stored in m_Poly) The solid areas can be more than one on copper layers, and do not have holes ( holes are linked by overlapping segments to the main outline) in order to have drawable (and plottable) filled polygons. More...
 
void addHatchFillTypeOnZone (const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aRawPolys)
 for zones having the ZONE_FILL_MODE::ZFM_HATCH_PATTERN, create a grid pattern in filled areas of aZone, giving to the filled polygons a fill style like a grid More...
 

Private Attributes

BOARDm_board
 
SHAPE_POLY_SET m_boardOutline
 
bool m_brdOutlinesValid
 
COMMITm_commit
 
WX_PROGRESS_REPORTERm_progressReporter
 
std::unique_ptr< WX_PROGRESS_REPORTERm_uniqueReporter
 
int m_high_def
 
int m_low_def
 

Detailed Description

Definition at line 39 of file zone_filler.h.

Constructor & Destructor Documentation

◆ ZONE_FILLER()

ZONE_FILLER::ZONE_FILLER ( BOARD aBoard,
COMMIT aCommit = nullptr 
)

Definition at line 83 of file zone_filler.cpp.

83  :
84  m_board( aBoard ), m_brdOutlinesValid( false ), m_commit( aCommit ),
85  m_progressReporter( nullptr )
86 {
87 }
BOARD * m_board
Definition: zone_filler.h:106
WX_PROGRESS_REPORTER * m_progressReporter
Definition: zone_filler.h:111
COMMIT * m_commit
Definition: zone_filler.h:110
bool m_brdOutlinesValid
Definition: zone_filler.h:108

◆ ~ZONE_FILLER()

ZONE_FILLER::~ZONE_FILLER ( )

Definition at line 90 of file zone_filler.cpp.

91 {
92 }

Member Function Documentation

◆ addHatchFillTypeOnZone()

void ZONE_FILLER::addHatchFillTypeOnZone ( const ZONE_CONTAINER aZone,
SHAPE_POLY_SET aRawPolys 
)
private

for zones having the ZONE_FILL_MODE::ZFM_HATCH_PATTERN, create a grid pattern in filled areas of aZone, giving to the filled polygons a fill style like a grid

Parameters
aZoneis the zone to modify
aRawPolysA reference to a SHAPE_POLY_SET buffer containing the initial filled areas, and after adding the grid pattern, the modified filled areas with holes

Definition at line 994 of file zone_filler.cpp.

995 {
996  // Build grid:
997 
998  // obviously line thickness must be > zone min thickness.
999  // It can happens if a board file was edited by hand by a python script
1000  // Use 1 micron margin to be *sure* there is no issue in Gerber files
1001  // (Gbr file unit = 1 or 10 nm) due to some truncation in coordinates or calculations
1002  // This margin also avoid problems due to rounding coordinates in next calculations
1003  // that can create incorrect polygons
1004  int thickness = std::max( aZone->GetHatchFillTypeThickness(),
1005  aZone->GetMinThickness()+Millimeter2iu( 0.001 ) );
1006 
1007  int linethickness = thickness - aZone->GetMinThickness();
1008  int gridsize = thickness + aZone->GetHatchFillTypeGap();
1009  double orientation = aZone->GetHatchFillTypeOrientation();
1010 
1011  SHAPE_POLY_SET filledPolys = aRawPolys;
1012  // Use a area that contains the rotated bbox by orientation,
1013  // and after rotate the result by -orientation.
1014  if( orientation != 0.0 )
1015  {
1016  filledPolys.Rotate( M_PI/180.0 * orientation, VECTOR2I( 0,0 ) );
1017  }
1018 
1019  BOX2I bbox = filledPolys.BBox( 0 );
1020 
1021  // Build hole shape
1022  // the hole size is aZone->GetHatchFillTypeGap(), but because the outline thickness
1023  // is aZone->GetMinThickness(), the hole shape size must be larger
1024  SHAPE_LINE_CHAIN hole_base;
1025  int hole_size = aZone->GetHatchFillTypeGap() + aZone->GetMinThickness();
1026  VECTOR2I corner( 0, 0 );;
1027  hole_base.Append( corner );
1028  corner.x += hole_size;
1029  hole_base.Append( corner );
1030  corner.y += hole_size;
1031  hole_base.Append( corner );
1032  corner.x = 0;
1033  hole_base.Append( corner );
1034  hole_base.SetClosed( true );
1035 
1036  // Calculate minimal area of a grid hole.
1037  // All holes smaller than a threshold will be removed
1038  double minimal_hole_area = hole_base.Area() / 2;
1039 
1040  // Now convert this hole to a smoothed shape:
1041  if( aZone->GetHatchFillTypeSmoothingLevel() > 0 )
1042  {
1043  // the actual size of chamfer, or rounded corner radius is the half size
1044  // of the HatchFillTypeGap scaled by aZone->GetHatchFillTypeSmoothingValue()
1045  // aZone->GetHatchFillTypeSmoothingValue() = 1.0 is the max value for the chamfer or the
1046  // radius of corner (radius = half size of the hole)
1047  int smooth_value = KiROUND( aZone->GetHatchFillTypeGap()
1048  * aZone->GetHatchFillTypeSmoothingValue() / 2 );
1049 
1050  // Minimal optimization:
1051  // make smoothing only for reasonnable smooth values, to avoid a lot of useless segments
1052  // and if the smooth value is small, use chamfer even if fillet is requested
1053  #define SMOOTH_MIN_VAL_MM 0.02
1054  #define SMOOTH_SMALL_VAL_MM 0.04
1055  if( smooth_value > Millimeter2iu( SMOOTH_MIN_VAL_MM ) )
1056  {
1057  SHAPE_POLY_SET smooth_hole;
1058  smooth_hole.AddOutline( hole_base );
1059  int smooth_level = aZone->GetHatchFillTypeSmoothingLevel();
1060 
1061  if( smooth_value < Millimeter2iu( SMOOTH_SMALL_VAL_MM ) && smooth_level > 1 )
1062  smooth_level = 1;
1063  // Use a larger smooth_value to compensate the outline tickness
1064  // (chamfer is not visible is smooth value < outline thickess)
1065  smooth_value += aZone->GetMinThickness()/2;
1066 
1067  // smooth_value cannot be bigger than the half size oh the hole:
1068  smooth_value = std::min( smooth_value, aZone->GetHatchFillTypeGap()/2 );
1069  // the error to approximate a circle by segments when smoothing corners by a arc
1070  int error_max = std::max( Millimeter2iu( 0.01), smooth_value/20 );
1071 
1072  switch( smooth_level )
1073  {
1074  case 1:
1075  // Chamfer() uses the distance from a corner to create a end point
1076  // for the chamfer.
1077  hole_base = smooth_hole.Chamfer( smooth_value ).Outline( 0 );
1078  break;
1079 
1080  default:
1081  if( aZone->GetHatchFillTypeSmoothingLevel() > 2 )
1082  error_max /= 2; // Force better smoothing
1083  hole_base = smooth_hole.Fillet( smooth_value, error_max ).Outline( 0 );
1084  break;
1085 
1086  case 0:
1087  break;
1088  };
1089  }
1090  }
1091 
1092  // Build holes
1093  SHAPE_POLY_SET holes;
1094 
1095  for( int xx = 0; ; xx++ )
1096  {
1097  int xpos = xx * gridsize;
1098 
1099  if( xpos > bbox.GetWidth() )
1100  break;
1101 
1102  for( int yy = 0; ; yy++ )
1103  {
1104  int ypos = yy * gridsize;
1105 
1106  if( ypos > bbox.GetHeight() )
1107  break;
1108 
1109  // Generate hole
1110  SHAPE_LINE_CHAIN hole( hole_base );
1111  hole.Move( VECTOR2I( xpos, ypos ) );
1112  holes.AddOutline( hole );
1113  }
1114  }
1115 
1116  holes.Move( bbox.GetPosition() );
1117 
1118  // Clamp holes to the area of filled zones with a outline thickness
1119  // > aZone->GetMinThickness() to be sure the thermal pads can be built
1120  int outline_margin = std::max( (aZone->GetMinThickness()*10)/9, linethickness/2 );
1121  filledPolys.Deflate( outline_margin, 16 );
1122  holes.BooleanIntersection( filledPolys, SHAPE_POLY_SET::PM_FAST );
1123 
1124  if( orientation != 0.0 )
1125  holes.Rotate( -M_PI/180.0 * orientation, VECTOR2I( 0,0 ) );
1126 
1127  // Now filter truncated holes to avoid small holes in pattern
1128  // It happens for holes near the zone outline
1129  for( int ii = 0; ii < holes.OutlineCount(); )
1130  {
1131  double area = holes.Outline( ii ).Area();
1132 
1133  if( area < minimal_hole_area ) // The current hole is too small: remove it
1134  holes.DeletePolygon( ii );
1135  else
1136  ++ii;
1137  }
1138 
1139  // create grid. Use SHAPE_POLY_SET::PM_STRICTLY_SIMPLE to
1140  // generate strictly simple polygons needed by Gerber files and Fracture()
1141  aRawPolys.BooleanSubtract( aRawPolys, holes, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
1142 }
int OutlineCount() const
Returns the number of outlines in the set
int GetHatchFillTypeThickness() const
Definition: class_zone.h:194
#define SMOOTH_MIN_VAL_MM
double GetHatchFillTypeOrientation() const
Definition: class_zone.h:200
double GetHatchFillTypeSmoothingValue() const
Definition: class_zone.h:206
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
#define SMOOTH_SMALL_VAL_MM
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
void DeletePolygon(int aIdx)
Deletes aIdx-th polygon from the set
void SetClosed(bool aClosed)
Function SetClosed()
void Move(const VECTOR2I &aVector) override
Class SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
coord_type GetWidth() const
Definition: box2.h:195
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
double Area() const
const Vec & GetPosition() const
Definition: box2.h:192
SHAPE_POLY_SET Fillet(int aRadius, int aErrorMax, std::set< VECTOR2I > *aPreserveCorners=nullptr)
Function Fillet returns a filleted version of the polygon set.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
#define max(a, b)
Definition: auxiliary.h:86
Class SHAPE_LINE_CHAIN.
SHAPE_POLY_SET Chamfer(int aDistance, std::set< VECTOR2I > *aPreserveCorners=nullptr)
Function Chamfer returns a chamfered version of the polygon set.
coord_type GetHeight() const
Definition: box2.h:196
int GetMinThickness() const
Definition: class_zone.h:185
int GetHatchFillTypeSmoothingLevel() const
Definition: class_zone.h:203
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
void Rotate(double aAngle, const VECTOR2I &aCenter)
Function Rotate rotates all vertices by a given angle.
const BOX2I BBox(int aClearance=0) const override
Function BBox()
int GetHatchFillTypeGap() const
Definition: class_zone.h:197
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114
#define min(a, b)
Definition: auxiliary.h:85

References SHAPE_POLY_SET::AddOutline(), SHAPE_LINE_CHAIN::Append(), SHAPE_LINE_CHAIN::Area(), SHAPE_POLY_SET::BBox(), SHAPE_POLY_SET::BooleanIntersection(), SHAPE_POLY_SET::BooleanSubtract(), SHAPE_POLY_SET::Chamfer(), SHAPE_POLY_SET::Deflate(), SHAPE_POLY_SET::DeletePolygon(), SHAPE_POLY_SET::Fillet(), ZONE_CONTAINER::GetHatchFillTypeGap(), ZONE_CONTAINER::GetHatchFillTypeOrientation(), ZONE_CONTAINER::GetHatchFillTypeSmoothingLevel(), ZONE_CONTAINER::GetHatchFillTypeSmoothingValue(), ZONE_CONTAINER::GetHatchFillTypeThickness(), BOX2< Vec >::GetHeight(), ZONE_CONTAINER::GetMinThickness(), BOX2< Vec >::GetPosition(), BOX2< Vec >::GetWidth(), KiROUND(), max, min, SHAPE_LINE_CHAIN::Move(), SHAPE_POLY_SET::Move(), SHAPE_POLY_SET::Outline(), SHAPE_POLY_SET::OutlineCount(), SHAPE_POLY_SET::PM_FAST, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE, SHAPE_POLY_SET::Rotate(), SHAPE_LINE_CHAIN::SetClosed(), SMOOTH_MIN_VAL_MM, SMOOTH_SMALL_VAL_MM, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by computeRawFilledArea(), and fillSingleZone().

◆ addKnockout() [1/2]

void ZONE_FILLER::addKnockout ( D_PAD aPad,
int  aGap,
SHAPE_POLY_SET aHoles 
)
private

Add a knockout for a pad.

The knockout is 'aGap' larger than the pad (which might be either the thermal clearance or the electrical clearance).

Definition at line 391 of file zone_filler.cpp.

392 {
393  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
394  {
395  // the pad shape in zone can be its convex hull or the shape itself
396  SHAPE_POLY_SET outline( aPad->GetCustomShapeAsPolygon() );
397  int numSegs = std::max( GetArcToSegmentCount( aGap, m_high_def, 360.0 ), 6 );
398  double correction = GetCircletoPolyCorrectionFactor( numSegs );
399  outline.Inflate( KiROUND( aGap * correction ), numSegs );
400  aPad->CustomShapeAsPolygonToBoardPosition( &outline, aPad->GetPosition(),
401  aPad->GetOrientation() );
402 
404  {
405  std::vector<wxPoint> convex_hull;
406  BuildConvexHull( convex_hull, outline );
407 
408  aHoles.NewOutline();
409 
410  for( const wxPoint& pt : convex_hull )
411  aHoles.Append( pt );
412  }
413  else
414  aHoles.Append( outline );
415  }
416  else
417  {
418  // Optimizing polygon vertex count: the high definition is used for round
419  // and oval pads (pads with large arcs) but low def for other shapes (with
420  // small arcs)
421  if( aPad->GetShape() == PAD_SHAPE_CIRCLE || aPad->GetShape() == PAD_SHAPE_OVAL ||
422  ( aPad->GetShape() == PAD_SHAPE_ROUNDRECT && aPad->GetRoundRectRadiusRatio() > 0.4 ) )
423  aPad->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_high_def );
424  else
425  aPad->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_low_def );
426  }
427 }
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
void BuildConvexHull(std::vector< wxPoint > &aResult, const std::vector< wxPoint > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
Definition: convex_hull.cpp:87
Class SHAPE_POLY_SET.
int NewOutline()
Creates a new empty polygon in the set and returns its index
CUST_PAD_SHAPE_IN_ZONE GetCustomShapeInZoneOpt() const
Definition: class_pad.h:237
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aClearanceValue, int aMaxError=ARC_HIGH_DEF, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the pad shape to a closed polygon Used in filli...
#define max(a, b)
Definition: auxiliary.h:86
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:406
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
const SHAPE_POLY_SET & GetCustomShapeAsPolygon() const
Accessor to the custom shape as one polygon.
Definition: class_pad.h:358
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:644
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:221
const wxPoint GetPosition() const override
Definition: class_pad.h:225
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114
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)
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)

References SHAPE_POLY_SET::Append(), BuildConvexHull(), CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL, D_PAD::CustomShapeAsPolygonToBoardPosition(), GetArcToSegmentCount(), GetCircletoPolyCorrectionFactor(), D_PAD::GetCustomShapeAsPolygon(), D_PAD::GetCustomShapeInZoneOpt(), D_PAD::GetOrientation(), D_PAD::GetPosition(), D_PAD::GetRoundRectRadiusRatio(), D_PAD::GetShape(), KiROUND(), m_high_def, m_low_def, max, SHAPE_POLY_SET::NewOutline(), PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_ROUNDRECT, and D_PAD::TransformShapeWithClearanceToPolygon().

Referenced by buildCopperItemClearances(), and knockoutThermalReliefs().

◆ addKnockout() [2/2]

void ZONE_FILLER::addKnockout ( BOARD_ITEM aItem,
int  aGap,
bool  aIgnoreLineWidth,
SHAPE_POLY_SET aHoles 
)
private

Add a knockout for a graphic item.

The knockout is 'aGap' larger than the item (which might be either the electrical clearance or the board edge clearance).

Definition at line 434 of file zone_filler.cpp.

436 {
437  switch( aItem->Type() )
438  {
439  case PCB_LINE_T:
440  {
441  DRAWSEGMENT* seg = (DRAWSEGMENT*) aItem;
442  seg->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_high_def, aIgnoreLineWidth );
443  break;
444  }
445  case PCB_TEXT_T:
446  {
447  TEXTE_PCB* text = (TEXTE_PCB*) aItem;
448  text->TransformBoundingBoxWithClearanceToPolygon( &aHoles, aGap );
449  break;
450  }
451  case PCB_MODULE_EDGE_T:
452  {
453  EDGE_MODULE* edge = (EDGE_MODULE*) aItem;
454  edge->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_high_def, aIgnoreLineWidth );
455  break;
456  }
457  case PCB_MODULE_TEXT_T:
458  {
459  TEXTE_MODULE* text = (TEXTE_MODULE*) aItem;
460 
461  if( text->IsVisible() )
462  text->TransformBoundingBoxWithClearanceToPolygon( &aHoles, aGap );
463 
464  break;
465  }
466  default:
467  break;
468  }
469 }
void TransformShapeWithClearanceToPolygon(SHAPE_POLY_SET &aCornerBuffer, int aClearanceValue, int aError=ARC_HIGH_DEF, bool ignoreLineWidth=false) const override
Function TransformShapeWithClearanceToPolygon Convert the draw segment to a closed polygon Used in fi...
bool IsVisible() const
Definition: eda_text.h:170
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
void TransformBoundingBoxWithClearanceToPolygon(SHAPE_POLY_SET *aCornerBuffer, int aClearanceValue) const
Function TransformBoundingBoxWithClearanceToPolygon Convert the text bounding box to a rectangular po...
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:93
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210

References EDA_TEXT::IsVisible(), m_high_def, PCB_LINE_T, PCB_MODULE_EDGE_T, PCB_MODULE_TEXT_T, PCB_TEXT_T, EDA_TEXT::TransformBoundingBoxWithClearanceToPolygon(), DRAWSEGMENT::TransformShapeWithClearanceToPolygon(), and EDA_ITEM::Type().

◆ buildCopperItemClearances()

void ZONE_FILLER::buildCopperItemClearances ( const ZONE_CONTAINER aZone,
SHAPE_POLY_SET aHoles 
)
private

Removes clearance from the shape for copper items which share the zone's layer but are not connected to it.

Definition at line 518 of file zone_filler.cpp.

519 {
520  int zone_clearance = aZone->GetClearance();
521  int edgeClearance = m_board->GetDesignSettings().m_CopperEdgeClearance;
522  int zone_to_edgecut_clearance = std::max( aZone->GetZoneClearance(), edgeClearance );
523 
524  // items outside the zone bounding box are skipped
525  // the bounding box is the zone bounding box + the biggest clearance found in Netclass list
526  EDA_RECT zone_boundingbox = aZone->GetBoundingBox();
527  int biggest_clearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
528  biggest_clearance = std::max( biggest_clearance, zone_clearance );
529  zone_boundingbox.Inflate( biggest_clearance );
530 
531  // Use a dummy pad to calculate hole clearance when a pad has a hole but is not on the
532  // zone's copper layer. The dummy pad has the size and shape of the original pad's hole.
533  // We have to give it a parent because some functions expect a non-null parent to find
534  // clearance data, etc.
535  MODULE dummymodule( m_board );
536  D_PAD dummypad( &dummymodule );
537 
538  // Add non-connected pad clearances
539  //
540  for( auto module : m_board->Modules() )
541  {
542  for( auto pad : module->Pads() )
543  {
544  if( !pad->IsOnLayer( aZone->GetLayer() ) )
545  {
546  if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
547  continue;
548 
549  setupDummyPadForHole( pad, dummypad );
550  pad = &dummypad;
551  }
552 
553  if( pad->GetNetCode() != aZone->GetNetCode()
554  || pad->GetNetCode() <= 0
555  || aZone->GetPadConnection( pad ) == PAD_ZONE_CONN_NONE )
556  {
557  int gap = std::max( zone_clearance, pad->GetClearance() );
558  EDA_RECT item_boundingbox = pad->GetBoundingBox();
559  item_boundingbox.Inflate( pad->GetClearance() );
560 
561  if( item_boundingbox.Intersects( zone_boundingbox ) )
562  addKnockout( pad, gap, aHoles );
563  }
564  }
565  }
566 
567  // Add non-connected track clearances
568  //
569  for( auto track : m_board->Tracks() )
570  {
571  if( !track->IsOnLayer( aZone->GetLayer() ) )
572  continue;
573 
574  if( track->GetNetCode() == aZone->GetNetCode() && ( aZone->GetNetCode() != 0) )
575  continue;
576 
577  int gap = std::max( zone_clearance, track->GetClearance() );
578  EDA_RECT item_boundingbox = track->GetBoundingBox();
579 
580  if( item_boundingbox.Intersects( zone_boundingbox ) )
581  track->TransformShapeWithClearanceToPolygon( aHoles, gap, m_low_def );
582  }
583 
584  // Add graphic item clearances. They are by definition unconnected, and have no clearance
585  // definitions of their own.
586  //
587  auto doGraphicItem = [&]( BOARD_ITEM* aItem )
588  {
589  // A item on the Edge_Cuts is always seen as on any layer:
590  if( !aItem->IsOnLayer( aZone->GetLayer() ) && !aItem->IsOnLayer( Edge_Cuts ) )
591  return;
592 
593  if( !aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
594  return;
595 
596  bool ignoreLineWidth = false;
597  int gap = zone_clearance;
598 
599  if( aItem->IsOnLayer( Edge_Cuts ) )
600  {
601  gap = zone_to_edgecut_clearance;
602 
603  // edge cuts by definition don't have a width
604  ignoreLineWidth = true;
605  }
606 
607  addKnockout( aItem, gap, ignoreLineWidth, aHoles );
608  };
609 
610  for( auto module : m_board->Modules() )
611  {
612  doGraphicItem( &module->Reference() );
613  doGraphicItem( &module->Value() );
614 
615  for( auto item : module->GraphicalItems() )
616  doGraphicItem( item );
617  }
618 
619  for( auto item : m_board->Drawings() )
620  doGraphicItem( item );
621 
622  // Add zones outlines having an higher priority and keepout
623  //
624  for( ZONE_CONTAINER* zone : m_board->GetZoneList( true ) )
625  {
626 
627  // If the zones share no common layers
628  if( !aZone->CommonLayerExists( zone->GetLayerSet() ) )
629  continue;
630 
631  if( !zone->GetIsKeepout() && zone->GetPriority() <= aZone->GetPriority() )
632  continue;
633 
634  if( zone->GetIsKeepout() && !zone->GetDoNotAllowCopperPour() )
635  continue;
636 
637  // A higher priority zone or keepout area is found: remove this area
638  EDA_RECT item_boundingbox = zone->GetBoundingBox();
639 
640  if( !item_boundingbox.Intersects( zone_boundingbox ) )
641  continue;
642 
643  // Add the zone outline area. Don't use any clearance for keepouts, or for zones with
644  // the same net (they will be connected but will honor their own clearance, thermal
645  // connections, etc.).
646  bool sameNet = aZone->GetNetCode() == zone->GetNetCode();
647  bool useNetClearance = true;
648  int minClearance = zone_clearance;
649 
650  // The final clearance is obviously the max value of each zone clearance
651  minClearance = std::max( minClearance, zone->GetClearance() );
652 
653  if( zone->GetIsKeepout() || sameNet )
654  {
655  minClearance = 0;
656  useNetClearance = false;
657  }
658 
659  zone->TransformOutlinesShapeWithClearanceToPolygon( aHoles, minClearance, useNetClearance );
660  }
661 
663 }
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
int GetNetCode() const
Function GetNetCode.
bool CommonLayerExists(const LSET aLayerSet) const
Function CommonLayerExist Test if this zone shares a common layer with the given layer set.
Definition: class_zone.cpp:222
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
BOARD * m_board
Definition: zone_filler.h:106
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:496
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
void addKnockout(D_PAD *aPad, int aGap, SHAPE_POLY_SET &aHoles)
Add a knockout for a pad.
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:203
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
int GetClearance(BOARD_CONNECTED_ITEM *aItem=NULL) const override
Function GetClearance returns the clearance in internal units.
Definition: class_zone.cpp:649
Pads are not covered.
Definition: zones.h:52
MODULES & Modules()
Definition: class_board.h:227
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:103
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:883
#define max(a, b)
Definition: auxiliary.h:86
Class EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
bool Intersects(const EDA_RECT &aRect) const
Function Intersects tests for a common area between rectangles.
static void setupDummyPadForHole(const D_PAD *aPad, D_PAD &aDummyPad)
Setup aDummyPad to have the same size and shape of aPad's hole.
int GetZoneClearance() const
Definition: class_zone.h:179
DRAWINGS & Drawings()
Definition: class_board.h:236
TRACKS & Tracks()
Definition: class_board.h:218
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
std::list< ZONE_CONTAINER * > GetZoneList(bool aIncludeZonesInFootprints=false)
Function GetZoneList.

References addKnockout(), ZONE_CONTAINER::CommonLayerExists(), BOARD::Drawings(), Edge_Cuts, BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue(), ZONE_CONTAINER::GetBoundingBox(), ZONE_CONTAINER::GetClearance(), BOARD::GetDesignSettings(), ZONE_CONTAINER::GetLayer(), BOARD_CONNECTED_ITEM::GetNetCode(), ZONE_CONTAINER::GetPadConnection(), ZONE_CONTAINER::GetPriority(), ZONE_CONTAINER::GetZoneClearance(), BOARD::GetZoneList(), EDA_RECT::Inflate(), EDA_RECT::Intersects(), m_board, BOARD_DESIGN_SETTINGS::m_CopperEdgeClearance, m_low_def, max, BOARD::Modules(), PAD_ZONE_CONN_NONE, SHAPE_POLY_SET::PM_FAST, setupDummyPadForHole(), SHAPE_POLY_SET::Simplify(), and BOARD::Tracks().

Referenced by computeRawFilledArea().

◆ buildThermalSpokes()

void ZONE_FILLER::buildThermalSpokes ( const ZONE_CONTAINER aZone,
std::deque< SHAPE_LINE_CHAIN > &  aSpokes 
)
private

Function buildThermalSpokes Constructs a list of all thermal spokes for the given zone.

Function buildThermalSpokes.

Definition at line 877 of file zone_filler.cpp.

879 {
880  auto zoneBB = aZone->GetBoundingBox();
881  int zone_clearance = aZone->GetZoneClearance();
882  int biggest_clearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
883  biggest_clearance = std::max( biggest_clearance, zone_clearance );
884  zoneBB.Inflate( biggest_clearance );
885 
886  // Is a point on the boundary of the polygon inside or outside? This small epsilon lets
887  // us avoid the question.
888  int epsilon = KiROUND( IU_PER_MM * 0.04 ); // about 1.5 mil
889 
890  for( auto module : m_board->Modules() )
891  {
892  for( auto pad : module->Pads() )
893  {
894  if( !hasThermalConnection( pad, aZone ) )
895  continue;
896 
897  // We currently only connect to pads, not pad holes
898  if( !pad->IsOnLayer( aZone->GetLayer() ) )
899  continue;
900 
901  int thermalReliefGap = aZone->GetThermalReliefGap( pad );
902 
903  // Calculate thermal bridge half width
904  int spoke_w = aZone->GetThermalReliefCopperBridge( pad );
905  // Avoid spoke_w bigger than the smaller pad size, because
906  // it is not possible to create stubs bigger than the pad.
907  // Possible refinement: have a separate size for vertical and horizontal stubs
908  spoke_w = std::min( spoke_w, pad->GetSize().x );
909  spoke_w = std::min( spoke_w, pad->GetSize().y );
910 
911  int spoke_half_w = spoke_w / 2;
912 
913  // Quick test here to possibly save us some work
914  BOX2I itemBB = pad->GetBoundingBox();
915  itemBB.Inflate( thermalReliefGap + epsilon );
916 
917  if( !( itemBB.Intersects( zoneBB ) ) )
918  continue;
919 
920  // Thermal spokes consist of segments from the pad center to points just outside
921  // the thermal relief.
922  //
923  // We use the bounding-box to lay out the spokes, but for this to work the
924  // bounding box has to be built at the same rotation as the spokes.
925 
926  wxPoint shapePos = pad->ShapePos();
927  wxPoint padPos = pad->GetPosition();
928  double padAngle = pad->GetOrientation();
929  pad->SetOrientation( 0.0 );
930  pad->SetPosition( { 0, 0 } );
931  BOX2I reliefBB = pad->GetBoundingBox();
932  pad->SetPosition( padPos );
933  pad->SetOrientation( padAngle );
934 
935  reliefBB.Inflate( thermalReliefGap + epsilon );
936 
937  // For circle pads, the thermal spoke orientation is 45 deg
938  if( pad->GetShape() == PAD_SHAPE_CIRCLE )
939  padAngle = s_RoundPadThermalSpokeAngle;
940 
941  for( int i = 0; i < 4; i++ )
942  {
943  SHAPE_LINE_CHAIN spoke;
944  switch( i )
945  {
946  case 0: // lower stub
947  spoke.Append( +spoke_half_w, -spoke_half_w );
948  spoke.Append( -spoke_half_w, -spoke_half_w );
949  spoke.Append( -spoke_half_w, reliefBB.GetBottom() );
950  spoke.Append( 0, reliefBB.GetBottom() ); // test pt
951  spoke.Append( +spoke_half_w, reliefBB.GetBottom() );
952  break;
953 
954  case 1: // upper stub
955  spoke.Append( +spoke_half_w, spoke_half_w );
956  spoke.Append( -spoke_half_w, spoke_half_w );
957  spoke.Append( -spoke_half_w, reliefBB.GetTop() );
958  spoke.Append( 0, reliefBB.GetTop() ); // test pt
959  spoke.Append( +spoke_half_w, reliefBB.GetTop() );
960  break;
961 
962  case 2: // right stub
963  spoke.Append( -spoke_half_w, spoke_half_w );
964  spoke.Append( -spoke_half_w, -spoke_half_w );
965  spoke.Append( reliefBB.GetRight(), -spoke_half_w );
966  spoke.Append( reliefBB.GetRight(), 0 ); // test pt
967  spoke.Append( reliefBB.GetRight(), spoke_half_w );
968  break;
969 
970  case 3: // left stub
971  spoke.Append( spoke_half_w, spoke_half_w );
972  spoke.Append( spoke_half_w, -spoke_half_w );
973  spoke.Append( reliefBB.GetLeft(), -spoke_half_w );
974  spoke.Append( reliefBB.GetLeft(), 0 ); // test pt
975  spoke.Append( reliefBB.GetLeft(), spoke_half_w );
976  break;
977  }
978 
979  for( int j = 0; j < spoke.PointCount(); j++ )
980  {
981  RotatePoint( spoke.Point( j ), padAngle );
982  spoke.Point( j ) += shapePos;
983  }
984 
985  spoke.SetClosed( true );
986  spoke.GenerateBBoxCache();
987  aSpokesList.push_back( std::move( spoke ) );
988  }
989  }
990  }
991 }
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:532
BOARD * m_board
Definition: zone_filler.h:106
coord_type GetTop() const
Definition: box2.h:202
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:496
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
static const double s_RoundPadThermalSpokeAngle
Definition: zone_filler.cpp:79
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:203
coord_type GetRight() const
Definition: box2.h:197
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:206
coord_type GetBottom() const
Definition: box2.h:198
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:523
int PointCount() const
Function PointCount()
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
bool Intersects(const BOX2< Vec > &aRect) const
Function Intersects.
Definition: box2.h:234
void SetClosed(bool aClosed)
Function SetClosed()
MODULES & Modules()
Definition: class_board.h:227
const Vec & GetPosition() const
Definition: box2.h:192
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:300
#define max(a, b)
Definition: auxiliary.h:86
Class SHAPE_LINE_CHAIN.
size_t i
Definition: json11.cpp:649
VECTOR2I & Point(int aIndex)
Function Point()
coord_type GetLeft() const
Definition: box2.h:201
int GetZoneClearance() const
Definition: class_zone.h:179
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114
#define min(a, b)
Definition: auxiliary.h:85
bool hasThermalConnection(D_PAD *pad, const ZONE_CONTAINER *aZone)
Return true if the given pad has a thermal connection with the given zone.

References SHAPE_LINE_CHAIN::Append(), SHAPE_LINE_CHAIN::GenerateBBoxCache(), BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue(), BOX2< Vec >::GetBottom(), ZONE_CONTAINER::GetBoundingBox(), BOARD::GetDesignSettings(), ZONE_CONTAINER::GetLayer(), BOX2< Vec >::GetLeft(), BOX2< Vec >::GetPosition(), BOX2< Vec >::GetRight(), ZONE_CONTAINER::GetThermalReliefCopperBridge(), ZONE_CONTAINER::GetThermalReliefGap(), BOX2< Vec >::GetTop(), ZONE_CONTAINER::GetZoneClearance(), hasThermalConnection(), i, BOX2< Vec >::Inflate(), BOX2< Vec >::Intersects(), KiROUND(), m_board, max, min, BOARD::Modules(), PAD_SHAPE_CIRCLE, SHAPE_LINE_CHAIN::Point(), SHAPE_LINE_CHAIN::PointCount(), RotatePoint(), s_RoundPadThermalSpokeAngle, and SHAPE_LINE_CHAIN::SetClosed().

Referenced by computeRawFilledArea().

◆ computeRawFilledArea()

void ZONE_FILLER::computeRawFilledArea ( const ZONE_CONTAINER aZone,
const SHAPE_POLY_SET aSmoothedOutline,
std::set< VECTOR2I > *  aPreserveCorners,
SHAPE_POLY_SET aRawPolys,
SHAPE_POLY_SET aFinalPolys 
)
private

Function computeRawFilledArea Add non copper areas polygons (pads and tracks with clearance) to a filled copper area used in BuildFilledSolidAreasPolygons when calculating filled areas in a zone Non copper areas are pads and track and their clearance area The filled copper area must be computed before BuildFilledSolidAreasPolygons() call this function just after creating the filled copper area polygon (without clearance areas.

1 - Creates the main zone outline using a correction to shrink the resulting area by m_ZoneMinThickness / 2.

Parameters
aPcbthe current board

The result is areas with a margin of m_ZoneMinThickness / 2 so that when drawing outline with segments having a thickness of m_ZoneMinThickness the outlines will match exactly the initial outlines 2 - Knocks out thermal reliefs around thermally-connected pads 3 - Builds a set of thermal spoke for the whole zone 4 - Knocks out unconnected copper items, deleting any affected spokes 5 - Removes unconnected copper islands, deleting any affected spokes 6 - Adds in the remaining spokes

Definition at line 677 of file zone_filler.cpp.

682 {
684  m_low_def = std::min( ARC_LOW_DEF, int( m_high_def*1.5 ) ); // Reasonable value
685 
686  // Features which are min_width should survive pruning; features that are *less* than
687  // min_width should not. Therefore we subtract epsilon from the min_width when
688  // deflating/inflating.
689  int half_min_width = aZone->GetMinThickness() / 2;
690  int epsilon = Millimeter2iu( 0.001 );
691  int numSegs = std::max( GetArcToSegmentCount( half_min_width, m_high_def, 360.0 ), 6 );
692 
694 
696  cornerStrategy = SHAPE_POLY_SET::ROUND_ACUTE_CORNERS;
697 
698  std::deque<SHAPE_LINE_CHAIN> thermalSpokes;
699  SHAPE_POLY_SET clearanceHoles;
700 
701  std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO(
702  s_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) );
703 
704  aRawPolys = aSmoothedOutline;
705 
707  dumper->BeginGroup( "clipper-zone" );
708 
709  knockoutThermalReliefs( aZone, aRawPolys );
710 
712  dumper->Write( &aRawPolys, "solid-areas-minus-thermal-reliefs" );
713 
714  buildCopperItemClearances( aZone, clearanceHoles );
715 
717  dumper->Write( &aRawPolys, "clearance holes" );
718 
719  buildThermalSpokes( aZone, thermalSpokes );
720 
721  // Create a temporary zone that we can hit-test spoke-ends against. It's only temporary
722  // because the "real" subtract-clearance-holes has to be done after the spokes are added.
723  static const bool USE_BBOX_CACHES = true;
724  SHAPE_POLY_SET testAreas = aRawPolys;
725  testAreas.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
726 
727  // Prune features that don't meet minimum-width criteria
728  if( half_min_width - epsilon > epsilon )
729  {
730  testAreas.Deflate( half_min_width - epsilon, numSegs, cornerStrategy );
731  testAreas.Inflate( half_min_width - epsilon, numSegs, cornerStrategy );
732  }
733 
734  // Spoke-end-testing is hugely expensive so we generate cached bounding-boxes to speed
735  // things up a bit.
736  testAreas.BuildBBoxCaches();
737 
738  for( const SHAPE_LINE_CHAIN& spoke : thermalSpokes )
739  {
740  const VECTOR2I& testPt = spoke.CPoint( 3 );
741 
742  // Hit-test against zone body
743  if( testAreas.Contains( testPt, -1, 1, USE_BBOX_CACHES ) )
744  {
745  aRawPolys.AddOutline( spoke );
746  continue;
747  }
748 
749  // Hit-test against other spokes
750  for( const SHAPE_LINE_CHAIN& other : thermalSpokes )
751  {
752  if( &other != &spoke && other.PointInside( testPt, 1, USE_BBOX_CACHES ) )
753  {
754  aRawPolys.AddOutline( spoke );
755  break;
756  }
757  }
758  }
759 
760  // Ensure previous changes (adding thermal stubs) do not add
761  // filled areas outside the zone boundary
762  aRawPolys.BooleanIntersection( aSmoothedOutline, SHAPE_POLY_SET::PM_FAST );
763  aRawPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
764 
766  dumper->Write( &aRawPolys, "solid-areas-with-thermal-spokes" );
767 
768  aRawPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
769  // Prune features that don't meet minimum-width criteria
770  if( half_min_width - epsilon > epsilon )
771  aRawPolys.Deflate( half_min_width - epsilon, numSegs, cornerStrategy );
772 
774  dumper->Write( &aRawPolys, "solid-areas-before-hatching" );
775 
776  // Now remove the non filled areas due to the hatch pattern
777  if( aZone->GetFillMode() == ZFM_HATCH_PATTERN )
778  addHatchFillTypeOnZone( aZone, aRawPolys );
779 
781  dumper->Write( &aRawPolys, "solid-areas-after-hatching" );
782 
783  // Re-inflate after pruning of areas that don't meet minimum-width criteria
784  if( aZone->GetFilledPolysUseThickness() )
785  {
786  // If we're stroking the zone with a min_width stroke then this will naturally
787  // inflate the zone by half_min_width
788  }
789  else if( half_min_width - epsilon > epsilon )
790  {
791  aRawPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
792  aRawPolys.Inflate( half_min_width - epsilon, numSegs, cornerStrategy );
793 
794  // If we've deflated/inflated by something near our corner radius then we will have
795  // ended up with too-sharp corners. Apply outline smoothing again.
796  if( aZone->GetMinThickness() > (int)aZone->GetCornerRadius() )
797  aRawPolys.BooleanIntersection( aSmoothedOutline, SHAPE_POLY_SET::PM_FAST );
798  }
799 
800  aRawPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
801 
803  dumper->Write( &aRawPolys, "areas_fractured" );
804 
805  aFinalPolys = aRawPolys;
806 
808  dumper->EndGroup();
809 }
Class SHAPE_FILE_IO.
Definition: shape_file_io.h:38
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
BOARD * m_board
Definition: zone_filler.h:106
bool GetFilledPolysUseThickness() const
Definition: class_zone.h:598
void buildCopperItemClearances(const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aHoles)
Removes clearance from the shape for copper items which share the zone's layer but are not connected ...
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Returns true if a given subpolygon contains the point aP.
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
static const bool s_DumpZonesWhenFilling
Definition: zone_filler.cpp:80
unsigned int GetCornerRadius() const
Definition: class_zone.h:596
Class SHAPE_POLY_SET.
ZONE_FILL_MODE GetFillMode() const
Definition: class_zone.h:159
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
void knockoutThermalReliefs(const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aFill)
Removes thermal reliefs from the shape for any pads connected to the zone.
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
void addHatchFillTypeOnZone(const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aRawPolys)
for zones having the ZONE_FILL_MODE::ZFM_HATCH_PATTERN, create a grid pattern in filled areas of aZon...
int GetCornerSmoothingType() const
Definition: class_zone.h:592
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
void BuildBBoxCaches()
Constructs BBoxCaches for Contains(), below.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
#define max(a, b)
Definition: auxiliary.h:86
Class SHAPE_LINE_CHAIN.
int GetMinThickness() const
Definition: class_zone.h:185
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
void buildThermalSpokes(const ZONE_CONTAINER *aZone, std::deque< SHAPE_LINE_CHAIN > &aSpokes)
Function buildThermalSpokes Constructs a list of all thermal spokes for the given zone.
#define min(a, b)
Definition: auxiliary.h:85

References addHatchFillTypeOnZone(), SHAPE_POLY_SET::AddOutline(), SHAPE_POLY_SET::BooleanIntersection(), SHAPE_POLY_SET::BooleanSubtract(), SHAPE_POLY_SET::BuildBBoxCaches(), buildCopperItemClearances(), buildThermalSpokes(), SHAPE_POLY_SET::CHOP_ACUTE_CORNERS, SHAPE_POLY_SET::Contains(), SHAPE_POLY_SET::Deflate(), SHAPE_POLY_SET::Fracture(), GetArcToSegmentCount(), ZONE_CONTAINER::GetCornerRadius(), ZONE_CONTAINER::GetCornerSmoothingType(), BOARD::GetDesignSettings(), ZONE_CONTAINER::GetFilledPolysUseThickness(), ZONE_CONTAINER::GetFillMode(), ZONE_CONTAINER::GetMinThickness(), SHAPE_POLY_SET::Inflate(), SHAPE_FILE_IO::IOM_APPEND, knockoutThermalReliefs(), m_board, m_high_def, m_low_def, BOARD_DESIGN_SETTINGS::m_MaxError, max, min, SHAPE_POLY_SET::PM_FAST, SHAPE_POLY_SET::ROUND_ACUTE_CORNERS, s_DumpZonesWhenFilling, SHAPE_POLY_SET::Simplify(), ZONE_SETTINGS::SMOOTHING_FILLET, and ZFM_HATCH_PATTERN.

Referenced by fillSingleZone().

◆ Fill()

bool ZONE_FILLER::Fill ( const std::vector< ZONE_CONTAINER * > &  aZones,
bool  aCheck = false 
)

Definition at line 103 of file zone_filler.cpp.

104 {
105  std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> toFill;
106  auto connectivity = m_board->GetConnectivity();
107  bool filledPolyWithOutline = not m_board->GetDesignSettings().m_ZoneUseNoOutlineInFill;
108 
109  std::unique_lock<std::mutex> lock( connectivity->GetLock(), std::try_to_lock );
110 
111  if( !lock )
112  return false;
113 
114  if( m_progressReporter )
115  {
116  m_progressReporter->Report( aCheck ? _( "Checking zone fills..." ) : _( "Building zone fills..." ) );
117  m_progressReporter->SetMaxProgress( toFill.size() );
118  }
119 
120  // The board outlines is used to clip solid areas inside the board (when outlines are valid)
123 
124  for( auto zone : aZones )
125  {
126  // Keepout zones are not filled
127  if( zone->GetIsKeepout() )
128  continue;
129 
130  if( m_commit )
131  m_commit->Modify( zone );
132 
133  // calculate the hash value for filled areas. it will be used later
134  // to know if the current filled areas are up to date
135  zone->BuildHashValue();
136 
137  // Add the zone to the list of zones to test or refill
138  toFill.emplace_back( CN_ZONE_ISOLATED_ISLAND_LIST(zone) );
139 
140  // Remove existing fill first to prevent drawing invalid polygons
141  // on some platforms
142  zone->UnFill();
143  }
144 
145  std::atomic<size_t> nextItem( 0 );
146  size_t parallelThreadCount =
147  std::min<size_t>( std::thread::hardware_concurrency(), aZones.size() );
148  std::vector<std::future<size_t>> returns( parallelThreadCount );
149 
150  auto fill_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
151  {
152  size_t num = 0;
153 
154  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
155  {
156  ZONE_CONTAINER* zone = toFill[i].m_zone;
157  zone->SetFilledPolysUseThickness( filledPolyWithOutline );
158  SHAPE_POLY_SET rawPolys, finalPolys;
159  fillSingleZone( zone, rawPolys, finalPolys );
160 
161  zone->SetRawPolysList( rawPolys );
162  zone->SetFilledPolysList( finalPolys );
163  zone->SetIsFilled( true );
164 
165  if( m_progressReporter )
167 
168  num++;
169  }
170 
171  return num;
172  };
173 
174  if( parallelThreadCount <= 1 )
175  fill_lambda( m_progressReporter );
176  else
177  {
178  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
179  returns[ii] = std::async( std::launch::async, fill_lambda, m_progressReporter );
180 
181  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
182  {
183  // Here we balance returns with a 100ms timeout to allow UI updating
184  std::future_status status;
185  do
186  {
187  if( m_progressReporter )
189 
190  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
191  } while( status != std::future_status::ready );
192  }
193  }
194 
195  // Now update the connectivity to check for copper islands
196  if( m_progressReporter )
197  {
199  m_progressReporter->Report( _( "Removing insulated copper islands..." ) );
201  }
202 
203  connectivity->SetProgressReporter( m_progressReporter );
204  connectivity->FindIsolatedCopperIslands( toFill );
205 
206  // Now remove insulated copper islands and islands outside the board edge
207  bool outOfDate = false;
208 
209  for( auto& zone : toFill )
210  {
211  std::sort( zone.m_islands.begin(), zone.m_islands.end(), std::greater<int>() );
212  SHAPE_POLY_SET poly = zone.m_zone->GetFilledPolysList();
213 
214  // Remove solid areas outside the board cutouts and the insulated islands
215  // only zones with net code > 0 can have insulated islands by definition
216  if( zone.m_zone->GetNetCode() > 0 )
217  {
218  // solid areas outside the board cutouts are also removed, because they are usually
219  // insulated islands
220  for( auto idx : zone.m_islands )
221  {
222  poly.DeletePolygon( idx );
223  }
224  }
225  // Zones with no net can have areas outside the board cutouts.
226  // By definition, Zones with no net have no isolated island
227  // (in fact all filled areas are isolated islands)
228  // but they can have some areas outside the board cutouts.
229  // A filled area outside the board cutouts has all points outside cutouts,
230  // so we only need to check one point for each filled polygon.
231  // Note also non copper zones are already clipped
232  else if( m_brdOutlinesValid && zone.m_zone->IsOnCopperLayer() )
233  {
234  for( int idx = 0; idx < poly.OutlineCount(); )
235  {
236  if( poly.Polygon( idx ).empty() ||
237  !m_boardOutline.Contains( poly.Polygon( idx ).front().CPoint( 0 ) ) )
238  {
239  poly.DeletePolygon( idx );
240  }
241  else
242  idx++;
243  }
244  }
245 
246  zone.m_zone->SetFilledPolysList( poly );
247 
248  if( aCheck && zone.m_zone->GetHashValue() != poly.GetHash() )
249  outOfDate = true;
250  }
251 
252  if( aCheck && outOfDate )
253  {
255  KIDIALOG dlg( m_progressReporter->GetParent(),
256  _( "Zone fills are out-of-date. Refill?" ),
257  _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
258  dlg.SetOKCancelLabels( _( "Refill" ), _( "Continue without Refill" ) );
259  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
260 
261  if( dlg.ShowModal() == wxID_CANCEL )
262  {
263  if( m_commit )
264  m_commit->Revert();
265 
266  connectivity->SetProgressReporter( nullptr );
267  return false;
268  }
269  }
270 
271  if( m_progressReporter )
272  {
274  m_progressReporter->Report( _( "Performing polygon fills..." ) );
275  m_progressReporter->SetMaxProgress( toFill.size() );
276  }
277 
278 
279  nextItem = 0;
280 
281  auto tri_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
282  {
283  size_t num = 0;
284 
285  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
286  {
287  toFill[i].m_zone->CacheTriangulation();
288  num++;
289 
290  if( m_progressReporter )
292  }
293 
294  return num;
295  };
296 
297  if( parallelThreadCount <= 1 )
298  tri_lambda( m_progressReporter );
299  else
300  {
301  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
302  returns[ii] = std::async( std::launch::async, tri_lambda, m_progressReporter );
303 
304  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
305  {
306  // Here we balance returns with a 100ms timeout to allow UI updating
307  std::future_status status;
308  do
309  {
310  if( m_progressReporter )
312 
313  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
314  } while( status != std::future_status::ready );
315  }
316  }
317 
318  if( m_progressReporter )
319  {
321  m_progressReporter->Report( _( "Committing changes..." ) );
323  }
324 
325  connectivity->SetProgressReporter( nullptr );
326 
327  if( m_commit )
328  {
329  m_commit->Push( _( "Fill Zone(s)" ), false );
330  }
331  else
332  {
333  for( auto& i : toFill )
334  connectivity->Update( i.m_zone );
335 
336  connectivity->RecalculateRatsnest();
337  }
338 
339  return true;
340 }
void SetFilledPolysList(SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:566
virtual void Revert()=0
Revertes the commit by restoring the modifed items state.
void AdvancePhase()
Uses the next vailable virtual zone of the dialog progress bar.
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox
Definition: confirm.cpp:53
int GetNetCode() const
Function GetNetCode.
void SetFilledPolysUseThickness(bool aOption)
Definition: class_zone.h:599
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:44
BOARD * m_board
Definition: zone_filler.h:106
A progress reporter for use in multi-threaded environments.
WX_PROGRESS_REPORTER * m_progressReporter
Definition: zone_filler.h:111
MD5_HASH GetHashValue()
Definition: class_zone.h:695
void Report(const wxString &aMessage)
Display aMessage in the progress bar dialog.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Returns true if a given subpolygon contains the point aP.
void SetIsFilled(bool isFilled)
Definition: class_zone.h:174
void DeletePolygon(int aIdx)
Deletes aIdx-th polygon from the set
COMMIT * m_commit
Definition: zone_filler.h:110
Class SHAPE_POLY_SET.
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:301
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, wxString *aErrorText=nullptr, wxPoint *aErrorLocation=nullptr)
Function GetBoardPolygonOutlines Extracts the board outlines and build a closed polygon from lines,...
#define _(s)
void SetRawPolysList(SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:575
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true)=0
Executes the changes.
bool m_ZoneUseNoOutlineInFill
Option to handle filled polygons in zones: the "legacy" option is using thick outlines around filled ...
size_t i
Definition: json11.cpp:649
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
SHAPE_POLY_SET m_boardOutline
Definition: zone_filler.h:107
bool m_brdOutlinesValid
Definition: zone_filler.h:108
void SetMaxProgress(int aMaxProgress)
Fix the value thar gives the 100 precent progress bar length (inside the current virtual zone)
void AdvanceProgress()
Increment the progress bar length (inside the current virtual zone)
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:209
bool fillSingleZone(ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aRawPolys, SHAPE_POLY_SET &aFinalPolys)
Build the filled solid areas polygons from zone outlines (stored in m_Poly) The solid areas can be mo...
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:552

References _, PROGRESS_REPORTER::AdvancePhase(), PROGRESS_REPORTER::AdvanceProgress(), SHAPE_POLY_SET::Contains(), SHAPE_POLY_SET::DeletePolygon(), KIDIALOG::DoNotShowCheckbox(), fillSingleZone(), BOARD::GetBoardPolygonOutlines(), BOARD::GetConnectivity(), BOARD::GetDesignSettings(), i, PROGRESS_REPORTER::KeepRefreshing(), m_board, m_boardOutline, m_brdOutlinesValid, m_commit, m_progressReporter, BOARD_DESIGN_SETTINGS::m_ZoneUseNoOutlineInFill, COMMIT::Modify(), COMMIT::Push(), SHAPE_POLY_SET::RemoveAllContours(), PROGRESS_REPORTER::Report(), COMMIT::Revert(), ZONE_CONTAINER::SetFilledPolysList(), ZONE_CONTAINER::SetFilledPolysUseThickness(), ZONE_CONTAINER::SetIsFilled(), PROGRESS_REPORTER::SetMaxProgress(), and ZONE_CONTAINER::SetRawPolysList().

Referenced by ZONE_FILLER_TOOL::CheckAllZones(), ZONE_CREATE_HELPER::commitZone(), PCB_EDIT_FRAME::Edit_Zone_Params(), export_vrml_zones(), ZONE_FILLER_TOOL::FillAllZones(), ZONE_CREATE_HELPER::performZoneCutout(), and ZONE_FILLER_TOOL::ZoneFill().

◆ fillSingleZone()

bool ZONE_FILLER::fillSingleZone ( ZONE_CONTAINER aZone,
SHAPE_POLY_SET aRawPolys,
SHAPE_POLY_SET aFinalPolys 
)
private

Build the filled solid areas polygons from zone outlines (stored in m_Poly) The solid areas can be more than one on copper layers, and do not have holes ( holes are linked by overlapping segments to the main outline) in order to have drawable (and plottable) filled polygons.

Returns
true if OK, false if the solid polygons cannot be built
Parameters
aZoneis the zone to fill
aRawPolysA reference to a SHAPE_POLY_SET buffer to store filled solid areas polygons (with holes)
aFinalPolysA reference to a SHAPE_POLY_SET buffer to store polygons with no holes (holes are linked to main outline by overlapping segments, and these polygons are shrinked by aZone->GetMinThickness() / 2 to be drawn with a outline thickness = aZone->GetMinThickness() aFinalPolys are polygons that will be drawn on screen and plotted

Definition at line 817 of file zone_filler.cpp.

819 {
820  SHAPE_POLY_SET smoothedPoly;
821  std::set<VECTOR2I> colinearCorners;
822  aZone->GetColinearCorners( m_board, colinearCorners );
823 
824  /*
825  * convert outlines + holes to outlines without holes (adding extra segments if necessary)
826  * m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
827  * this zone
828  */
829  if ( !aZone->BuildSmoothedPoly( smoothedPoly, &colinearCorners ) )
830  return false;
831 
832  if( aZone->IsOnCopperLayer() )
833  {
834  computeRawFilledArea( aZone, smoothedPoly, &colinearCorners, aRawPolys, aFinalPolys );
835  }
836  else
837  {
838  // Features which are min_width should survive pruning; features that are *less* than
839  // min_width should not. Therefore we subtract epsilon from the min_width when
840  // deflating/inflating.
841  int half_min_width = aZone->GetMinThickness() / 2;
842  int epsilon = Millimeter2iu( 0.001 );
843  int numSegs = std::max( GetArcToSegmentCount( half_min_width, m_high_def, 360.0 ), 6 );
844 
845  if( m_brdOutlinesValid )
847 
848  smoothedPoly.Deflate( half_min_width - epsilon, numSegs );
849 
850  // Remove the non filled areas due to the hatch pattern
851  if( aZone->GetFillMode() == ZFM_HATCH_PATTERN )
852  addHatchFillTypeOnZone( aZone, smoothedPoly );
853 
854  // Re-inflate after pruning of areas that don't meet minimum-width criteria
855  if( aZone->GetFilledPolysUseThickness() )
856  {
857  // If we're stroking the zone with a min_width stroke then this will naturally
858  // inflate the zone by half_min_width
859  }
860  else if( half_min_width - epsilon > epsilon )
861  smoothedPoly.Deflate( -( half_min_width - epsilon ), numSegs );
862 
863  aRawPolys = smoothedPoly;
864  aFinalPolys = smoothedPoly;
865 
867  }
868 
869  aZone->SetNeedRefill( false );
870  return true;
871 }
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
BOARD * m_board
Definition: zone_filler.h:106
void computeRawFilledArea(const ZONE_CONTAINER *aZone, const SHAPE_POLY_SET &aSmoothedOutline, std::set< VECTOR2I > *aPreserveCorners, SHAPE_POLY_SET &aRawPolys, SHAPE_POLY_SET &aFinalPolys)
Function computeRawFilledArea Add non copper areas polygons (pads and tracks with clearance) to a fil...
bool GetFilledPolysUseThickness() const
Definition: class_zone.h:598
void GetColinearCorners(BOARD *aBoard, std::set< VECTOR2I > &colinearCorners)
Some intersecting zones, despite being on the same layer with the same net, cannot be merged due to o...
Class SHAPE_POLY_SET.
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, std::set< VECTOR2I > *aPreserveCorners) const
Function GetSmoothedPoly returns a pointer to the corner-smoothed version of m_Poly.
ZONE_FILL_MODE GetFillMode() const
Definition: class_zone.h:159
void Deflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
void addHatchFillTypeOnZone(const ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aRawPolys)
for zones having the ZONE_FILL_MODE::ZFM_HATCH_PATTERN, create a grid pattern in filled areas of aZon...
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
#define max(a, b)
Definition: auxiliary.h:86
int GetMinThickness() const
Definition: class_zone.h:185
SHAPE_POLY_SET m_boardOutline
Definition: zone_filler.h:107
bool m_brdOutlinesValid
Definition: zone_filler.h:108
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:209
void SetNeedRefill(bool aNeedRefill)
Definition: class_zone.h:177

References addHatchFillTypeOnZone(), SHAPE_POLY_SET::BooleanIntersection(), ZONE_CONTAINER::BuildSmoothedPoly(), computeRawFilledArea(), SHAPE_POLY_SET::Deflate(), SHAPE_POLY_SET::Fracture(), GetArcToSegmentCount(), ZONE_CONTAINER::GetColinearCorners(), ZONE_CONTAINER::GetFilledPolysUseThickness(), ZONE_CONTAINER::GetFillMode(), ZONE_CONTAINER::GetMinThickness(), ZONE_CONTAINER::IsOnCopperLayer(), m_board, m_boardOutline, m_brdOutlinesValid, m_high_def, max, SHAPE_POLY_SET::PM_FAST, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE, ZONE_CONTAINER::SetNeedRefill(), and ZFM_HATCH_PATTERN.

Referenced by Fill().

◆ InstallNewProgressReporter()

void ZONE_FILLER::InstallNewProgressReporter ( wxWindow *  aParent,
const wxString &  aTitle,
int  aNumPhases 
)

Definition at line 95 of file zone_filler.cpp.

97 {
98  m_uniqueReporter = std::make_unique<WX_PROGRESS_REPORTER>( aParent, aTitle, aNumPhases );
100 }
WX_PROGRESS_REPORTER * m_progressReporter
Definition: zone_filler.h:111
std::unique_ptr< WX_PROGRESS_REPORTER > m_uniqueReporter
Definition: zone_filler.h:112

References m_progressReporter, and m_uniqueReporter.

Referenced by ZONE_FILLER_TOOL::CheckAllZones(), PCB_EDIT_FRAME::Edit_Zone_Params(), ZONE_FILLER_TOOL::FillAllZones(), and ZONE_FILLER_TOOL::ZoneFill().

◆ knockoutThermalReliefs()

void ZONE_FILLER::knockoutThermalReliefs ( const ZONE_CONTAINER aZone,
SHAPE_POLY_SET aFill 
)
private

Removes thermal reliefs from the shape for any pads connected to the zone.

Does NOT add in spokes, which must be done later.

Definition at line 476 of file zone_filler.cpp.

477 {
478  SHAPE_POLY_SET holes;
479 
480  // Use a dummy pad to calculate relief when a pad has a hole but is not on the zone's
481  // copper layer. The dummy pad has the size and shape of the original pad's hole. We have
482  // to give it a parent because some functions expect a non-null parent to find clearance
483  // data, etc.
484  MODULE dummymodule( m_board );
485  D_PAD dummypad( &dummymodule );
486 
487  for( auto module : m_board->Modules() )
488  {
489  for( auto pad : module->Pads() )
490  {
491  if( !hasThermalConnection( pad, aZone ) )
492  continue;
493 
494  // If the pad isn't on the current layer but has a hole, knock out a thermal relief
495  // for the hole.
496  if( !pad->IsOnLayer( aZone->GetLayer() ) )
497  {
498  if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
499  continue;
500 
501  setupDummyPadForHole( pad, dummypad );
502  pad = &dummypad;
503  }
504 
505  addKnockout( pad, aZone->GetThermalReliefGap( pad ), holes );
506  }
507  }
508 
511 }
BOARD * m_board
Definition: zone_filler.h:106
void addKnockout(D_PAD *aPad, int aGap, SHAPE_POLY_SET &aHoles)
Add a knockout for a pad.
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:203
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:523
MODULES & Modules()
Definition: class_board.h:227
Class SHAPE_POLY_SET.
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
static void setupDummyPadForHole(const D_PAD *aPad, D_PAD &aDummyPad)
Setup aDummyPad to have the same size and shape of aPad's hole.
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
bool hasThermalConnection(D_PAD *pad, const ZONE_CONTAINER *aZone)
Return true if the given pad has a thermal connection with the given zone.

References addKnockout(), SHAPE_POLY_SET::BooleanSubtract(), ZONE_CONTAINER::GetLayer(), ZONE_CONTAINER::GetThermalReliefGap(), hasThermalConnection(), m_board, BOARD::Modules(), SHAPE_POLY_SET::PM_FAST, setupDummyPadForHole(), and SHAPE_POLY_SET::Simplify().

Referenced by computeRawFilledArea().

Member Data Documentation

◆ m_board

BOARD* ZONE_FILLER::m_board
private

◆ m_boardOutline

SHAPE_POLY_SET ZONE_FILLER::m_boardOutline
private

Definition at line 107 of file zone_filler.h.

Referenced by Fill(), and fillSingleZone().

◆ m_brdOutlinesValid

bool ZONE_FILLER::m_brdOutlinesValid
private

Definition at line 108 of file zone_filler.h.

Referenced by Fill(), and fillSingleZone().

◆ m_commit

COMMIT* ZONE_FILLER::m_commit
private

Definition at line 110 of file zone_filler.h.

Referenced by Fill().

◆ m_high_def

int ZONE_FILLER::m_high_def
private

Definition at line 115 of file zone_filler.h.

Referenced by addKnockout(), computeRawFilledArea(), and fillSingleZone().

◆ m_low_def

int ZONE_FILLER::m_low_def
private

Definition at line 121 of file zone_filler.h.

Referenced by addKnockout(), buildCopperItemClearances(), and computeRawFilledArea().

◆ m_progressReporter

WX_PROGRESS_REPORTER* ZONE_FILLER::m_progressReporter
private

Definition at line 111 of file zone_filler.h.

Referenced by Fill(), and InstallNewProgressReporter().

◆ m_uniqueReporter

std::unique_ptr<WX_PROGRESS_REPORTER> ZONE_FILLER::m_uniqueReporter
private

Definition at line 112 of file zone_filler.h.

Referenced by InstallNewProgressReporter().


The documentation for this class was generated from the following files: