60 RESULTS(
int aOutline1,
int aOutline2,
int aVertex1,
int aVertex2 ) :
107 SEG::ecoord min_dist = std::numeric_limits<SEG::ecoord>::max();
110 auto check_pt = [&](
VERTEX* p )
112 VECTOR2D diff( p->x - aPt->
x, p->y - aPt->
y );
115 if( dist2 > 0 && dist2 < limit2 && dist2 < min_dist && p->isEar(
true ) )
124 while( p && p->
z <= maxZ )
132 while( p && p->
z >= minZ )
147 std::set<VERTEX*> visited;
160 if( ( visited.empty() || !visited.contains( p ) ) && ( q =
getPoint( p ) ) )
164 if( !visited.contains( q ) &&
166 p->
i, q->
i ).second )
170 visited.insert( p->
prev );
172 visited.insert( p->
next );
175 visited.insert( q->
prev );
177 visited.insert( q->
next );
201 m_brdOutlinesValid( false ),
203 m_progressReporter( nullptr ),
204 m_worstClearance( 0 )
221 wxASSERT_MSG(
m_commit, wxT(
"ZONE_FILLER must have a valid commit to call SetProgressReporter" ) );
239 std::vector<std::pair<ZONE*, PCB_LAYER_ID>> toFill;
240 std::map<std::pair<ZONE*, PCB_LAYER_ID>,
HASH_128> oldFillHashes;
241 std::map<ZONE*, std::map<PCB_LAYER_ID, ISOLATED_ISLANDS>> isolatedIslandsMap;
250 connectivity->ClearRatsnest();
258 :
_(
"Building zone fills..." ) );
271 zone->CacheBoundingBox();
275 for(
PAD*
pad : footprint->Pads() )
279 pad->BuildEffectiveShapes();
284 for(
ZONE* zone : footprint->Zones() )
285 zone->CacheBoundingBox();
288 footprint->BuildCourtyardCaches();
289 footprint->BuildNetTieCache();
294 auto findHighestPriorityZone =
296 const std::function<bool(
const ZONE* )>& testFn ) ->
ZONE*
298 unsigned highestPriority = 0;
299 ZONE* highestPriorityZone =
nullptr;
304 if( zone->GetIsRuleArea() )
307 if( zone->GetAssignedPriority() < highestPriority )
310 if( !zone->IsOnLayer( itemLayer ) )
314 if( zone->GetNumCorners() <= 2 )
317 if( !zone->GetBoundingBox().Intersects( bbox ) )
320 if( !testFn( zone ) )
324 if( zone->GetAssignedPriority() > highestPriority
325 || zone->GetNetCode() == netcode )
328 highestPriorityZone = zone;
332 return highestPriorityZone;
335 auto isInPourKeepoutArea =
340 if( !zone->GetIsRuleArea() )
343 if( !zone->HasKeepoutParametersSet() )
346 if( !zone->GetDoNotAllowZoneFills() )
349 if( !zone->IsOnLayer( itemLayer ) )
353 if( zone->GetNumCorners() <= 2 )
356 if( !zone->GetBoundingBox().Intersects( bbox ) )
359 if( zone->Outline()->Contains( testPoint ) )
375 via->ClearZoneLayerOverrides();
377 if( !
via->GetRemoveUnconnected() )
382 int holeRadius =
via->GetDrillValue() / 2 + 1;
383 int netcode =
via->GetNetCode();
384 LSET layers =
via->GetLayerSet() & boardCuMask;
388 [&](
const ZONE* aZone ) ->
bool
395 if( !
via->ConditionallyFlashed( layer ) )
398 if( isInPourKeepoutArea( bbox, layer,
center ) )
404 ZONE* zone = findHighestPriorityZone( bbox, layer, netcode, viaTestFn );
407 && (
via->Padstack().UnconnectedLayerMode()
409 || layer ==
via->Padstack().Drill().start
410 || layer ==
via->Padstack().Drill().end ) )
422 for(
PAD*
pad : footprint->Pads() )
424 pad->ClearZoneLayerOverrides();
426 if( !
pad->GetRemoveUnconnected() )
431 int netcode =
pad->GetNetCode();
432 LSET layers =
pad->GetLayerSet() & boardCuMask;
435 [&](
const ZONE* aZone ) ->
bool
442 if( !
pad->ConditionallyFlashed( layer ) )
445 if( isInPourKeepoutArea( bbox, layer,
center ) )
451 ZONE* zone = findHighestPriorityZone( bbox, layer, netcode, padTestFn );
462 for(
ZONE* zone : aZones )
465 if( zone->GetIsRuleArea() )
469 if( zone->GetNumCorners() <= 2 )
479 zone->BuildHashValue( layer );
480 oldFillHashes[ { zone, layer } ] = zone->GetHashValue( layer );
483 toFill.emplace_back( std::make_pair( zone, layer ) );
492 auto check_fill_dependency =
500 if( aOtherZone->GetFillFlag( aLayer ) )
505 if( aOtherZone->GetIsRuleArea() )
509 if( aOtherZone->GetNumCorners() <= 2 )
513 if( !aOtherZone->GetLayerSet().test( aLayer ) )
520 if( aOtherZone->SameNet( aZone ) )
528 if( !inflatedBBox.
Intersects( aOtherZone->GetBoundingBox() ) )
535 [&]( std::pair<ZONE*, PCB_LAYER_ID> aFillItem ) ->
int
538 ZONE* zone = aFillItem.first;
543 for(
ZONE* otherZone : aZones )
545 if( otherZone == zone )
548 if( check_fill_dependency( zone, layer, otherZone ) )
563 std::unique_lock<std::mutex> zoneLock( zone->
GetLock(), std::try_to_lock );
565 if( !zoneLock.owns_lock() )
582 auto tesselate_lambda =
583 [&]( std::pair<ZONE*, PCB_LAYER_ID> aFillItem ) ->
int
589 ZONE* zone = aFillItem.first;
592 std::unique_lock<std::mutex> zoneLock( zone->
GetLock(), std::try_to_lock );
594 if( !zoneLock.owns_lock() )
606 std::vector<std::pair<std::future<int>,
int>> returns;
607 returns.reserve( toFill.size() );
609 bool cancelled =
false;
613 for(
const std::pair<ZONE*, PCB_LAYER_ID>& fillItem : toFill )
614 returns.emplace_back( std::make_pair(
tp.submit( fill_lambda, fillItem ), 0 ) );
616 while( !cancelled && finished != 2 * toFill.size() )
618 for(
size_t ii = 0; ii < returns.size(); ++ii )
620 auto& ret = returns[ii];
625 std::future_status status = ret.first.wait_for( std::chrono::seconds( 0 ) );
627 if( status == std::future_status::ready )
629 if( ret.first.get() )
638 if( ret.second == 0 )
639 returns[ii].first =
tp.submit( fill_lambda, toFill[ii] );
640 else if( ret.second == 1 )
641 returns[ii].first =
tp.submit( tesselate_lambda, toFill[ii] );
646 std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) );
660 for(
auto& ret : returns )
662 if( ret.first.valid() )
664 std::future_status status = ret.first.wait_for( std::chrono::seconds( 0 ) );
666 while( status != std::future_status::ready )
671 status = ret.first.wait_for( std::chrono::milliseconds( 100 ) );
690 connectivity->FillIsolatedIslandsMap( isolatedIslandsMap );
691 connectivity->SetProgressReporter(
nullptr );
696 for(
ZONE* zone : aZones )
699 if( zone->GetIsRuleArea() )
702 zone->SetIsFilled(
true );
708 for(
const auto& [ zone, zoneIslands ] : isolatedIslandsMap )
711 bool allIslands =
true;
713 for(
const auto& [ layer, layerIslands ] : zoneIslands )
715 if( layerIslands.m_IsolatedOutlines.size()
716 !=
static_cast<size_t>( zone->GetFilledPolysList( layer )->OutlineCount() ) )
726 for(
const auto& [ layer, layerIslands ] : zoneIslands )
731 if( layerIslands.m_IsolatedOutlines.empty() )
734 std::vector<int> islands = layerIslands.m_IsolatedOutlines;
738 std::sort( islands.begin(), islands.end(), std::greater<int>() );
740 std::shared_ptr<SHAPE_POLY_SET> poly = zone->GetFilledPolysList( layer );
741 long long int minArea = zone->GetMinIslandArea();
744 for(
int idx : islands )
748 if( mode == ISLAND_REMOVAL_MODE::ALWAYS )
749 poly->DeletePolygonAndTriangulationData( idx,
false );
750 else if ( mode == ISLAND_REMOVAL_MODE::AREA && outline.
Area(
true ) < minArea )
751 poly->DeletePolygonAndTriangulationData( idx,
false );
753 zone->SetIsIsland( layer, idx );
756 poly->UpdateTriangulationDataHash();
757 zone->CalculateFilledArea();
766 using island_check_return = std::vector<std::pair<std::shared_ptr<SHAPE_POLY_SET>,
int>>;
768 std::vector<std::pair<std::shared_ptr<SHAPE_POLY_SET>,
double>> polys_to_check;
773 for(
ZONE* zone : aZones )
783 double minArea = (double) zone->GetMinThickness() * zone->GetMinThickness() * 3;
790 polys_to_check.emplace_back( zone->GetFilledPolysList( layer ), minArea );
795 [&](
int aStart,
int aEnd ) -> island_check_return
797 island_check_return retval;
799 for(
int ii = aStart; ii < aEnd && !cancelled; ++ii )
801 auto [poly, minArea] = polys_to_check[ii];
803 for(
int jj = poly->OutlineCount() - 1; jj >= 0; jj-- )
808 double island_area = test_poly.
Area();
810 if( island_area < minArea )
822 if( intersection.
Area() < island_area / 2.0 )
823 retval.emplace_back( poly, jj );
830 auto island_returns =
tp.parallelize_loop( 0, polys_to_check.size(), island_lambda );
834 for(
size_t ii = 0; ii < island_returns.size(); ++ii )
836 std::future<island_check_return>& ret = island_returns[ii];
840 std::future_status status = ret.wait_for( std::chrono::seconds( 0 ) );
842 while( status != std::future_status::ready )
852 status = ret.wait_for( std::chrono::milliseconds( 100 ) );
860 for(
size_t ii = 0; ii < island_returns.size(); ++ii )
862 std::future<island_check_return>& ret = island_returns[ii];
866 for(
auto& action_item : ret.get() )
867 action_item.first->DeletePolygonAndTriangulationData( action_item.second,
true );
871 for(
ZONE* zone : aZones )
872 zone->CalculateFilledArea();
877 bool outOfDate =
false;
879 for(
ZONE* zone : aZones )
882 if( zone->GetIsRuleArea() )
887 zone->BuildHashValue( layer );
889 if( oldFillHashes[ { zone, layer } ] != zone->GetHashValue( layer ) )
897 KIDIALOG dlg( aParent,
_(
"Prototype zone fill enabled. Disable setting and refill?" ),
898 _(
"Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
906 else if( !outOfDate )
914 KIDIALOG dlg( aParent,
_(
"Zone fills are out-of-date. Refill?" ),
915 _(
"Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
958 std::vector<VECTOR2I> convex_hull;
963 for(
const VECTOR2I& pt : convex_hull )
994 minorAxis = std::min( padSize.
x, padSize.
y );
1000 minorAxis =
via->GetWidth( aLayer );
1014 switch( aItem->
Type() )
1021 if(
text->IsVisible() )
1023 if(
text->IsKnockout() )
1073 std::vector<BOARD_ITEM*>& aThermalConnectionPads,
1074 std::vector<PAD*>& aNoConnectionPads )
1080 std::shared_ptr<SHAPE> padShape;
1086 for(
PAD*
pad : footprint->Pads() )
1088 if( !
pad->IsOnLayer( aLayer ) )
1091 BOX2I padBBox =
pad->GetBoundingBox();
1097 bool noConnection =
pad->GetNetCode() != aZone->
GetNetCode();
1104 noConnection =
true;
1111 aNoConnectionPads.push_back(
pad );
1119 if( aZone->
GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN )
1121 aThermalConnectionPads.push_back(
pad );
1128 connection = ZONE_CONNECTION::FULL;
1132 constraint = bds.
m_DRCEngine->EvalZoneConnection(
pad, aZone, aLayer );
1136 if( connection == ZONE_CONNECTION::THERMAL && !
pad->CanFlashLayer( aLayer ) )
1137 connection = ZONE_CONNECTION::NONE;
1139 switch( connection )
1141 case ZONE_CONNECTION::THERMAL:
1142 padShape =
pad->GetEffectiveShape( aLayer, FLASHING::ALWAYS_FLASHED );
1144 if( aFill.
Collide( padShape.get(), 0 ) )
1150 aThermalConnectionPads.push_back(
pad );
1156 case ZONE_CONNECTION::NONE:
1165 if(
pad->FlashLayer( aLayer ) )
1169 else if(
pad->GetDrillSize().x > 0 )
1172 pad, aZone, aLayer );
1177 holeClearance = padClearance;
1194 if( aZone->
GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN )
1202 if( !
via->IsOnLayer( aLayer ) )
1205 BOX2I viaBBox =
via->GetBoundingBox();
1211 bool noConnection =
via->GetNetCode() != aZone->
GetNetCode()
1212 || (
via->Padstack().UnconnectedLayerMode()
1214 && aLayer !=
via->Padstack().Drill().start
1215 && aLayer !=
via->Padstack().Drill().end );
1220 aThermalConnectionPads.push_back(
via );
1235 const std::vector<PAD*>& aNoConnectionPads,
1241 auto checkForCancel =
1244 return aReporter && ( ticker++ % 50 ) == 0 && aReporter->IsCancelled();
1257 auto evalRulesForItems =
1271 auto knockoutPadClearance =
1276 bool hasHole = aPad->GetDrillSize().x > 0;
1277 bool flashLayer = aPad->FlashLayer( aLayer );
1278 bool platedHole = hasHole && aPad->GetAttribute() == PAD_ATTRIB::PTH;
1280 if( flashLayer || platedHole )
1283 aZone, aPad, aLayer ) );
1286 if( flashLayer && gap >= 0 )
1287 addKnockout( aPad, aLayer, gap + extra_margin, aHoles );
1292 if( aPad->GetAttribute() == PAD_ATTRIB::NPTH )
1296 aZone, aPad, aLayer ) );
1299 aZone, aPad, aLayer ) );
1306 for(
PAD*
pad : aNoConnectionPads )
1311 knockoutPadClearance(
pad );
1316 auto knockoutTrackClearance =
1319 if( aTrack->GetBoundingBox().Intersects( zone_boundingbox ) )
1321 bool sameNet = aTrack->GetNetCode() == aZone->
GetNetCode();
1327 aZone, aTrack, aLayer );
1340 aZone, aTrack, aLayer ) );
1347 if(
via->FlashLayer( aLayer ) && gap > 0 )
1349 via->TransformShapeToPolygon( aHoles, aLayer, gap + extra_margin,
1354 aZone,
via, aLayer ) );
1359 aZone,
via, aLayer ) );
1367 radius + gap + extra_margin,
1375 aTrack->TransformShapeToPolygon( aHoles, aLayer, gap + extra_margin,
1384 if( !track->IsOnLayer( aLayer ) )
1390 knockoutTrackClearance( track );
1395 auto knockoutGraphicClearance =
1403 bool sameNet = shapeNet == aZone->
GetNetCode();
1409 if( aItem->IsOnLayer( aLayer )
1411 || aItem->IsOnLayer(
Margin ) )
1413 if( aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
1415 bool ignoreLineWidths =
false;
1417 aZone, aItem, aLayer );
1419 if( aItem->IsOnLayer( aLayer ) && !sameNet )
1422 aZone, aItem, aLayer ) );
1424 else if( aItem->IsOnLayer(
Edge_Cuts ) )
1427 aZone, aItem, aLayer ) );
1428 ignoreLineWidths =
true;
1430 else if( aItem->IsOnLayer(
Margin ) )
1433 aZone, aItem, aLayer ) );
1438 gap += extra_margin;
1439 addKnockout( aItem, aLayer, gap, ignoreLineWidths, aHoles );
1445 auto knockoutCourtyardClearance =
1448 if( aFootprint->GetBoundingBox().Intersects( zone_boundingbox ) )
1451 aFootprint, aLayer );
1455 aHoles.
Append( aFootprint->GetCourtyard( aLayer ) );
1468 knockoutCourtyardClearance( footprint );
1469 knockoutGraphicClearance( &footprint->Reference() );
1470 knockoutGraphicClearance( &footprint->Value() );
1472 std::set<PAD*> allowedNetTiePads;
1476 if( footprint->IsNetTie() )
1478 for(
PAD*
pad : footprint->Pads() )
1487 if(
pad->IsOnLayer( aLayer ) )
1488 allowedNetTiePads.insert(
pad );
1490 for(
PAD* other : footprint->GetNetTiePads(
pad ) )
1492 if( other->IsOnLayer( aLayer ) )
1493 allowedNetTiePads.insert( other );
1499 for(
BOARD_ITEM* item : footprint->GraphicalItems() )
1504 BOX2I itemBBox = item->GetBoundingBox();
1506 if( !zone_boundingbox.
Intersects( itemBBox ) )
1509 bool skipItem =
false;
1511 if( item->IsOnLayer( aLayer ) )
1513 std::shared_ptr<SHAPE> itemShape = item->GetEffectiveShape();
1515 for(
PAD*
pad : allowedNetTiePads )
1517 if(
pad->GetBoundingBox().Intersects( itemBBox )
1518 &&
pad->GetEffectiveShape( aLayer )->Collide( itemShape.get() ) )
1527 knockoutGraphicClearance( item );
1536 knockoutGraphicClearance( item );
1541 auto knockoutZoneClearance =
1542 [&](
ZONE* aKnockout )
1545 if( !aKnockout->GetLayerSet().test( aLayer ) )
1548 if( aKnockout->GetBoundingBox().Intersects( zone_boundingbox ) )
1550 if( aKnockout->GetIsRuleArea() )
1553 aKnockout->TransformSmoothedOutlineToPolygon( aHoles, 0,
m_maxError,
1559 aZone, aKnockout, aLayer ) );
1562 aZone, aKnockout, aLayer ) );
1565 aKnockout->TransformShapeToPolygon( poly, aLayer, gap + extra_margin,
1578 if( !otherZone->GetBoundingBox().Intersects( zone_boundingbox ) )
1585 if( otherZone->GetIsRuleArea() )
1587 if( otherZone->GetDoNotAllowZoneFills() && !aZone->
IsTeardropArea() )
1588 knockoutZoneClearance( otherZone );
1590 else if( otherZone->HigherPriority( aZone ) )
1592 if( !otherZone->SameNet( aZone ) )
1593 knockoutZoneClearance( otherZone );
1599 for(
ZONE* otherZone : footprint->Zones() )
1605 if( !otherZone->GetBoundingBox().Intersects( zone_boundingbox ) )
1608 if( otherZone->GetIsRuleArea() )
1610 if( otherZone->GetDoNotAllowZoneFills() && !aZone->
IsTeardropArea() )
1611 knockoutZoneClearance( otherZone );
1613 else if( otherZone->HigherPriority( aZone ) )
1615 if( !otherZone->SameNet( aZone ) )
1616 knockoutZoneClearance( otherZone );
1634 auto knockoutZoneOutline =
1635 [&](
ZONE* aKnockout )
1638 if( !aKnockout->GetLayerSet().test( aLayer ) )
1641 if( aKnockout->GetBoundingBox().Intersects( zoneBBox ) )
1657 if( otherZone->SameNet( aZone )
1661 if( !otherZone->IsTeardropArea() )
1662 knockoutZoneOutline( otherZone );
1668 for(
ZONE* otherZone : footprint->Zones() )
1670 if( otherZone->SameNet( aZone ) && otherZone->HigherPriority( aZone ) )
1673 if( !otherZone->IsTeardropArea() )
1674 knockoutZoneOutline( otherZone );
1692 std::map<int, std::vector<std::pair<int, VECTOR2I>>> insertion_points;
1704 insertion_points[result.m_outline1].push_back( { result.m_vertex1, pt1 } );
1705 insertion_points[result.m_outline1].push_back( { result.m_vertex1, pt2 } );
1708 for(
auto& [outline, vertices] : insertion_points )
1712 if( vertices.empty() )
1717 std::stable_sort( vertices.begin(), vertices.end(),
1718 [](
const std::pair<int, VECTOR2I>& a,
const std::pair<int, VECTOR2I>& b )
1720 return a.first < b.first;
1723 std::vector<VECTOR2I> new_points;
1724 new_points.reserve( line.
PointCount() + vertices.size() );
1726 size_t vertex_idx = 0;
1730 new_points.push_back( line.
CPoint( i ) );
1733 while( vertex_idx < vertices.size() && vertices[vertex_idx].first == i )
1735 new_points.push_back( vertices[vertex_idx].second );
1742 for(
const auto& pt : new_points )
1748#define DUMP_POLYS_TO_COPPER_LAYER( a, b, c ) \
1749 { if( m_debugZoneFiller && aDebugLayer == b ) \
1751 m_board->SetLayerName( b, c ); \
1752 SHAPE_POLY_SET d = a; \
1788 CORNER_STRATEGY fastCornerStrategy = CORNER_STRATEGY::CHAMFER_ALL_CORNERS;
1791 std::vector<BOARD_ITEM*> thermalConnectionPads;
1792 std::vector<PAD*> noConnectionPads;
1793 std::deque<SHAPE_LINE_CHAIN> thermalSpokes;
1796 aFillPolys = aSmoothedOutline;
1833 static const bool USE_BBOX_CACHES =
true;
1860 const VECTOR2I& testPt = spoke.CPoint( 3 );
1863 if( testAreas.
Contains( testPt, -1, 1, USE_BBOX_CACHES ) )
1872 if( interval++ > 400 )
1885 if( &other != &spoke
1886 && other.PointInside( testPt, 1, USE_BBOX_CACHES )
1887 && spoke.PointInside( other.CPoint( 3 ), 1, USE_BBOX_CACHES ) )
1917 for(
int ii = aFillPolys.
OutlineCount() - 1; ii >= 0; ii-- )
1919 std::vector<SHAPE_LINE_CHAIN>& island = aFillPolys.
Polygon( ii );
1920 BOX2I islandExtents;
1922 for(
const VECTOR2I& pt : island.front().CPoints() )
1924 islandExtents.
Merge( pt );
1943 if( aZone->
GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN
1980 for(
BOARD_ITEM* item : thermalConnectionPads )
2011 auto checkForCancel =
2014 return aReporter && ( ticker++ % 50 ) == 0 && aReporter->IsCancelled();
2017 auto knockoutGraphicItem =
2020 if( aItem->IsKnockout() && aItem->IsOnLayer( aLayer )
2021 && aItem->GetBoundingBox().Intersects( zone_boundingbox ) )
2023 addKnockout( aItem, aLayer, 0,
true, clearanceHoles );
2032 knockoutGraphicItem( &footprint->Reference() );
2033 knockoutGraphicItem( &footprint->Value() );
2035 for(
BOARD_ITEM* item : footprint->GraphicalItems() )
2036 knockoutGraphicItem( item );
2044 knockoutGraphicItem( item );
2047 aFillPolys = aSmoothedOutline;
2050 auto subtractKeepout =
2051 [&](
ZONE* candidate )
2053 if( !candidate->GetIsRuleArea() )
2056 if( !candidate->HasKeepoutParametersSet() )
2059 if( candidate->GetDoNotAllowZoneFills() && candidate->IsOnLayer( aLayer ) )
2061 if( candidate->GetBoundingBox().Intersects( zone_boundingbox ) )
2063 if( candidate->Outline()->ArcCount() == 0 )
2082 subtractKeepout( keepout );
2090 for(
ZONE* keepout : footprint->Zones() )
2091 subtractKeepout( keepout );
2103 if( aZone->
GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN )
2132 debugLayer = aLayer;
2136 if( !aZone->
BuildSmoothedPoly( maxExtents, aLayer, boardOutline, &smoothedPoly ) )
2144 if(
fillCopperZone( aZone, aLayer, debugLayer, smoothedPoly, maxExtents, aFillPolys ) )
2161 const std::vector<BOARD_ITEM*>& aSpokedPadsList,
2162 std::deque<SHAPE_LINE_CHAIN>& aSpokesList )
2169 if( aZone->
GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN )
2181 if( !item->IsOnLayer( aLayer ) )
2184 int thermalReliefGap = 0;
2188 bool circular =
false;
2192 pad =
static_cast<PAD*
>( item );
2195 if(
pad->GetShape( aLayer) == PAD_SHAPE::CIRCLE
2196 || (
pad->GetShape( aLayer ) == PAD_SHAPE::OVAL && padSize.
x == padSize.
y ) )
2211 if( aZone->
GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN )
2216 if( thermalReliefGap < 0 )
2230 int spoke_max_allowed_w = std::min(
pad->GetSize( aLayer ).x,
pad->GetSize( aLayer ).y );
2232 spoke_w = std::clamp( spoke_w, constraint.
Value().
Min(), constraint.
Value().
Max() );
2235 spoke_w = std::min( spoke_w, spoke_max_allowed_w );
2238 if( spoke_w < aZone->GetMinThickness() )
2247 int spoke_half_w = spoke_w / 2;
2250 BOX2I itemBB = item->GetBoundingBox();
2256 bool customSpokes =
false;
2258 if(
pad &&
pad->GetShape( aLayer ) == PAD_SHAPE::CUSTOM )
2260 for(
const std::shared_ptr<PCB_SHAPE>& primitive :
pad->GetPrimitives( aLayer ) )
2262 if( primitive->IsProxyItem() && primitive->GetShape() == SHAPE_T::SEGMENT )
2264 customSpokes =
true;
2275 auto buildSpokesFromOrigin =
2282 auto intersectLineBox =
2285 double dx = direction.
x;
2286 double dy = direction.y;
2290 if( direction.x == 0 )
2292 else if( direction.y == 0 )
2297 double tx = std::min( half_size.
x /
std::abs( dx ),
2299 return VECTOR2I( dx * tx, dy * tx );
2311 for(
const EDA_ANGLE& spokeAngle : angles )
2313 VECTOR2D direction( spokeAngle.Cos(), spokeAngle.Sin() );
2316 VECTOR2I intersection = intersectLineBox( direction );
2326 aSpokesList.push_back( std::move( spoke ) );
2335 pad->TransformShapeToPolygon( thermalPoly, aLayer, thermalReliefGap +
epsilon,
2339 thermalOutline = thermalPoly.
Outline( 0 );
2343 auto trimToOutline = [&](
SEG& aSegment )
2347 if( padOutline.
Intersect( aSegment, intersections ) )
2349 intersections.clear();
2352 if( thermalOutline.
Intersect( aSegment, intersections ) )
2354 aSegment.B = intersections.front().p;
2361 for(
const std::shared_ptr<PCB_SHAPE>& primitive :
pad->GetPrimitives( aLayer ) )
2363 if( primitive->IsProxyItem() && primitive->GetShape() == SHAPE_T::SEGMENT )
2365 SEG seg( primitive->GetStart(), primitive->GetEnd() );
2370 seg.
A +=
pad->ShapePos( aLayer );
2371 seg.
B +=
pad->ShapePos( aLayer );
2385 if( trimToOutline( seg ) )
2387 VECTOR2I direction = ( seg.
B - seg.
A ).Resize( spoke_half_w );
2391 SEG segL( seg.
A - direction - offset, seg.
B + direction - offset );
2392 SEG segR( seg.
A - direction + offset, seg.
B + direction + offset );
2395 if( trimToOutline( segL ) && trimToOutline( segR ) )
2403 spoke.
Append( seg.
A + offset );
2404 spoke.
Append( seg.
A - offset );
2406 spoke.
Append( segL.
B + direction );
2407 spoke.
Append( seg.
B + direction );
2408 spoke.
Append( segR.
B + direction );
2411 aSpokesList.push_back( std::move( spoke ) );
2421 if( aZone->
GetFillMode() == ZONE_FILL_MODE::HATCH_PATTERN )
2424 thermalSpokeAngle =
pad->GetThermalSpokeAngle();
2443 position =
pad->ShapePos( aLayer );
2444 orientation =
pad->GetOrientation();
2452 position =
via->GetPosition();
2458 spokesBox.
Inflate( thermalReliefGap +
epsilon + zone_half_width );
2465 buildSpokesFromOrigin( spokesBox,
ANGLE_0 );
2467 if( thermalSpokeAngle !=
ANGLE_0 )
2470 for(
auto it = aSpokesList.rbegin(); it != aSpokesList.rbegin() + 4; ++it )
2471 it->Rotate( thermalSpokeAngle );
2476 buildSpokesFromOrigin( spokesBox, thermalSpokeAngle );
2479 auto spokeIter = aSpokesList.rbegin();
2481 for(
int ii = 0; ii < 4; ++ii, ++spokeIter )
2483 spokeIter->Rotate( orientation );
2484 spokeIter->Move( position );
2489 for(
size_t ii = 0; ii < aSpokesList.size(); ++ii )
2490 aSpokesList[ii].GenerateBBoxCache();
2525 hole_base.
Append( corner );
2526 corner.
x += hole_size;
2527 hole_base.
Append( corner );
2528 corner.
y += hole_size;
2529 hole_base.
Append( corner );
2531 hole_base.
Append( corner );
2551 #define SMOOTH_MIN_VAL_MM 0.02
2552 #define SMOOTH_SMALL_VAL_MM 0.04
2568 smooth_value = std::min( smooth_value, aZone->
GetHatchGap() / 2 );
2571 maxError = std::max( maxError * 2, smooth_value / 20 );
2573 switch( smooth_level )
2585 hole_base = smooth_hole.
Fillet( smooth_value, maxError ).
Outline( 0 );
2598 bool zone_has_offset =
false;
2607 if( !zone_has_offset )
2620 int x_offset = bbox.
GetX() - ( bbox.
GetX() ) % gridsize - gridsize;
2621 int y_offset = bbox.
GetY() - ( bbox.
GetY() ) % gridsize - gridsize;
2624 for(
int xx = x_offset; xx <= bbox.
GetRight(); xx += gridsize )
2626 for(
int yy = y_offset; yy <= bbox.
GetBottom(); yy += gridsize )
2637 hole.
Move(
VECTOR2I( offset_opt.
x % gridsize, offset_opt.
y % gridsize ) );
2650 deflated_thickness = std::max( deflated_thickness, maxError * 2 );
2656 deflatedFilledPolys.
Deflate( deflated_thickness, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, maxError );
2672 if( area < minimal_hole_area )
constexpr EDA_IU_SCALE pcbIUScale
@ ZLO_FORCE_NO_ZONE_CONNECTION
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
int GetBiggestClearanceValue() const
ZONE_SETTINGS & GetDefaultZoneSettings()
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const
Convert the item shape to a closed polygon.
virtual void SetIsKnockout(bool aKnockout)
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Information pertinent to a Pcbnew printed circuit board.
bool GetBoardPolygonOutlines(SHAPE_POLY_SET &aOutlines, OUTLINE_ERROR_HANDLER *aErrorHandler=nullptr, bool aAllowUseArcsInPolygons=false, bool aIncludeNPTHAsOutlines=false)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
const ZONES & Zones() const
int GetMaxClearanceValue() const
Returns the maximum clearance value for any object on the board.
int GetCopperLayerCount() const
const FOOTPRINTS & Footprints() const
const TRACKS & Tracks() const
PROJECT * GetProject() const
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Return a list of missing connections between components/tracks.
const DRAWINGS & Drawings() const
constexpr int GetSizeMax() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
constexpr coord_type GetY() const
constexpr size_type GetWidth() const
constexpr coord_type GetX() const
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr const Vec GetCenter() const
constexpr size_type GetHeight() const
constexpr coord_type GetRight() const
constexpr bool Intersects(const BOX2< Vec > &aRect) const
constexpr coord_type GetBottom() const
Represent a set of changes (additions, deletions or modifications) of a data model (e....
COMMIT & Modify(EDA_ITEM *aItem, BASE_SCREEN *aScreen=nullptr, RECURSE_MODE aRecurse=RECURSE_MODE::NO_RECURSE)
Modify a given item in the model.
MINOPTMAX< int > & Value()
const MINOPTMAX< int > & GetValue() const
ZONE_CONNECTION m_ZoneConnection
KICAD_T Type() const
Returns the type of object.
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
void DoNotShowCheckbox(wxString file, int line)
Shows the 'do not show again' checkbox.
bool SetOKCancelLabels(const ButtonLabel &ok, const ButtonLabel &cancel) override
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
static const LSET & InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
const BOX2I GetBoundingBox() const override
The bounding box is cached, so this will be efficient most of the time.
PAD_SHAPE GetShape(PCB_LAYER_ID aLayer) const
void SetOffset(PCB_LAYER_ID aLayer, const VECTOR2I &aOffset)
void SetPosition(const VECTOR2I &aPos) override
void SetOrientation(const EDA_ANGLE &aAngle)
Set the rotation angle of the pad.
bool TransformHoleToPolygon(SHAPE_POLY_SET &aBuffer, int aClearance, int aError, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Build the corner list of the polygonal drill shape in the board coordinate system.
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the item shape to a closed polygon.
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
void SetPosition(const VECTOR2I &aPoint) override
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
A progress reporter interface for use in multi-threaded environments.
virtual bool IsCancelled() const =0
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void Report(const wxString &aMessage)=0
Display aMessage in the progress bar dialog.
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
virtual void AdvanceProgress()=0
Increment the progress bar length (inside the current virtual zone).
virtual void SetMaxProgress(int aMaxProgress)=0
Fix the value that gives the 100 percent progress bar length (inside the current virtual zone).
bool m_PrototypeZoneFill
Whether Zone fill should always be solid for performance with large boards.
virtual PROJECT_LOCAL_SETTINGS & GetLocalSettings() const
RESULTS(int aOutline1, int aOutline2, int aVertex1, int aVertex2)
bool operator<(const RESULTS &aOther) const
VECTOR2I::extended_type ecoord
static SEG::ecoord Square(int a)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Move(const VECTOR2I &aVector) override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Clear()
Remove all points from the line chain.
double Area(bool aAbsolute=true) const
Return the area of this chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
std::vector< INTERSECTION > INTERSECTIONS
Represent a set of closed polygons.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
SHAPE_POLY_SET Chamfer(int aDistance)
Return a chamfered version of the polygon set.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void DeletePolygon(int aIdx)
Delete aIdx-th polygon from the set.
double Area()
Return the area of this poly set.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
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 Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
void BuildBBoxCaches() const
Construct BBoxCaches for Contains(), below.
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET Fillet(int aRadius, int aErrorMax)
Return a filleted version of the polygon set.
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
SHAPE_POLY_SET CloneDropTriangulation() const
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const BOX2I BBoxFromCaches() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
VERTEX * getPoint(VERTEX *aPt) const
std::set< RESULTS > GetResults() const
VERTEX_CONNECTOR(const BOX2I &aBBox, const SHAPE_POLY_SET &aPolys, int aDist)
std::set< RESULTS > m_results
std::deque< VERTEX > m_vertices
VERTEX * createList(const SHAPE_LINE_CHAIN &points, VERTEX *aTail=nullptr, void *aUserData=nullptr)
Create a list of vertices from a line chain.
void SetBoundingBox(const BOX2I &aBBox)
uint32_t zOrder(const double aX, const double aY) const
Note that while the inputs are doubles, these are scaled by the size of the bounding box to fit into ...
void updateList()
After inserting or changing nodes, this function should be called to remove duplicate vertices and en...
void * GetUserData() const
bool isEar(bool aMatchUserData=false) const
Check whether the given vertex is in the middle of an ear.
void buildCopperItemClearances(const ZONE *aZone, PCB_LAYER_ID aLayer, const std::vector< PAD * > &aNoConnectionPads, SHAPE_POLY_SET &aHoles)
Removes clearance from the shape for copper items which share the zone's layer but are not connected ...
void connect_nearby_polys(SHAPE_POLY_SET &aPolys, double aDistance)
Create strands of zero-width between elements of SHAPE_POLY_SET that are within aDistance of each oth...
void buildThermalSpokes(const ZONE *box, PCB_LAYER_ID aLayer, const std::vector< BOARD_ITEM * > &aSpokedPadsList, std::deque< SHAPE_LINE_CHAIN > &aSpokes)
Function buildThermalSpokes Constructs a list of all thermal spokes for the given zone.
ZONE_FILLER(BOARD *aBoard, COMMIT *aCommit)
void subtractHigherPriorityZones(const ZONE *aZone, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aRawFill)
Removes the outlines of higher-proirity zones with the same net.
void knockoutThermalReliefs(const ZONE *aZone, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aFill, std::vector< BOARD_ITEM * > &aThermalConnectionPads, std::vector< PAD * > &aNoConnectionPads)
Removes thermal reliefs from the shape for any pads connected to the zone.
void addKnockout(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer, int aGap, SHAPE_POLY_SET &aHoles)
Add a knockout for a pad or via.
SHAPE_POLY_SET m_boardOutline
bool addHatchFillTypeOnZone(const ZONE *aZone, PCB_LAYER_ID aLayer, PCB_LAYER_ID aDebugLayer, SHAPE_POLY_SET &aFillPolys)
for zones having the ZONE_FILL_MODE::ZONE_FILL_MODE::HATCH_PATTERN, create a grid pattern in filled a...
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
PROGRESS_REPORTER * m_progressReporter
bool fillCopperZone(const ZONE *aZone, PCB_LAYER_ID aLayer, PCB_LAYER_ID aDebugLayer, const SHAPE_POLY_SET &aSmoothedOutline, const SHAPE_POLY_SET &aMaxExtents, SHAPE_POLY_SET &aFillPolys)
Function fillCopperZone Add non copper areas polygons (pads and tracks with clearance) to a filled co...
void addHoleKnockout(PAD *aPad, int aGap, SHAPE_POLY_SET &aHoles)
Add a knockout for a pad's hole.
bool fillNonCopperZone(const ZONE *candidate, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aSmoothedOutline, SHAPE_POLY_SET &aFillPolys)
bool fillSingleZone(ZONE *aZone, PCB_LAYER_ID aLayer, SHAPE_POLY_SET &aFillPolys)
Build the filled solid areas polygons from zone outlines (stored in m_Poly) The solid areas can be mo...
bool Fill(const std::vector< ZONE * > &aZones, bool aCheck=false, wxWindow *aParent=nullptr)
Fills the given list of zones.
ZONE_SETTINGS handles zones parameters.
std::map< PCB_LAYER_ID, ZONE_LAYER_PROPERTIES > m_LayerProperties
Handle a list of polygons defining a copper zone.
void SetNeedRefill(bool aNeedRefill)
std::optional< int > GetLocalClearance() const override
ZONE_LAYER_PROPERTIES & LayerProperties(PCB_LAYER_ID aLayer)
const std::optional< VECTOR2I > & HatchingOffset(PCB_LAYER_ID aLayer) const
void CacheTriangulation(PCB_LAYER_ID aLayer=UNDEFINED_LAYER)
Create a list of triangles that "fill" the solid areas used for instance to draw these solid areas on...
const BOX2I GetBoundingBox() const override
SHAPE_POLY_SET * Outline()
void SetFillFlag(PCB_LAYER_ID aLayer, bool aFlag)
void SetFilledPolysList(PCB_LAYER_ID aLayer, const SHAPE_POLY_SET &aPolysList)
Set the list of filled polygons.
int GetMinThickness() const
bool HigherPriority(const ZONE *aOther) const
int GetHatchThickness() const
double GetHatchHoleMinArea() const
bool IsTeardropArea() const
EDA_ANGLE GetHatchOrientation() const
bool BuildSmoothedPoly(SHAPE_POLY_SET &aSmoothedPoly, PCB_LAYER_ID aLayer, SHAPE_POLY_SET *aBoardOutline, SHAPE_POLY_SET *aSmoothedPolyWithApron=nullptr) const
ZONE_FILL_MODE GetFillMode() const
double GetHatchSmoothingValue() const
int GetHatchSmoothingLevel() const
bool IsOnCopperLayer() const override
unsigned GetAssignedPriority() const
void TransformCircleToPolygon(SHAPE_LINE_CHAIN &aBuffer, const VECTOR2I &aCenter, int aRadius, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a circle to a polygon, using multiple straight lines.
void BuildConvexHull(std::vector< VECTOR2I > &aResult, const std::vector< VECTOR2I > &aPoly)
Calculate the convex hull of a list of points in counter-clockwise order.
CORNER_STRATEGY
define how inflate transform build inflated polygon
@ EDGE_CLEARANCE_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
@ THERMAL_RELIEF_GAP_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
static constexpr EDA_ANGLE ANGLE_0
a few functions useful in geometry calculations.
double m_ExtraClearance
When filling zones, we add an extra amount of clearance to each zone to ensure that rounding errors d...
bool m_DebugZoneFiller
A mode that dumps the various stages of a F_Cu fill into In1_Cu through In9_Cu.
This file is part of the common library.
PCB_LAYER_ID
A quick note on layer IDs:
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
constexpr int mmToIU(double mm) const
A storage class for 128-bit hash value.
A struct recording the isolated and single-pad islands within a zone.
std::optional< VECTOR2I > hatching_offset
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
BS::thread_pool thread_pool
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
@ PCB_PAD_T
class PAD, a pad in a footprint
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
VECTOR2< int32_t > VECTOR2I
#define SMOOTH_MIN_VAL_MM
int getHatchFillThermalClearance(const ZONE *aZone, BOARD_ITEM *aItem, PCB_LAYER_ID aLayer)
#define DUMP_POLYS_TO_COPPER_LAYER(a, b, c)
#define SMOOTH_SMALL_VAL_MM
ISLAND_REMOVAL_MODE
Whether or not to remove isolated islands from a zone.
ZONE_CONNECTION
How pads are covered by copper in zone.