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

(cherry picked from commit 442aae19d9)
This commit is contained in:
Seth Hillbrand 2022-03-16 16:48:24 -07:00
parent bd86999615
commit e33bf78d96
24 changed files with 102 additions and 32 deletions

View File

@ -130,7 +130,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

@ -146,6 +146,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

@ -178,7 +178,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

@ -798,7 +798,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

@ -2013,7 +2013,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>();
@ -2025,12 +2025,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

@ -708,7 +708,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

@ -443,7 +443,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

@ -207,7 +207,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;
wxString GetClass() const override
{

View File

@ -29,10 +29,11 @@
#include <math/util.h> // for KiROUND
#include <eda_draw_frame.h>
#include <geometry/shape_circle.h>
#include <geometry/shape_compound.h>
#include <geometry/shape_null.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_segment.h>
#include <geometry/shape_simple.h>
#include <geometry/shape_rect.h>
#include <geometry/shape_compound.h>
#include <string_utils.h>
#include <i18n_utility.h>
#include <view/view.h>
@ -307,8 +308,26 @@ 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( ( GetAttribute() == PAD_ATTRIB::PTH && aFlash == FLASHING::NEVER_FLASHED )
|| ( aLayer != UNDEFINED_LAYER && !FlashLayer( aLayer ) ) )
{
if( GetAttribute() == PAD_ATTRIB::PTH )
{
BOARD_DESIGN_SETTINGS& bds = GetBoard()->GetDesignSettings();
// Note: drill size represents finish size, which means the actual holes size is the
// plating thickness larger.
auto hole = static_cast<SHAPE_SEGMENT*>( GetEffectiveHoleShape()->Clone() );
hole->SetWidth( hole->GetWidth() + bds.GetHolePlatingThickness() );
return std::make_shared<SHAPE_SEGMENT>( *hole );
}
return std::make_shared<SHAPE_NULL>();
}
if( m_shapesDirty )
BuildEffectiveShapes( aLayer );

View File

@ -423,7 +423,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

@ -354,7 +354,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

@ -127,7 +127,7 @@ void PCB_MARKER::Flip( const wxPoint& 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

@ -84,7 +84,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

@ -189,7 +189,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

@ -94,7 +94,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

@ -213,7 +213,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

@ -135,7 +135,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

@ -998,15 +998,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 );
}
@ -1022,7 +1023,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
@ -293,7 +294,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;
//TODO(snh): Add GetSelectMenuText() and GetMsgPanelInfoBase()
@ -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

@ -1362,7 +1362,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

@ -324,7 +324,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.