Don't depend on a pad being connected to a non-zone when filling zones.

If the pad hasn't already been owned by another zone, and the zone we're
currently filling can connect to it, then we want to try to flash it even
if it's not connected to anything else.

Fixes https://gitlab.com/kicad/code/kicad/issues/13415
This commit is contained in:
Jeff Young 2023-01-07 15:20:12 +00:00
parent 53dedb2c99
commit e509fa0fc9
4 changed files with 60 additions and 18 deletions

View File

@ -247,7 +247,7 @@ bool PAD::FlashLayer( LSET aLayers ) const
}
bool PAD::FlashLayer( int aLayer ) const
bool PAD::FlashLayer( int aLayer, bool aOnlyCheckIfPermitted ) const
{
if( aLayer == UNDEFINED_LAYER )
return true;
@ -304,9 +304,20 @@ bool PAD::FlashLayer( int aLayer ) const
// clearance.
// See https://gitlab.com/kicad/code/kicad/-/issues/11299.
if( m_zoneLayerConnections[ aLayer ] == ZLC_CONNECTED )
{
return true;
return board->GetConnectivity()->IsConnectedOnLayer( this, aLayer, types );
}
else if( m_zoneLayerConnections[ aLayer ] == ZLC_UNCONNECTED )
{
return false;
}
else /* ZLC_UNRESOLVED */
{
if( aOnlyCheckIfPermitted )
return true;
else
return board->GetConnectivity()->IsConnectedOnLayer( this, aLayer, types );
}
}
}

View File

@ -631,9 +631,16 @@ public:
* Check to see whether the pad should be flashed on the specific layer.
*
* @param aLayer Layer to check for connectivity
* @param aOnlyCheckIfPermitted indicates that the routine should just return whether or not
* a flashed connection is permitted on this layer (without checking for a connection)
* @return true if connected by pad or track (or optionally zone)
*/
bool FlashLayer( int aLayer ) const;
bool FlashLayer( int aLayer, bool aOnlyCheckIfPermitted = false ) const;
bool CanFlashLayer( int aLayer )
{
return FlashLayer( aLayer, true );
}
PCB_LAYER_ID GetLayer() const override;

View File

@ -305,6 +305,7 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) cons
{
PCB_LAYER_ID primary = GetPrimaryHighContrastLayer();
bool isActive = m_highContrastLayers.count( aLayer );
bool hide = false;
switch( originalLayer )
{
@ -313,7 +314,10 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) cons
const PAD* pad = static_cast<const PAD*>( item );
if( !pad->FlashLayer( primary ) )
{
isActive = false;
hide = true;
}
if( m_PadEditModePad && pad != m_PadEditModePad )
isActive = false;
@ -328,7 +332,10 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) cons
// Target graphic is active if the via crosses the primary layer
if( via->GetLayerSet().test( primary ) == 0 )
{
isActive = false;
hide = true;
}
break;
}
@ -338,7 +345,10 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) cons
const PCB_VIA* via = static_cast<const PCB_VIA*>( item );
if( !via->FlashLayer( primary ) )
{
isActive = false;
hide = true;
}
break;
}
@ -380,8 +390,12 @@ COLOR4D PCB_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) cons
if( !isActive )
{
if( m_ContrastModeDisplay == HIGH_CONTRAST_MODE::HIDDEN || IsNetnameLayer( aLayer ) )
if( m_ContrastModeDisplay == HIGH_CONTRAST_MODE::HIDDEN
|| IsNetnameLayer( aLayer )
|| hide )
{
color = COLOR4D::CLEAR;
}
else
{
color = color.Mix( m_layerColors[LAYER_PCB_BACKGROUND], m_hiContrastFactor );

View File

@ -734,10 +734,16 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer
constraint = bds.m_DRCEngine->EvalRules( THERMAL_RELIEF_GAP_CONSTRAINT, pad, aZone,
aLayer );
padClearance = constraint.GetValue().Min();
holeClearance = padClearance;
if( pad->FlashLayer( aLayer ) )
if( pad->CanFlashLayer( aLayer ) )
{
aThermalConnectionPads.push_back( pad );
addKnockout( pad, aLayer, padClearance, holes );
}
else if( pad->GetDrillSize().x > 0 )
{
pad->TransformHoleToPolygon( holes, padClearance, m_maxError, ERROR_OUTSIDE );
}
break;
@ -750,13 +756,22 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer
else
padClearance = aZone->GetLocalClearance();
constraint = bds.m_DRCEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT, pad,
aZone, aLayer );
if( pad->FlashLayer( aLayer ) )
{
addKnockout( pad, aLayer, padClearance, holes );
}
else if( pad->GetDrillSize().x > 0 )
{
constraint = bds.m_DRCEngine->EvalRules( PHYSICAL_HOLE_CLEARANCE_CONSTRAINT,
pad, aZone, aLayer );
if( constraint.GetValue().Min() > padClearance )
holeClearance = constraint.GetValue().Min();
else
holeClearance = padClearance;
if( constraint.GetValue().Min() > padClearance )
holeClearance = constraint.GetValue().Min();
else
holeClearance = padClearance;
pad->TransformHoleToPolygon( holes, holeClearance, m_maxError, ERROR_OUTSIDE );
}
break;
@ -764,11 +779,6 @@ void ZONE_FILLER::knockoutThermalReliefs( const ZONE* aZone, PCB_LAYER_ID aLayer
// No knockout
continue;
}
if( pad->FlashLayer( aLayer ) )
addKnockout( pad, aLayer, padClearance, holes );
else if( pad->GetDrillSize().x > 0 )
pad->TransformHoleToPolygon( holes, holeClearance, m_maxError, ERROR_OUTSIDE );
}
}