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::ZONE_FILL_MODE::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 76 of file zone_filler.cpp.

76  :
77  m_board( aBoard ),
78  m_brdOutlinesValid( false ),
79  m_commit( aCommit ),
80  m_progressReporter( nullptr ),
81  m_high_def( 9 ),
82  m_low_def( 6 )
83 {
84 }
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 87 of file zone_filler.cpp.

88 {
89 }

Member Function Documentation

◆ addHatchFillTypeOnZone()

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

for zones having the ZONE_FILL_MODE::ZONE_FILL_MODE::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 991 of file zone_filler.cpp.

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

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(), 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 388 of file zone_filler.cpp.

389 {
390  if( aPad->GetShape() == PAD_SHAPE_CUSTOM )
391  {
392  // the pad shape in zone can be its convex hull or the shape itself
393  SHAPE_POLY_SET outline( aPad->GetCustomShapeAsPolygon() );
394  int numSegs = std::max( GetArcToSegmentCount( aGap, m_high_def, 360.0 ), 6 );
395  double correction = GetCircletoPolyCorrectionFactor( numSegs );
396  outline.Inflate( KiROUND( aGap * correction ), numSegs );
397  aPad->CustomShapeAsPolygonToBoardPosition( &outline, aPad->GetPosition(),
398  aPad->GetOrientation() );
399 
401  {
402  std::vector<wxPoint> convex_hull;
403  BuildConvexHull( convex_hull, outline );
404 
405  aHoles.NewOutline();
406 
407  for( const wxPoint& pt : convex_hull )
408  aHoles.Append( pt );
409  }
410  else
411  aHoles.Append( outline );
412  }
413  else
414  {
415  // Optimizing polygon vertex count: the high definition is used for round
416  // and oval pads (pads with large arcs) but low def for other shapes (with
417  // small arcs)
418  if( aPad->GetShape() == PAD_SHAPE_CIRCLE || aPad->GetShape() == PAD_SHAPE_OVAL ||
419  ( aPad->GetShape() == PAD_SHAPE_ROUNDRECT && aPad->GetRoundRectRadiusRatio() > 0.4 ) )
420  aPad->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_high_def );
421  else
422  aPad->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_low_def );
423  }
424 }
double GetCircletoPolyCorrectionFactor(int aSegCountforCircle)
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:253
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...
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:422
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:374
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:671
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:237
const wxPoint GetPosition() const override
Definition: class_pad.h:241
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
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)
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:89

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, 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 431 of file zone_filler.cpp.

433 {
434  switch( aItem->Type() )
435  {
436  case PCB_LINE_T:
437  {
438  DRAWSEGMENT* seg = (DRAWSEGMENT*) aItem;
439  seg->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_high_def, aIgnoreLineWidth );
440  break;
441  }
442  case PCB_TEXT_T:
443  {
444  TEXTE_PCB* text = (TEXTE_PCB*) aItem;
445  text->TransformBoundingBoxWithClearanceToPolygon( &aHoles, aGap );
446  break;
447  }
448  case PCB_MODULE_EDGE_T:
449  {
450  EDGE_MODULE* edge = (EDGE_MODULE*) aItem;
451  edge->TransformShapeWithClearanceToPolygon( aHoles, aGap, m_high_def, aIgnoreLineWidth );
452  break;
453  }
454  case PCB_MODULE_TEXT_T:
455  {
456  TEXTE_MODULE* text = (TEXTE_MODULE*) aItem;
457 
458  if( text->IsVisible() )
459  text->TransformBoundingBoxWithClearanceToPolygon( &aHoles, aGap );
460 
461  break;
462  }
463  default:
464  break;
465  }
466 }
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
Convert the text bounding box to a rectangular polygon depending on the text orientation,...
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:207

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 515 of file zone_filler.cpp.

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

