Separate flashing check for connectivity

When building the connectivity database, we should not be using the
connectivity to check for shapes.

To make this deterministic, we introduce two flags (ALWAYS_FLASH and
NEVER_FLASH) that are used with connectivity building to determine
whether a pad is flashed for connectivity or not.  ZONE <-> PAD/VIA
connectivity will be checked with ALWAYS_FLASHED and all other
connectivity will be checked with NEVER_FLASHED if they are marked for
potential annular ring removal.  If they are not marked for removal,
they will be checked ALWAYS_FLASHED.

Fixes https://gitlab.com/kicad/code/kicad/issues/11114
This commit is contained in:
Seth Hillbrand 2022-03-16 16:48:24 -07:00
parent e68e2e973e
commit 442aae19d9
28 changed files with 100 additions and 36 deletions

View File

@ -134,7 +134,8 @@ public:
* @param aLayer in case of items spanning multiple layers, only the shapes belonging to aLayer
* will be returned. Pass UNDEFINED_LAYER to return shapes for all layers.
*/
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const;
BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_parent; }

View File

@ -139,6 +139,17 @@ enum PCB_LAYER_ID: int
#define MAX_CU_LAYERS (B_Cu - F_Cu + 1)
/**
* Enum used during connectivity building to ensure we do not query connectivity while building
* the database
*/
enum class FLASHING
{
DEFAULT, // Flashing follows connectivity
ALWAYS_FLASHED, // Always flashed for connectivity
NEVER_FLASHED, // Never flashed for connectivity
};
/// Dedicated layers for net names used in Pcbnew
enum NETNAMES_LAYER_ID: int
{

View File

@ -194,7 +194,7 @@ bool BOARD_ITEM::ptr_cmp::operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b
}
std::shared_ptr<SHAPE> BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
std::shared_ptr<SHAPE> shape;

View File

@ -769,6 +769,16 @@ void CN_VISITOR::checkZoneItemConnection( CN_ZONE_LAYER* aZoneLayer, CN_ITEM* aI
}
}
if( aItem->Parent()->Type() == PCB_VIA_T || aItem->Parent()->Type() == PCB_PAD_T )
{
// As long as the pad/via crosses the zone layer, check for the full effective shape
// We check for the overlapping layers above
if( aZoneLayer->Collide( aItem->Parent()->GetEffectiveShape( layer, FLASHING::ALWAYS_FLASHED ).get() ) )
connect();
return;
}
if( aZoneLayer->Collide( aItem->Parent()->GetEffectiveShape( layer ).get() ) )
connect();
}
@ -867,7 +877,33 @@ bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
for( PCB_LAYER_ID layer : commonLayers.Seq() )
{
if( parentA->GetEffectiveShape( layer )->Collide( parentB->GetEffectiveShape( layer ).get() ) )
FLASHING flashingA = FLASHING::NEVER_FLASHED;
FLASHING flashingB = FLASHING::NEVER_FLASHED;
if( const PAD* pad = dyn_cast<const PAD*>( parentA ) )
{
if( !pad->GetRemoveUnconnected() || ( ( layer == F_Cu || layer == B_Cu ) && pad->GetKeepTopBottom() ) )
flashingA = FLASHING::ALWAYS_FLASHED;
}
else if( const PCB_VIA* via = dyn_cast<const PCB_VIA*>( parentA ) )
{
if( !via->GetRemoveUnconnected() || ( ( layer == F_Cu || layer == B_Cu ) && via->GetKeepTopBottom() ) )
flashingA = FLASHING::ALWAYS_FLASHED;
}
if( const PAD* pad = dyn_cast<const PAD*>( parentB ) )
{
if( !pad->GetRemoveUnconnected() || ( ( layer == F_Cu || layer == B_Cu ) && pad->GetKeepTopBottom() ) )
flashingB = FLASHING::ALWAYS_FLASHED;
}
else if( const PCB_VIA* via = dyn_cast<const PCB_VIA*>( parentB ) )
{
if( !via->GetRemoveUnconnected() || ( ( layer == F_Cu || layer == B_Cu ) && via->GetKeepTopBottom() ) )
flashingB = FLASHING::ALWAYS_FLASHED;
}
if( parentA->GetEffectiveShape( layer, flashingA )->Collide(
parentB->GetEffectiveShape( layer, flashingB ).get() ) )
{
m_item->Connect( aCandidate );
aCandidate->Connect( m_item );

View File

@ -2100,7 +2100,7 @@ double FOOTPRINT::CoverageRatio( const GENERAL_COLLECTOR& aCollector ) const
}
std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
std::shared_ptr<SHAPE_COMPOUND> shape = std::make_shared<SHAPE_COMPOUND>();
@ -2112,12 +2112,12 @@ std::shared_ptr<SHAPE> FOOTPRINT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
// We'll go with (2) for now....
for( PAD* pad : Pads() )
shape->AddShape( pad->GetEffectiveShape( aLayer )->Clone() );
shape->AddShape( pad->GetEffectiveShape( aLayer, aFlash )->Clone() );
for( BOARD_ITEM* item : GraphicalItems() )
{
if( item->Type() == PCB_FP_SHAPE_T )
shape->AddShape( item->GetEffectiveShape( aLayer )->Clone() );
shape->AddShape( item->GetEffectiveShape( aLayer, aFlash )->Clone() );
}
return shape;

View File

@ -700,7 +700,8 @@ public:
*/
void BuildPolyCourtyards( OUTLINE_ERROR_HANDLER* aErrorHandler = nullptr );
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
virtual void SwapData( BOARD_ITEM* aImage ) override;

View File

@ -438,7 +438,7 @@ wxString FP_TEXT::GetShownText( int aDepth ) const
}
std::shared_ptr<SHAPE> FP_TEXT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> FP_TEXT::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
return GetEffectiveTextShape();
}

