From e509fa0fc9170c1ec4790f3c593dba4729199d9a Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sat, 7 Jan 2023 15:20:12 +0000 Subject: [PATCH] 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 --- pcbnew/pad.cpp | 17 ++++++++++++++--- pcbnew/pad.h | 9 ++++++++- pcbnew/pcb_painter.cpp | 16 +++++++++++++++- pcbnew/zone_filler.cpp | 36 +++++++++++++++++++++++------------- 4 files changed, 60 insertions(+), 18 deletions(-) diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index 1eb2c6e13d..c347c49e44 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -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 ); + } } } diff --git a/pcbnew/pad.h b/pcbnew/pad.h index cfff55fb11..5ce61fb3e9 100644 --- a/pcbnew/pad.h +++ b/pcbnew/pad.h @@ -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; diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 0ce3598f92..88eb09f70f 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -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( 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( 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 ); diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index da7cb85d5d..9096eff4ed 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -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 ); } }