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 ); OBJECT_2D* createPadWithDrill( const PAD* aPad, int aInflateValue );
void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer, void addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper, bool aSkipPlatedPads, PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads );
bool aSkipNonPlatedPads );
void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer, void addFootprintShapes( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aDstContainer,
PCB_LAYER_ID aLayerId ); 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, void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aContainer,
PCB_LAYER_ID aLayerId, bool aSkipNPTHPadsWihNoCopper, PCB_LAYER_ID aLayerId, bool aSkipPlatedPads, bool aSkipNonPlatedPads )
bool aSkipPlatedPads, bool aSkipNonPlatedPads )
{ {
for( PAD* pad : aFootprint->Pads() ) for( PAD* pad : aFootprint->Pads() )
{ {
if( !pad->IsOnLayer( aLayerId ) ) if( !pad->IsOnLayer( aLayerId ) )
continue; continue;
// Skip pad annulus when not connected on this layer (if removing is enabled) if( IsCopperLayer( aLayerId ) )
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( pad->GetDrillSize() == pad->GetSize() && pad->GetOffset() == VECTOR2I( 0, 0 ) ) // 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
switch( pad->GetShape() ) // the entire pad).
{ if( !pad->IsOnCopperLayer() )
case PAD_SHAPE::CIRCLE: continue;
if( pad->GetDrillShape() == PAD_DRILL_SHAPE_CIRCLE )
continue;
break; // Skip pad annulus when not connected on this layer (if removing is enabled)
if( !pad->FlashLayer( aLayerId ) )
case PAD_SHAPE::OVAL: continue;
if( pad->GetDrillShape() != PAD_DRILL_SHAPE_CIRCLE )
continue;
break;
default:
break;
}
}
} }
VECTOR2I margin( 0, 0 ); VECTOR2I margin( 0, 0 );

View File

@ -525,9 +525,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PADS // ADD PADS
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
{ {
// Note: NPTH pads are not drawn on copper layers when the pad has the same shape addPads( footprint, layerContainer, layer, renderPlatedPadsAsPlated, false );
// as its hole
addPads( footprint, layerContainer, layer, true, renderPlatedPadsAsPlated, false );
// Micro-wave footprints may have items on copper layers // Micro-wave footprints may have items on copper layers
addFootprintShapes( footprint, layerContainer, layer ); addFootprintShapes( footprint, layerContainer, layer );
@ -539,8 +537,8 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
// ADD PLATED PADS // ADD PLATED PADS
for( FOOTPRINT* footprint : m_board->Footprints() ) for( FOOTPRINT* footprint : m_board->Footprints() )
{ {
addPads( footprint, m_platedPadsFront, F_Cu, true, false, true ); addPads( footprint, m_platedPadsFront, F_Cu, false, true );
addPads( footprint, m_platedPadsBack, B_Cu, true, false, true ); addPads( footprint, m_platedPadsBack, B_Cu, false, true );
} }
m_platedPadsFront->BuildBVH(); m_platedPadsFront->BuildBVH();
@ -995,7 +993,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
} }
else else
{ {
addPads( footprint, layerContainer, layer, false, false, false ); addPads( footprint, layerContainer, layer, false, false );
} }
addFootprintShapes( footprint, layerContainer, layer ); 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 int PAD::GetLocalClearanceOverrides( wxString* aSource ) const
{ {
// A pad can have specific clearance that overrides its NETCLASS clearance value // 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 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 // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
// defined by the pad settings only // defined by the pad settings only
bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any(); if( !IsOnCopperLayer() )
if( !isOnCopperLayer )
return 0; return 0;
int margin = m_localSolderMaskMargin; int margin = m_localSolderMaskMargin;
@ -862,13 +890,9 @@ int PAD::GetSolderMaskExpansion() const
VECTOR2I PAD::GetSolderPasteMargin() 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 // Pads defined only on mask layers (and perhaps on other tech layers) use the shape
// defined by the pad settings only // defined by the pad settings only
bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any(); if( !IsOnCopperLayer() )
if( !isOnCopperLayer )
return VECTOR2I( 0, 0 ); return VECTOR2I( 0, 0 );
int margin = m_localSolderPasteMargin; int margin = m_localSolderPasteMargin;

View File

@ -239,10 +239,7 @@ public:
/** /**
* @return true if the pad is on any copper layer, false otherwise. * @return true if the pad is on any copper layer, false otherwise.
*/ */
bool IsOnCopperLayer() const override bool IsOnCopperLayer() const override;
{
return ( GetLayerSet() & LSET::AllCuMask() ) != 0;
}
void SetY( int y ) { m_pos.y = y; SetDirty(); } void SetY( int y ) { m_pos.y = y; SetDirty(); }
void SetX( int x ) { m_pos.x = x; 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 /// pads not connected to copper are optionally not drawn
if( onCopperLayer && !pad->FlashLayer( aLayerMask ) ) if( onCopperLayer && !pad->FlashLayer( aLayerMask ) )
continue; continue;

View File

@ -726,9 +726,7 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( const ZONE* aZone, PCB_LAYER_ID aLayer,
GBR_METADATA gbr_metadata; GBR_METADATA gbr_metadata;
bool isOnCopperLayer = aZone->IsOnCopperLayer(); if( aZone->IsOnCopperLayer() )
if( isOnCopperLayer )
{ {
gbr_metadata.SetNetName( aZone->GetNetname() ); gbr_metadata.SetNetName( aZone->GetNetname() );
gbr_metadata.SetCopper( true ); 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 ) bool isCopper( const PNS::ITEM* aItem )
{ {
BOARD_ITEM* parent = aItem->Parent(); const BOARD_ITEM *parent = aItem->Parent();
if( parent && parent->Type() == PCB_PAD_T ) return !parent || parent->IsOnCopperLayer();
{
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;
} }