View File

@ -169,7 +169,8 @@ public:
int aError, ERROR_LOC aErrorLoc ) const;
// @copydoc BOARD_ITEM::GetEffectiveShape
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
wxString GetClass() const override
{

View File

@ -323,7 +323,7 @@ wxString FP_TEXTBOX::GetShownText( int aDepth ) const
}
std::shared_ptr<SHAPE> FP_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> FP_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
return GetEffectiveTextShape();
}

View File

@ -111,7 +111,8 @@ public:
int aError, ERROR_LOC aErrorLoc ) const;
// @copydoc BOARD_ITEM::GetEffectiveShape
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
wxString GetClass() const override
{

View File

@ -325,9 +325,10 @@ const std::shared_ptr<SHAPE_POLY_SET>& PAD::GetEffectivePolygon() const
}
std::shared_ptr<SHAPE> PAD::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PAD::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
if( aLayer != UNDEFINED_LAYER && !FlashLayer( aLayer ) )
if( ( GetAttribute() == PAD_ATTRIB::PTH && aFlash == FLASHING::NEVER_FLASHED )
|| ( aLayer != UNDEFINED_LAYER && !FlashLayer( aLayer ) ) )
{
if( GetAttribute() == PAD_ATTRIB::PTH )
{

View File

@ -424,7 +424,8 @@ public:
int aError, ERROR_LOC aErrorLoc ) const;
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
const std::shared_ptr<SHAPE_POLY_SET>& GetEffectivePolygon() const;

View File

@ -338,7 +338,7 @@ void PCB_DIMENSION_BASE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame,
}
std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_DIMENSION_BASE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
std::shared_ptr<SHAPE_COMPOUND> effectiveShape = std::make_shared<SHAPE_COMPOUND>();

View File

@ -242,7 +242,8 @@ public:
const EDA_RECT GetBoundingBox() const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer ) const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;

View File

@ -176,7 +176,7 @@ void PCB_MARKER::Flip( const VECTOR2I& aCentre, bool aFlipLeftRight )
}
std::shared_ptr<SHAPE> PCB_MARKER::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_MARKER::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
// Markers do not participate in the board geometry space, and therefore have no
// effectiven shape.

View File

@ -88,7 +88,8 @@ public:
GAL_LAYER_ID GetColorLayer() const;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer ) const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;

View File

@ -241,7 +241,7 @@ const BOX2I PCB_SHAPE::ViewBBox() const
}
std::shared_ptr<SHAPE> PCB_SHAPE::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_SHAPE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
return std::make_shared<SHAPE_COMPOUND>( MakeEffectiveShapes() );
}

View File

@ -105,7 +105,8 @@ public:
/**
* Make a set of SHAPE objects representing the PCB_SHAPE. Caller owns the objects.
*/
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;

View File

@ -113,7 +113,7 @@ const EDA_RECT PCB_TARGET::GetBoundingBox() const
}
std::shared_ptr<SHAPE> PCB_TARGET::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_TARGET::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
return std::make_shared<SHAPE_CIRCLE>( m_pos, m_size / 2 );
}

View File

@ -84,7 +84,8 @@ public:
// Virtual function
const EDA_RECT GetBoundingBox() const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer ) const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;

View File

@ -233,7 +233,7 @@ void PCB_TEXT::SwapData( BOARD_ITEM* aImage )
}
std::shared_ptr<SHAPE> PCB_TEXT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_TEXT::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
return GetEffectiveTextShape();
}

View File

@ -133,7 +133,8 @@ public:
bool aIgnoreLineWidth = false ) const override;
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;

View File

@ -295,10 +295,10 @@ void PCB_TEXTBOX::SwapData( BOARD_ITEM* aImage )
}
std::shared_ptr<SHAPE> PCB_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
if( PCB_SHAPE::GetStroke().GetWidth() >= 0 )
return PCB_SHAPE::GetEffectiveShape( aLayer );
return PCB_SHAPE::GetEffectiveShape( aLayer, aFlash );
else
return GetEffectiveTextShape();
}

View File

@ -112,7 +112,8 @@ public:
bool aIgnoreLineWidth = false ) const override;
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;

View File

@ -1060,15 +1060,16 @@ bool PCB_TRACK::cmp_tracks::operator() ( const PCB_TRACK* a, const PCB_TRACK* b
}
std::shared_ptr<SHAPE> PCB_TRACK::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_TRACK::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
return std::make_shared<SHAPE_SEGMENT>( m_Start, m_End, m_Width );
}
std::shared_ptr<SHAPE> PCB_VIA::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_VIA::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
if( FlashLayer( aLayer ) )
if( aFlash == FLASHING::ALWAYS_FLASHED
|| ( aFlash == FLASHING::DEFAULT && FlashLayer( aLayer ) ) )
{
return std::make_shared<SHAPE_CIRCLE>( m_Start, m_Width / 2 );
}
@ -1084,7 +1085,7 @@ std::shared_ptr<SHAPE> PCB_VIA::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
}
std::shared_ptr<SHAPE> PCB_ARC::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> PCB_ARC::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
return std::make_shared<SHAPE_ARC>( GetStart(), GetMid(), GetEnd(), GetWidth() );
}

View File

@ -149,7 +149,8 @@ public:
bool ignoreLineWidth = false ) const override;
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
/**
* Function IsPointOnEnds
@ -295,7 +296,8 @@ public:
}
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
/**
* Function GetLength
@ -490,7 +492,8 @@ public:
void SwapData( BOARD_ITEM* aImage ) override;
// @copydoc BOARD_ITEM::GetEffectiveShape
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
protected:
wxString layerMaskDescribe() const override;

View File

@ -1286,7 +1286,7 @@ double FP_ZONE::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const
}
std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
std::shared_ptr<SHAPE> ZONE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
{
std::shared_ptr<SHAPE> shape;

View File

@ -334,7 +334,8 @@ public:
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE>
GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER,
FLASHING aFlash = FLASHING::DEFAULT ) const override;
/**
* Test if a point is near an outline edge or a corner of this zone.