875 {
876  auto zoneBB = aZone->GetBoundingBox();
877  int zone_clearance = aZone->GetZoneClearance();
878  int biggest_clearance = m_board->GetDesignSettings().GetBiggestClearanceValue();
879  biggest_clearance = std::max( biggest_clearance, zone_clearance );
880  zoneBB.Inflate( biggest_clearance );
881 
882  // Is a point on the boundary of the polygon inside or outside? This small epsilon lets
883  // us avoid the question.
884  int epsilon = KiROUND( IU_PER_MM * 0.04 ); // about 1.5 mil
885 
886  for( auto module : m_board->Modules() )
887  {
888  for( auto pad : module->Pads() )
889  {
890  if( !hasThermalConnection( pad, aZone ) )
891  continue;
892 
893  // We currently only connect to pads, not pad holes
894  if( !pad->IsOnLayer( aZone->GetLayer() ) )
895  continue;
896 
897  int thermalReliefGap = aZone->GetThermalReliefGap( pad );
898 
899  // Calculate thermal bridge half width
900  int spoke_w = aZone->GetThermalReliefCopperBridge( pad );
901  // Avoid spoke_w bigger than the smaller pad size, because
902  // it is not possible to create stubs bigger than the pad.
903  // Possible refinement: have a separate size for vertical and horizontal stubs
904  spoke_w = std::min( spoke_w, pad->GetSize().x );
905  spoke_w = std::min( spoke_w, pad->GetSize().y );
906 
907  // Cannot create stubs having a width < zone min thickness
908  if( spoke_w <= aZone->GetMinThickness() )
909  continue;
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  spoke.Rotate( -DECIDEG2RAD( padAngle ) );
980  spoke.Move( shapePos );
981 
982  spoke.SetClosed( true );
983  spoke.GenerateBBoxCache();
984  aSpokesList.push_back( std::move( spoke ) );
985  }
986  }
987  }
988 }
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:533
BOARD * m_board
Definition: zone_filler.h:106
coord_type GetTop() const
Definition: box2.h:203
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox (virtual)
Definition: class_zone.cpp:497
int GetBiggestClearanceValue()
Function GetBiggestClearanceValue.
void Rotate(double aAngle, const VECTOR2I &aCenter=VECTOR2I(0, 0))
Function Rotate rotates all vertices by a given angle.
void Move(const VECTOR2I &aVector) override
static const double s_RoundPadThermalSpokeAngle
Definition: zone_filler.cpp:72
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:204
coord_type GetRight() const
Definition: box2.h:198
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:530
coord_type GetBottom() const
Definition: box2.h:199
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:524
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
bool Intersects(const BOX2< Vec > &aRect) const
Function Intersects.
Definition: box2.h:235
void SetClosed(bool aClosed)
Function SetClosed()
MODULES & Modules()
Definition: class_board.h:226
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:301
SHAPE_LINE_CHAIN.
double DECIDEG2RAD(double deg)
Definition: trigo.h:214
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:61
coord_type GetLeft() const
Definition: box2.h:202
int GetZoneClearance() const
Definition: class_zone.h:176
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(), DECIDEG2RAD(), SHAPE_LINE_CHAIN::GenerateBBoxCache(), BOARD_DESIGN_SETTINGS::GetBiggestClearanceValue(), BOX2< Vec >::GetBottom(), ZONE_CONTAINER::GetBoundingBox(), BOARD::GetDesignSettings(), ZONE_CONTAINER::GetLayer(), BOX2< Vec >::GetLeft(), BOX2< Vec >::GetRight(), ZONE_CONTAINER::GetThermalReliefCopperBridge(), ZONE_CONTAINER::GetThermalReliefGap(), BOX2< Vec >::GetTop(), ZONE_CONTAINER::GetZoneClearance(), hasThermalConnection(), BOX2< Vec >::Inflate(), BOX2< Vec >::Intersects(), KiROUND(), m_board, BOARD::Modules(), SHAPE_LINE_CHAIN::Move(), PAD_SHAPE_CIRCLE, SHAPE_LINE_CHAIN::Rotate(), 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 673 of file zone_filler.cpp.

