Move same-net higher-priority knockout to after smoothing.
Fixes https://gitlab.com/kicad/code/kicad/issues/6145
This commit is contained in:
parent
317bdc58a8
commit
050cfd34dd
|
@ -92,7 +92,8 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*>& aZones, bool aCheck, wxWin
|
|||
std::unique_lock<std::mutex> lock( connectivity->GetLock(), std::try_to_lock );
|
||||
|
||||
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
|
||||
int worstClearance = bds.GetBiggestClearanceValue();
|
||||
|
||||
m_worstClearance = bds.GetBiggestClearanceValue();
|
||||
|
||||
if( !lock )
|
||||
return false;
|
||||
|
@ -109,7 +110,14 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*>& aZones, bool aCheck, wxWin
|
|||
m_boardOutline.RemoveAllContours();
|
||||
m_brdOutlinesValid = m_board->GetBoardPolygonOutlines( m_boardOutline );
|
||||
|
||||
// Update the bounding box and shape caches in the pads to prevent multi-threaded rebuilds.
|
||||
// Update and cache zone bounding boxes and pad effective shapes so that we don't have to
|
||||
// make them thread-safe.
|
||||
for( ZONE_CONTAINER* zone : m_board->Zones() )
|
||||
{
|
||||
zone->CacheBoundingBox();
|
||||
m_worstClearance = std::max( m_worstClearance, zone->GetLocalClearance() );
|
||||
}
|
||||
|
||||
for( MODULE* module : m_board->Modules() )
|
||||
{
|
||||
for( D_PAD* pad : module->Pads() )
|
||||
|
@ -117,23 +125,11 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*>& aZones, bool aCheck, wxWin
|
|||
if( pad->IsDirty() )
|
||||
pad->BuildEffectiveShapes( UNDEFINED_LAYER );
|
||||
}
|
||||
}
|
||||
|
||||
// Update (and cache) the zone bounding boxes as well.
|
||||
for( ZONE_CONTAINER* zone : m_board->Zones() )
|
||||
{
|
||||
zone->CacheBoundingBox();
|
||||
worstClearance = std::max( worstClearance, zone->GetLocalClearance() );
|
||||
|
||||
}
|
||||
|
||||
for( MODULE* module : m_board->Modules() )
|
||||
{
|
||||
for( ZONE_CONTAINER* zone : module->Zones() )
|
||||
{
|
||||
zone->CacheBoundingBox();
|
||||
worstClearance = std::max( worstClearance, zone->GetLocalClearance() );
|
||||
|
||||
m_worstClearance = std::max( m_worstClearance, zone->GetLocalClearance() );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,7 +200,7 @@ bool ZONE_FILLER::Fill( std::vector<ZONE_CONTAINER*>& aZones, bool aCheck, wxWin
|
|||
// A higher priority zone is found: if we intersect and it's not filled yet
|
||||
// then we have to wait.
|
||||
EDA_RECT inflatedBBox = aZone->GetCachedBoundingBox();
|
||||
inflatedBBox.Inflate( worstClearance );
|
||||
inflatedBBox.Inflate( m_worstClearance );
|
||||
|
||||
return inflatedBBox.Intersects( aOtherZone->GetCachedBoundingBox() );
|
||||
};
|
||||
|
@ -715,8 +711,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
|
||||
// Items outside the zone bounding box are skipped, so it needs to be inflated by the
|
||||
// largest clearance value found in the netclasses and rules
|
||||
int biggest_clearance = std::max( zone_clearance, bds.GetBiggestClearanceValue() );
|
||||
zone_boundingbox.Inflate( biggest_clearance + extra_margin );
|
||||
zone_boundingbox.Inflate( m_worstClearance + extra_margin );
|
||||
|
||||
// Use a dummy pad to calculate hole clearance when a pad has a hole but is not on the
|
||||
// zone's copper layer. The dummy pad has the size and shape of the original pad's hole.
|
||||
|
@ -850,7 +845,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
for( BOARD_ITEM* item : m_board->Drawings() )
|
||||
doGraphicItem( item );
|
||||
|
||||
// Add keepout zones and higher-priority zones
|
||||
// Add non-connected zone clearances
|
||||
//
|
||||
auto knockoutZone =
|
||||
[&]( ZONE_CONTAINER* aKnockout )
|
||||
|
@ -859,51 +854,46 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
if( !aKnockout->GetLayerSet().test( aLayer ) )
|
||||
return;
|
||||
|
||||
if( aKnockout->GetBoundingBox().Intersects( zone_boundingbox ) )
|
||||
if( aKnockout->GetCachedBoundingBox().Intersects( zone_boundingbox ) )
|
||||
{
|
||||
if( aKnockout->GetIsRuleArea()
|
||||
|| aZone->GetNetCode() == aKnockout->GetNetCode() )
|
||||
if( aKnockout->GetIsRuleArea() )
|
||||
{
|
||||
// Keepouts and same-net zones use outline with no clearance
|
||||
// Keepouts use outline with no clearance
|
||||
aKnockout->TransformSmoothedOutlineToPolygon( aHoles, 0, nullptr );
|
||||
}
|
||||
else
|
||||
else if( bds.m_ZoneFillVersion == 5 )
|
||||
{
|
||||
// 5.x used outline with clearance
|
||||
int gap = evalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, aZone,
|
||||
aKnockout, aLayer );
|
||||
|
||||
if( bds.m_ZoneFillVersion == 5 )
|
||||
{
|
||||
// 5.x used outline with clearance
|
||||
aKnockout->TransformSmoothedOutlineToPolygon( aHoles, gap, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 6.0 uses filled areas with clearance
|
||||
SHAPE_POLY_SET poly;
|
||||
aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer, gap,
|
||||
m_maxError,
|
||||
ERROR_OUTSIDE );
|
||||
aHoles.Append( poly );
|
||||
}
|
||||
aKnockout->TransformSmoothedOutlineToPolygon( aHoles, gap, nullptr );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 6.0 uses filled areas with clearance
|
||||
int gap = evalRulesForItems( DRC_CONSTRAINT_TYPE_CLEARANCE, aZone,
|
||||
aKnockout, aLayer );
|
||||
|
||||
SHAPE_POLY_SET poly;
|
||||
aKnockout->TransformShapeWithClearanceToPolygon( poly, aLayer, gap,
|
||||
m_maxError,
|
||||
ERROR_OUTSIDE );
|
||||
aHoles.Append( poly );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for( ZONE_CONTAINER* otherZone : m_board->Zones() )
|
||||
{
|
||||
if( otherZone == aZone )
|
||||
continue;
|
||||
|
||||
if( otherZone->GetIsRuleArea() )
|
||||
if( otherZone->GetNetCode() != aZone->GetNetCode()
|
||||
&& otherZone->GetPriority() > aZone->GetPriority() )
|
||||
{
|
||||
if( otherZone->GetDoNotAllowCopperPour() )
|
||||
knockoutZone( otherZone );
|
||||
knockoutZone( otherZone );
|
||||
}
|
||||
else
|
||||
else if( otherZone->GetIsRuleArea() && otherZone->GetDoNotAllowCopperPour() )
|
||||
{
|
||||
if( otherZone->GetPriority() > aZone->GetPriority() )
|
||||
knockoutZone( otherZone );
|
||||
knockoutZone( otherZone );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -911,15 +901,14 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
{
|
||||
for( ZONE_CONTAINER* otherZone : module->Zones() )
|
||||
{
|
||||
if( otherZone->GetIsRuleArea() )
|
||||
if( otherZone->GetNetCode() != aZone->GetNetCode()
|
||||
&& otherZone->GetPriority() > aZone->GetPriority() )
|
||||
{
|
||||
if( otherZone->GetDoNotAllowCopperPour() )
|
||||
knockoutZone( otherZone );
|
||||
knockoutZone( otherZone );
|
||||
}
|
||||
else
|
||||
else if( otherZone->GetIsRuleArea() && otherZone->GetDoNotAllowCopperPour() )
|
||||
{
|
||||
if( otherZone->GetPriority() > aZone->GetPriority() )
|
||||
knockoutZone( otherZone );
|
||||
knockoutZone( otherZone );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -928,6 +917,49 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LA
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the outlines of higher-proirity zones with the same net. These zones should be
|
||||
* in charge of the fill parameters within their own outlines.
|
||||
*/
|
||||
void ZONE_FILLER::subtractHigherPriorityZones( const ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aRawFill )
|
||||
{
|
||||
auto knockoutZone =
|
||||
[&]( ZONE_CONTAINER* aKnockout )
|
||||
{
|
||||
// If the zones share no common layers
|
||||
if( !aKnockout->GetLayerSet().test( aLayer ) )
|
||||
return;
|
||||
|
||||
if( aKnockout->GetCachedBoundingBox().Intersects( aZone->GetCachedBoundingBox() ) )
|
||||
{
|
||||
aRawFill.BooleanSubtract( *aKnockout->Outline(), SHAPE_POLY_SET::PM_FAST );
|
||||
}
|
||||
};
|
||||
|
||||
for( ZONE_CONTAINER* otherZone : m_board->Zones() )
|
||||
{
|
||||
if( otherZone->GetNetCode() == aZone->GetNetCode()
|
||||
&& otherZone->GetPriority() > aZone->GetPriority() )
|
||||
{
|
||||
knockoutZone( otherZone );
|
||||
}
|
||||
}
|
||||
|
||||
for( MODULE* module : m_board->Modules() )
|
||||
{
|
||||
for( ZONE_CONTAINER* otherZone : module->Zones() )
|
||||
{
|
||||
if( otherZone->GetNetCode() == aZone->GetNetCode()
|
||||
&& otherZone->GetPriority() > aZone->GetPriority() )
|
||||
{
|
||||
knockoutZone( otherZone );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define DUMP_POLYS_TO_COPPER_LAYER( a, b, c ) \
|
||||
{ if( m_debugZoneFiller && dumpLayer == b ) \
|
||||
{ \
|
||||
|
@ -1119,6 +1151,9 @@ void ZONE_FILLER::computeRawFilledArea( const ZONE_CONTAINER* aZone, PCB_LAYER_I
|
|||
aRawPolys.BooleanSubtract( clearanceHoles, SHAPE_POLY_SET::PM_FAST );
|
||||
DUMP_POLYS_TO_COPPER_LAYER( aRawPolys, In13_Cu, "after-trim-to-clearance-holes" );
|
||||
|
||||
// Lastly give any same-net but higher-priority zones control over their own area.
|
||||
subtractHigherPriorityZones( aZone, aLayer, aRawPolys );
|
||||
|
||||
aRawPolys.Fracture( SHAPE_POLY_SET::PM_FAST );
|
||||
|
||||
aFinalPolys = aRawPolys;
|
||||
|
|
|
@ -60,6 +60,9 @@ private:
|
|||
void buildCopperItemClearances( const ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aHoles );
|
||||
|
||||
void subtractHigherPriorityZones( const ZONE_CONTAINER* aZone, PCB_LAYER_ID aLayer,
|
||||
SHAPE_POLY_SET& aRawFill );
|
||||
|
||||
/**
|
||||
* Function computeRawFilledArea
|
||||
* Add non copper areas polygons (pads and tracks with clearance)
|
||||
|
@ -118,6 +121,7 @@ private:
|
|||
std::unique_ptr<WX_PROGRESS_REPORTER> m_uniqueReporter;
|
||||
|
||||
int m_maxError;
|
||||
int m_worstClearance;
|
||||
|
||||
bool m_debugZoneFiller;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue