Improvements for pads/vias in zones which knockout other zones.

1) Drop tiny islands which might cause connection problems.
2) Cleanup some dead code in filler
3) Don't estabilish a connection to an island that is fully covered
by whatever its connecting to.

Fixes https://gitlab.com/kicad/code/kicad/issues/11036
This commit is contained in:
Jeff Young 2022-03-05 15:18:24 +00:00
parent 46d423a164
commit 1ffe0da204
3 changed files with 72 additions and 33 deletions

View File

@ -402,17 +402,36 @@ bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, i
&& connected->Layers().Overlaps( aLayer )
&& matchType( connected->Parent()->Type() ) )
{
if( connected->Net() == aItem->GetNetCode() )
{
return true;
}
else if( aCheckOptionalFlashing && aItem->Type() == PCB_PAD_T )
if( aCheckOptionalFlashing && aItem->Type() == PCB_PAD_T )
{
const PAD* pad = static_cast<const PAD*>( aItem );
SHAPE_SEGMENT hole( *pad->GetEffectiveHoleShape() );
PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
return connected->Parent()->GetEffectiveShape( layer )->Collide( &hole );
if( connected->Net() != aItem->GetNetCode() )
{
// Even if the nets aren't the same, we need to check for a physical
// connection with the unflashed pad's hole (as its walls are plated).
return connected->Parent()->GetEffectiveShape( layer )->Collide( &hole );
}
else if( CN_ZONE_LAYER* zoneLayer = dynamic_cast<CN_ZONE_LAYER*>( connected ) )
{
ZONE* zone = static_cast<ZONE*>( zoneLayer->Parent() );
int islandIdx = zoneLayer->SubpolyIndex();
const SHAPE_POLY_SET& fill = zone->GetFilledPolysList( layer );
const SHAPE_LINE_CHAIN& island = fill.COutline( islandIdx );
std::shared_ptr<SHAPE> flashing = pad->GetEffectiveShape();
for( const VECTOR2I& pt : island.CPoints() )
{
if( !flashing->Collide( pt ) )
return true;
}
// If the entire island is inside the pad's flashing then the pad won't
// *actually* connect to anything *else* so don't consider it connected.
return false;
}
}
else if( aCheckOptionalFlashing && aItem->Type() == PCB_VIA_T )
{
@ -420,8 +439,33 @@ bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, i
SHAPE_CIRCLE hole( via->GetCenter(), via->GetDrillValue() / 2 );
PCB_LAYER_ID layer = ToLAYER_ID( aLayer );
return connected->Parent()->GetEffectiveShape( layer )->Collide( &hole );
if( connected->Net() != aItem->GetNetCode() )
{
// Even if the nets aren't the same, we need to check for a physical
// connection with the unflashed via's hole (as its walls are plated).
return connected->Parent()->GetEffectiveShape( layer )->Collide( &hole );
}
else if( CN_ZONE_LAYER* zoneLayer = dynamic_cast<CN_ZONE_LAYER*>( connected ) )
{
ZONE* zone = static_cast<ZONE*>( zoneLayer->Parent() );
int islandIdx = zoneLayer->SubpolyIndex();
const SHAPE_POLY_SET& fill = zone->GetFilledPolysList( layer );
const SHAPE_LINE_CHAIN& island = fill.COutline( islandIdx );
SHAPE_CIRCLE flashing( via->GetCenter(), via->GetWidth() / 2 );
for( const VECTOR2I& pt : island.CPoints() )
{
if( !flashing.SHAPE::Collide( pt ) )
return true;
}
// If the entire island is inside the via's flashing then the via won't
// *actually* connect to anything *else* so don't consider it connected.
return false;
}
}
return connected->Net() == aItem->GetNetCode();
}
}
}

View File

@ -304,10 +304,9 @@ public:
m_cachedPoly = std::make_unique<POLY_GRID_PARTITION>( outline, 16 );
}
int SubpolyIndex() const
{
return m_subpolyIndex;
}
int SubpolyIndex() const { return m_subpolyIndex; }
PCB_LAYER_ID GetLayer() const { return m_layer; }
bool ContainsAnchor( const CN_ANCHOR_PTR anchor ) const
{

View File

@ -363,10 +363,16 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
}
}
// Now remove islands outside the board edge
// Now remove islands which are either outside the board edge or fail to meet the minimum
// area requirements
for( ZONE* zone : aZones )
{
LSET zoneCopperLayers = zone->GetLayerSet() & LSET::AllCuMask( MAX_CU_LAYERS );
LSET zoneCopperLayers = zone->GetLayerSet() & LSET::AllCuMask( MAX_CU_LAYERS );
// Min-thickness is the web thickness. On the other hand, a blob min-thickness by
// min-thickness is not useful. Since there's no obvious definition of web vs. blob, we
// arbitrarily choose "at least 2X the area".
double minArea = (double) zone->GetMinThickness() * zone->GetMinThickness() * 2;
for( PCB_LAYER_ID layer : zoneCopperLayers.Seq() )
{
@ -379,8 +385,12 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
{
std::vector<SHAPE_LINE_CHAIN>& island = poly.Polygon( ii );
if( island.empty() || !m_boardOutline.Contains( island.front().CPoint( 0 ) ) )
if( island.empty()
|| !m_boardOutline.Contains( island.front().CPoint( 0 ) )
|| island.front().Area() < minArea )
{
poly.DeletePolygon( ii );
}
}
zone->SetFilledPolysList( layer, poly );
@ -709,10 +719,8 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
if( aPad->GetNetCode() > 0 && aPad->GetNetCode() == aZone->GetNetCode() )
{
// For pads having the same netcode as the zone, the net and hole
// clearances have no meanings.
// So just knock out the greater of the zone's local clearance and
// thermal relief.
// For unconnected but same-net pads, electrical clearances don't apply.
// Use the greater of the zone's local clearance and thermal relief.
gap = std::max( zone_clearance, aZone->GetThermalReliefGap( aPad ) );
knockoutHoleClearance = false;
}
@ -767,18 +775,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
int gap = 0;
bool checkHoleClearance = true;
if( via->GetNetCode() > 0 && via->GetNetCode() == aZone->GetNetCode() )
{
// For pads having the same netcode as the zone, the net and hole
// clearances have no meanings.
// So just knock out the zone's local clearance.
gap = zone_clearance;
checkHoleClearance = false;
}
else
{
gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aTrack, aLayer );
}
gap = evalRulesForItems( CLEARANCE_CONSTRAINT, aZone, aTrack, aLayer );
if( via->FlashLayer( aLayer ) )
{
@ -815,7 +812,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
if( !track->IsOnLayer( aLayer ) )
continue;
if( track->GetNetCode() == aZone->GetNetCode() && ( aZone->GetNetCode() != 0) )
if( track->GetNetCode() == aZone->GetNetCode() && ( aZone->GetNetCode() != 0) )
continue;
if( checkForCancel( m_progressReporter ) )
@ -867,8 +864,7 @@ void ZONE_FILLER::buildCopperItemClearances( const ZONE* aZone, PCB_LAYER_ID aLa
knockoutGraphicClearance( &footprint->Reference() );
knockoutGraphicClearance( &footprint->Value() );
// Don't knock out holes in zones that share a net
// with a nettie footprint
// Don't knock out holes in zones that share a net with a nettie footprint
if( footprint->IsNetTie() )
{
for( PAD* pad : footprint->Pads() )