678 {
680  m_low_def = std::min( ARC_LOW_DEF, int( m_high_def*1.5 ) ); // Reasonable value
681 
682  // Features which are min_width should survive pruning; features that are *less* than
683  // min_width should not. Therefore we subtract epsilon from the min_width when
684  // deflating/inflating.
685  int half_min_width = aZone->GetMinThickness() / 2;
686  int epsilon = Millimeter2iu( 0.001 );
687  int numSegs = std::max( GetArcToSegmentCount( half_min_width, m_high_def, 360.0 ), 6 );
688 
690 
692  cornerStrategy = SHAPE_POLY_SET::ROUND_ACUTE_CORNERS;
693 
694  std::deque<SHAPE_LINE_CHAIN> thermalSpokes;
695  SHAPE_POLY_SET clearanceHoles;
696 
697  std::unique_ptr<SHAPE_FILE_IO> dumper( new SHAPE_FILE_IO(
698  s_DumpZonesWhenFilling ? "zones_dump.txt" : "", SHAPE_FILE_IO::IOM_APPEND ) );
699 
700  aRawPolys = aSmoothedOutline;
701 
703  dumper->BeginGroup( "clipper-zone" );
704 
705  knockoutThermalReliefs( aZone, aRawPolys );
706 
708  dumper->Write( &aRawPolys, "solid-areas-minus-thermal-reliefs" );
709 
710  buildCopperItemClearances( aZone, clearanceHoles );
711 
713  dumper->Write( &aRawPolys, "clearance holes" );
714 
715  buildThermalSpokes( aZone, thermalSpokes );
716 
717  // Create a temporary zone that we can hit-test spoke-ends against. It's only temporary
718  // because the "real" subtract-clearance-holes has to be done after the spokes are added.
719  static const bool USE_BBOX_CACHES = true;
720  SHAPE_POLY_SET testAreas = aRawPolys;
721  testAreas.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
722 
723  // Prune features that don't meet minimum-width criteria
724  if( half_min_width - epsilon > epsilon )
725  {
726  testAreas.Deflate( half_min_width - epsilon, numSegs, cornerStrategy );
727  testAreas.Inflate( half_min_width - epsilon, numSegs, cornerStrategy );
728  }
729 
730  // Spoke-end-testing is hugely expensive so we generate cached bounding-boxes to speed
731  // things up a bit.
732  testAreas.BuildBBoxCaches();
733 
734  for( const SHAPE_LINE_CHAIN& spoke : thermalSpokes )
735  {
736  const VECTOR2I& testPt = spoke.CPoint( 3 );
737 
738  // Hit-test against zone body
739  if( testAreas.Contains( testPt, -1, 1, USE_BBOX_CACHES ) )
740  {
741  aRawPolys.AddOutline( spoke );
742  continue;
743  }
744 
745  // Hit-test against other spokes
746  for( const SHAPE_LINE_CHAIN& other : thermalSpokes )
747  {
748  if( &other != &spoke && other.PointInside( testPt, 1, USE_BBOX_CACHES ) )
749  {
750  aRawPolys.AddOutline( spoke );
751  break;
752  }
753  }
754  }
755 
756  // Ensure previous changes (adding thermal stubs) do not add
757  // filled areas outside the zone boundary
758  aRawPolys.BooleanIntersection( aSmoothedOutline, SHAPE_POLY_SET::PM_FAST );
759  aRawPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
760 
762  dumper->Write( &aRawPolys, "solid-areas-with-thermal-spokes" );
763 
764  aRawPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
765  // Prune features that don't meet minimum-width criteria
766  if( half_min_width - epsilon > epsilon )
767  aRawPolys.Deflate( half_min_width - epsilon, numSegs, cornerStrategy );
768 
770  dumper->Write( &aRawPolys, "solid-areas-before-hatching" );
771 
772  // Now remove the non filled areas due to the hatch pattern
774  addHatchFillTypeOnZone( aZone, aRawPolys );
775 
777  dumper->Write( &aRawPolys, "solid-areas-after-hatching" );
778 
779  // Re-inflate after pruning of areas that don't meet minimum-width criteria
780  if( aZone->GetFilledPolysUseThickness() )
781  {
782  // If we're stroking the zone with a min_width stroke then this will naturally
783  // inflate the zone by half_min_width
784  }
785  else if( half_min_width - epsilon > epsilon )
786  {
787  aRawPolys.Simplify( SHAPE_POLY_SET::PM_FAST );
788  aRawPolys.Inflate( half_min_width - epsilon, numSegs, cornerStrategy );
789 
790  // If we've deflated/inflated by something near our corner radius then we will have
791  // ended up with too-sharp corners. Apply outline smoothing again.
792  if( aZone->GetMinThickness() > (int)aZone->GetCornerRadius() )
793  aRawPolys.BooleanIntersection( aSmoothedOutline, SHAPE_POLY_SET::PM_FAST );
794  }
795 
796  aRawPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
797 
799  dumper->Write( &aRawPolys, "areas_fractured" );
800 
801  aFinalPolys = aRawPolys;
802 
804  dumper->EndGroup();
805 }
SHAPE_FILE_IO.
Definition: shape_file_io.h:39
BOARD * m_board
Definition: zone_filler.h:106
bool GetFilledPolysUseThickness() const
Definition: class_zone.h:599
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:530
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:73
unsigned int GetCornerRadius() const
Definition: class_zone.h:597
SHAPE_POLY_SET.
ZONE_FILL_MODE GetFillMode() const
Definition: class_zone.h:156
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::ZONE_FILL_MODE::HATCH_PATTERN, create a grid pattern in filled a...
int GetCornerSmoothingType() const
Definition: class_zone.h:593
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
SHAPE_LINE_CHAIN.
int GetMinThickness() const
Definition: class_zone.h:186
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
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.

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(), HATCH_PATTERN, SHAPE_POLY_SET::Inflate(), SHAPE_FILE_IO::IOM_APPEND, knockoutThermalReliefs(), m_board, m_high_def, m_low_def, BOARD_DESIGN_SETTINGS::m_MaxError, SHAPE_POLY_SET::PM_FAST, SHAPE_POLY_SET::ROUND_ACUTE_CORNERS, s_DumpZonesWhenFilling, SHAPE_POLY_SET::Simplify(), and ZONE_SETTINGS::SMOOTHING_FILLET.

