Centralize NPTH has-annulus processing.

Fixes https://gitlab.com/kicad/code/kicad/issues/13437
This commit is contained in:
Jeff Young 2023-04-08 15:02:48 +01:00
parent ffa86db9a9
commit 3b63d70d01
8 changed files with 56 additions and 76 deletions

View File

@ -342,8 +342,7 @@ private:
OBJECT_2D* createPadWithDrill( const PAD* aPad, int aInflateValue );
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads,
bool aSkipNonPlatedPads );
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads );
void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId );

View File

@ -490,41 +490,24 @@ OBJECT_2D* BOARD_ADAPTER::createPadWithDrill( const PAD* aPad, int aInflateValue
void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aContainer,
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper,
bool aSkipPlatedPads, bool aSkipNonPlatedPads )
PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads )
{
for( PAD* pad : aFootprint->Pads() )
{
if( !pad->IsOnLayer( aLayerId ) )
continue;
// Skip pad annulus when not connected on this layer (if removing is enabled)
if( !pad->FlashLayer( aLayerId ) && IsCopperLayer( aLayerId ) )
continue;
// NPTH pads are not drawn on layers if the shape size and pos is the same as their hole:
if( aSkipNPTHPadsWihNoCopper && ( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
if( IsCopperLayer( aLayerId ) )
{
if( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == VECTOR2I( 0, 0 ) )
{
switch( pad->GetShape() )
{
case PAD_SHAPE::CIRCLE:
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
continue;
// Skip pad annulus when there isn't one (note: this is more discerning than
// pad->IsOnLayer(), which doesn't check for NPTH pads with holes that consume
// the entire pad).
if( !pad->IsOnCopperLayer() )
continue;
break;
case PAD_SHAPE::OVAL:
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
continue;
break;
default:
break;
}
}
// Skip pad annulus when not connected on this layer (if removing is enabled)
if( !pad->FlashLayer( aLayerId ) )
continue;
}
VECTOR2I margin( 0, 0 );

View File

@ -525,9 +525,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PADS
for( FOOTPRINT* footprint : m_board->Footprints() )
{
// Note: NPTH pads are not drawn on copper layers when the pad has the same shape
// as its hole
addPads( footprint, layerContainer, layer, true, renderPlatedPadsAsPlated, false );
addPads( footprint, layerContainer, layer, renderPlatedPadsAsPlated, false );
// Micro-wave footprints may have items on copper layers
addFootprintShapes( footprint, layerContainer, layer );
@ -539,8 +537,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PLATED PADS
for( FOOTPRINT* footprint : m_board->Footprints() )
{
addPads( footprint, m_platedPadsFront, F_Cu, true, false, true );
addPads( footprint, m_platedPadsBack, B_Cu, true, false, true );
addPads( footprint, m_platedPadsFront, F_Cu, false, true );
addPads( footprint, m_platedPadsBack, B_Cu, false, true );
}
m_platedPadsFront->BuildBVH();
@ -995,7 +993,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
}
else
{
addPads( footprint, layerContainer, layer, false, false, false );
addPads( footprint, layerContainer, layer, false, false );
}
addFootprintShapes( footprint, layerContainer, layer );

View File

@ -766,6 +766,38 @@ VECTOR2I PAD::ShapePos() const
}
bool PAD::IsOnCopperLayer() const
{
if( GetAttribute() == PAD_ATTRIB::NPTH )
{
// NPTH pads have no plated hole cylinder. If their annular ring size is 0 or
// negative, then they have no annular ring either.
switch( GetShape() )
{
case PAD_SHAPE::CIRCLE:
if( m_offset == VECTOR2I( 0, 0 ) && m_size.x <= m_drill.x )
return false;
break;
case PAD_SHAPE::OVAL:
if( m_offset == VECTOR2I( 0, 0 ) && m_size.x <= m_drill.x && m_size.y <= m_drill.y )
return false;
break;
default:
// We could subtract the hole polygon from the shape polygon for these, but it
// would be expensive and we're probably well out of the common use cases....
break;
}
}
return ( GetLayerSet() & LSET::AllCuMask() ).any();
}
int PAD::GetLocalClearanceOverrides( wxString* aSource ) const
{
// A pad can have specific clearance that overrides its NETCLASS clearance value
@ -817,13 +849,9 @@ int PAD::GetOwnClearance( PCB_LAYER_ID aLayer, wxString* aSource ) const
int PAD::GetSolderMaskExpansion() const
{
// The pad inherits the margin only to calculate a default shape,
// therefore only if it is also a copper layer
// Pads defined only on mask layers (and perhaps on other tech layers) use the shape
// defined by the pad settings only
bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
if( !isOnCopperLayer )
if( !IsOnCopperLayer() )
return 0;
int margin = m_localSolderMaskMargin;
@ -862,13 +890,9 @@ int PAD::GetSolderMaskExpansion() const
VECTOR2I PAD::GetSolderPasteMargin() const
{
// The pad inherits the margin only to calculate a default shape,
// therefore only if it is also a copper layer.
// Pads defined only on mask layers (and perhaps on other tech layers) use the shape
// defined by the pad settings only
bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
if( !isOnCopperLayer )
if( !IsOnCopperLayer() )
return VECTOR2I( 0, 0 );
int margin = m_localSolderPasteMargin;

View File

@ -239,10 +239,7 @@ public:
/**
* @return true if the pad is on any copper layer, false otherwise.
*/
bool IsOnCopperLayer() const override
{
return ( GetLayerSet() & LSET::AllCuMask() ) != 0;
}
bool IsOnCopperLayer() const override;
void SetY( int y ) { m_pos.y = y; SetDirty(); }
void SetX( int x ) { m_pos.x = x; SetDirty(); }

View File

@ -310,6 +310,9 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
}
}
if( onCopperLayer && !pad->IsOnCopperLayer() )
continue;
/// pads not connected to copper are optionally not drawn
if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
continue;

View File

@ -726,9 +726,7 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( const ZONE* aZone, PCB_LAYER_ID aLayer,
GBR_METADATA gbr_metadata;
bool isOnCopperLayer = aZone->IsOnCopperLayer();
if( isOnCopperLayer )
if( aZone->IsOnCopperLayer() )
{
gbr_metadata.SetNetName( aZone->GetNetname() );
gbr_metadata.SetCopper( true );

View File

@ -254,31 +254,9 @@ bool PNS_PCBNEW_RULE_RESOLVER::IsNetTieExclusion( const PNS::ITEM* aItem,
bool isCopper( const PNS::ITEM* aItem )
{
BOARD_ITEM* parent = aItem->Parent();
const BOARD_ITEM *parent = aItem->Parent();
if( parent && parent->Type() == PCB_PAD_T )
{
PAD* pad = static_cast<PAD*>( parent );
if( !pad->IsOnCopperLayer() )
return false;
if( pad->GetAttribute() != PAD_ATTRIB::NPTH )
return true;
// round NPTH with a hole size >= pad size are not on a copper layer
// All other NPTH are seen on copper layers
// This is a basic criteria, but probably enough for a NPTH
if( pad->GetShape() == PAD_SHAPE::CIRCLE )
{
if( pad->GetSize().x <= pad->GetDrillSize().x )
return false;
}
return true;
}
return true;
return !parent || parent->IsOnCopperLayer();
}