Referenced by fillSingleZone().

◆ Fill()

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

Definition at line 100 of file zone_filler.cpp.

101 {
102  std::vector<CN_ZONE_ISOLATED_ISLAND_LIST> toFill;
103  auto connectivity = m_board->GetConnectivity();
104  bool filledPolyWithOutline = not m_board->GetDesignSettings().m_ZoneUseNoOutlineInFill;
105 
106  std::unique_lock<std::mutex> lock( connectivity->GetLock(), std::try_to_lock );
107 
108  if( !lock )
109  return false;
110 
111  if( m_progressReporter )
112  {
113  m_progressReporter->Report( aCheck ? _( "Checking zone fills..." ) : _( "Building zone fills..." ) );
114  m_progressReporter->SetMaxProgress( toFill.size() );
115  }
116 
117  // The board outlines is used to clip solid areas inside the board (when outlines are valid)
120 
121  for( auto zone : aZones )
122  {
123  // Keepout zones are not filled
124  if( zone->GetIsKeepout() )
125  continue;
126 
127  if( m_commit )
128  m_commit->Modify( zone );
129 
130  // calculate the hash value for filled areas. it will be used later
131  // to know if the current filled areas are up to date
132  zone->BuildHashValue();
133 
134  // Add the zone to the list of zones to test or refill
135  toFill.emplace_back( CN_ZONE_ISOLATED_ISLAND_LIST(zone) );
136 
137  // Remove existing fill first to prevent drawing invalid polygons
138  // on some platforms
139  zone->UnFill();
140  }
141 
142  std::atomic<size_t> nextItem( 0 );
143  size_t parallelThreadCount =
144  std::min<size_t>( std::thread::hardware_concurrency(), aZones.size() );
145  std::vector<std::future<size_t>> returns( parallelThreadCount );
146 
147  auto fill_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
148  {
149  size_t num = 0;
150 
151  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
152  {
153  ZONE_CONTAINER* zone = toFill[i].m_zone;
154  zone->SetFilledPolysUseThickness( filledPolyWithOutline );
155  SHAPE_POLY_SET rawPolys, finalPolys;
156  fillSingleZone( zone, rawPolys, finalPolys );
157 
158  zone->SetRawPolysList( rawPolys );
159  zone->SetFilledPolysList( finalPolys );
160  zone->SetIsFilled( true );
161 
162  if( m_progressReporter )
164 
165  num++;
166  }
167 
168  return num;
169  };
170 
171  if( parallelThreadCount <= 1 )
172  fill_lambda( m_progressReporter );
173  else
174  {
175  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
176  returns[ii] = std::async( std::launch::async, fill_lambda, m_progressReporter );
177 
178  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
179  {
180  // Here we balance returns with a 100ms timeout to allow UI updating
181  std::future_status status;
182  do
183  {
184  if( m_progressReporter )
186 
187  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
188  } while( status != std::future_status::ready );
189  }
190  }
191 
192  // Now update the connectivity to check for copper islands
193  if( m_progressReporter )
194  {
196  m_progressReporter->Report( _( "Removing insulated copper islands..." ) );
198  }
199 
200  connectivity->SetProgressReporter( m_progressReporter );
201  connectivity->FindIsolatedCopperIslands( toFill );
202 
203  // Now remove insulated copper islands and islands outside the board edge
204  bool outOfDate = false;
205 
206  for( auto& zone : toFill )
207  {
208  std::sort( zone.m_islands.begin(), zone.m_islands.end(), std::greater<int>() );
209  SHAPE_POLY_SET poly = zone.m_zone->GetFilledPolysList();
210 
211  // Remove solid areas outside the board cutouts and the insulated islands
212  // only zones with net code > 0 can have insulated islands by definition
213  if( zone.m_zone->GetNetCode() > 0 )
214  {
215  // solid areas outside the board cutouts are also removed, because they are usually
216  // insulated islands
217  for( auto idx : zone.m_islands )
218  {
219  poly.DeletePolygon( idx );
220  }
221  }
222  // Zones with no net can have areas outside the board cutouts.
223  // By definition, Zones with no net have no isolated island
224  // (in fact all filled areas are isolated islands)
225  // but they can have some areas outside the board cutouts.
226  // A filled area outside the board cutouts has all points outside cutouts,
227  // so we only need to check one point for each filled polygon.
228  // Note also non copper zones are already clipped
229  else if( m_brdOutlinesValid && zone.m_zone->IsOnCopperLayer() )
230  {
231  for( int idx = 0; idx < poly.OutlineCount(); )
232  {
233  if( poly.Polygon( idx ).empty() ||
234  !m_boardOutline.Contains( poly.Polygon( idx ).front().CPoint( 0 ) ) )
235  {
236  poly.DeletePolygon( idx );
237  }
238  else
239  idx++;
240  }
241  }
242 
243  zone.m_zone->SetFilledPolysList( poly );
244 
245  if( aCheck && zone.m_zone->GetHashValue() != poly.GetHash() )
246  outOfDate = true;
247  }
248 
249  if( aCheck && outOfDate )
250  {
252  KIDIALOG dlg( m_progressReporter->GetParent(),
253  _( "Zone fills are out-of-date. Refill?" ),
254  _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
255  dlg.SetOKCancelLabels( _( "Refill" ), _( "Continue without Refill" ) );
256  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
257 
258  if( dlg.ShowModal() == wxID_CANCEL )
259  {
260  if( m_commit )
261  m_commit->Revert();
262 
263  connectivity->SetProgressReporter( nullptr );
264  return false;
265  }
266  }
267 
268  if( m_progressReporter )
269  {
271  m_progressReporter->Report( _( "Performing polygon fills..." ) );
272  m_progressReporter->SetMaxProgress( toFill.size() );
273  }
274 
275 
276  nextItem = 0;
277 
278  auto tri_lambda = [&] ( PROGRESS_REPORTER* aReporter ) -> size_t
279  {
280  size_t num = 0;
281 
282  for( size_t i = nextItem++; i < toFill.size(); i = nextItem++ )
283  {
284  toFill[i].m_zone->CacheTriangulation();
285  num++;
286 
287  if( m_progressReporter )
289  }
290 
291  return num;
292  };
293 
294  if( parallelThreadCount <= 1 )
295  tri_lambda( m_progressReporter );
296  else
297  {
298  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
299  returns[ii] = std::async( std::launch::async, tri_lambda, m_progressReporter );
300 
301  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
302  {
303  // Here we balance returns with a 100ms timeout to allow UI updating
304  std::future_status status;
305  do
306  {
307  if( m_progressReporter )
309 
310  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
311  } while( status != std::future_status::ready );
312  }
313  }
314 
315  if( m_progressReporter )
316  {
318  m_progressReporter->Report( _( "Committing changes..." ) );
320  }
321 
322  connectivity->SetProgressReporter( nullptr );
323 
324  if( m_commit )
325  {
326  m_commit->Push( _( "Fill Zone(s)" ), false );
327  }
328  else
329  {
330  for( auto& i : toFill )
331  connectivity->Update( i.m_zone );
332 
333  connectivity->RecalculateRatsnest();
334  }
335 
336  return true;
337 }
void SetFilledPolysList(SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:567
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.
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:600
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:696
void Report(const wxString &aMessage)
Display aMessage in the progress bar dialog.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:530
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:171
void DeletePolygon(int aIdx)
Deletes aIdx-th polygon from the set
COMMIT * m_commit
Definition: zone_filler.h:110
SHAPE_POLY_SET.
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:300
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,...
void SetRawPolysList(SHAPE_POLY_SET &aPolysList)
Function SetFilledPolysList sets the list of filled polygons.
Definition: class_zone.h:576
virtual void Push(const wxString &aMessage=wxT("A commit"), bool aCreateUndoEntry=true, bool aSetDirtyBit=true)=0
Executes the changes.
#define _(s)
Definition: 3d_actions.cpp:31
bool m_ZoneUseNoOutlineInFill
Option to handle filled polygons in zones: the "legacy" option is using thick outlines around filled ...
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:210
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:553

References _, PROGRESS_REPORTER::AdvancePhase(), PROGRESS_REPORTER::AdvanceProgress(), SHAPE_POLY_SET::Contains(), SHAPE_POLY_SET::DeletePolygon(), KIDIALOG::DoNotShowCheckbox(), fillSingleZone(), BOARD::GetBoardPolygonOutlines(), BOARD::GetConnectivity(), BOARD::GetDesignSettings(), 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 813 of file zone_filler.cpp.

815 {
816  SHAPE_POLY_SET smoothedPoly;
817  std::set<VECTOR2I> colinearCorners;
818  aZone->GetColinearCorners( m_board, colinearCorners );
819 
820  /*
821  * convert outlines + holes to outlines without holes (adding extra segments if necessary)
822  * m_Poly data is expected normalized, i.e. NormalizeAreaOutlines was used after building
823  * this zone
824  */
825  if ( !aZone->BuildSmoothedPoly( smoothedPoly, &colinearCorners ) )
826  return false;
827 
828  if( aZone->IsOnCopperLayer() )
829  {
830  computeRawFilledArea( aZone, smoothedPoly, &colinearCorners, aRawPolys, aFinalPolys );
831  }
832  else
833  {
834  // Features which are min_width should survive pruning; features that are *less* than
835  // min_width should not. Therefore we subtract epsilon from the min_width when
836  // deflating/inflating.
837  int half_min_width = aZone->GetMinThickness() / 2;
838  int epsilon = Millimeter2iu( 0.001 );
839  int numSegs = std::max( GetArcToSegmentCount( half_min_width, m_high_def, 360.0 ), 6 );
840 
841  if( m_brdOutlinesValid )
843 
844  smoothedPoly.Deflate( half_min_width - epsilon, numSegs );
845 
846  // Remove the non filled areas due to the hatch pattern
848  addHatchFillTypeOnZone( aZone, smoothedPoly );
849 
850  // Re-inflate after pruning of areas that don't meet minimum-width criteria
851  if( aZone->GetFilledPolysUseThickness() )
852  {
853  // If we're stroking the zone with a min_width stroke then this will naturally
854  // inflate the zone by half_min_width
855  }
856  else if( half_min_width - epsilon > epsilon )
857  smoothedPoly.Deflate( -( half_min_width - epsilon ), numSegs );
858 
859  aRawPolys = smoothedPoly;
860  aFinalPolys = smoothedPoly;
861 
863  }
864 
865  aZone->SetNeedRefill( false );
866  return true;
867 }
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:599
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...
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:156
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::ZONE_FILL_MODE::HATCH_PATTERN, create a grid pattern in filled a...
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
int GetMinThickness() const
Definition: class_zone.h:186
SHAPE_POLY_SET m_boardOutline
Definition: zone_filler.h:107
bool m_brdOutlinesValid
Definition: zone_filler.h:108
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:210
void SetNeedRefill(bool aNeedRefill)
Definition: class_zone.h:174

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(), HATCH_PATTERN, ZONE_CONTAINER::IsOnCopperLayer(), m_board, m_boardOutline, m_brdOutlinesValid, m_high_def, SHAPE_POLY_SET::PM_FAST, SHAPE_POLY_SET::PM_STRICTLY_SIMPLE, and ZONE_CONTAINER::SetNeedRefill().

Referenced by Fill().

◆ InstallNewProgressReporter()

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

Definition at line 92 of file zone_filler.cpp.

94 {
95  m_uniqueReporter = std::make_unique<WX_PROGRESS_REPORTER>( aParent, aTitle, aNumPhases );
97 }
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 473 of file zone_filler.cpp.

474 {
475  SHAPE_POLY_SET holes;
476 
477  // Use a dummy pad to calculate relief when a pad has a hole but is not on the zone's
478  // copper layer. The dummy pad has the size and shape of the original pad's hole. We have
479  // to give it a parent because some functions expect a non-null parent to find clearance
480  // data, etc.
481  MODULE dummymodule( m_board );
482  D_PAD dummypad( &dummymodule );
483 
484  for( auto module : m_board->Modules() )
485  {
486  for( auto pad : module->Pads() )
487  {
488  if( !hasThermalConnection( pad, aZone ) )
489  continue;
490 
491  // If the pad isn't on the current layer but has a hole, knock out a thermal relief
492  // for the hole.
493  if( !pad->IsOnLayer( aZone->GetLayer() ) )
494  {
495  if( pad->GetDrillSize().x == 0 && pad->GetDrillSize().y == 0 )
496  continue;
497 
498  setupDummyPadForHole( pad, dummypad );
499  pad = &dummypad;
500  }
501 
502  addKnockout( pad, aZone->GetThermalReliefGap( pad ), holes );
503  }
504  }
505 
508 }
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:204
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:524
MODULES & Modules()
Definition: class_board.h:226
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: