Make sure that NPTH pads still get handled in copper clearance checker.
... because that's where we do hole-to-copper clearance testing. Also augments the Clearance Resolution reporter to report on said hole clearances. And changes the interpretation of HOLE_CLEARANCE_CONSTRAINT to include local pad clearance overrides. Fixes https://gitlab.com/kicad/code/kicad/issues/7325
This commit is contained in:
parent
f47e64c47d
commit
56ea55ae9c
|
@ -729,7 +729,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_T aConstraintId,
|
||||||
bool implicit = false;
|
bool implicit = false;
|
||||||
|
|
||||||
// Local overrides take precedence
|
// Local overrides take precedence
|
||||||
if( aConstraintId == CLEARANCE_CONSTRAINT )
|
if( aConstraintId == CLEARANCE_CONSTRAINT || aConstraintId == HOLE_CLEARANCE_CONSTRAINT )
|
||||||
{
|
{
|
||||||
int overrideA = 0;
|
int overrideA = 0;
|
||||||
int overrideB = 0;
|
int overrideB = 0;
|
||||||
|
@ -756,7 +756,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_T aConstraintId,
|
||||||
|
|
||||||
if( overrideA || overrideB )
|
if( overrideA || overrideB )
|
||||||
{
|
{
|
||||||
DRC_CONSTRAINT constraint( CLEARANCE_CONSTRAINT, m_msg );
|
DRC_CONSTRAINT constraint( aConstraintId, m_msg );
|
||||||
constraint.m_Value.SetMin( std::max( overrideA, overrideB ) );
|
constraint.m_Value.SetMin( std::max( overrideA, overrideB ) );
|
||||||
return constraint;
|
return constraint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,7 +122,18 @@ public:
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for( int layer : aItem->GetLayerSet().Seq() )
|
LSET layers = aItem->GetLayerSet();
|
||||||
|
|
||||||
|
// Special-case pad holes which pierce all the copper layers
|
||||||
|
if( aItem->Type() == PCB_PAD_T )
|
||||||
|
{
|
||||||
|
PAD* pad = static_cast<PAD*>( aItem );
|
||||||
|
|
||||||
|
if( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||||
|
layers |= LSET::AllCuMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int layer : layers.Seq() )
|
||||||
addLayer( (PCB_LAYER_ID) layer );
|
addLayer( (PCB_LAYER_ID) layer );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,7 +263,9 @@ int DRC_TEST_PROVIDER::forEachGeometryItem( const std::vector<KICAD_T>& aTypes,
|
||||||
{
|
{
|
||||||
for( PAD* pad : footprint->Pads() )
|
for( PAD* pad : footprint->Pads() )
|
||||||
{
|
{
|
||||||
if( ( pad->GetLayerSet() & aLayers ).any() )
|
// Careful: if a pad has a hole then it pierces all layers
|
||||||
|
if( ( pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0 )
|
||||||
|
|| ( pad->GetLayerSet() & aLayers ).any() )
|
||||||
{
|
{
|
||||||
if( !aFunc( pad ) )
|
if( !aFunc( pad ) )
|
||||||
return n;
|
return n;
|
||||||
|
|
|
@ -282,6 +282,13 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||||
BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
|
BOARD_ITEM* a = static_cast<BOARD_ITEM*>( selection.GetItem( 0 ) );
|
||||||
BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection.GetItem( 1 ) );
|
BOARD_ITEM* b = static_cast<BOARD_ITEM*>( selection.GetItem( 1 ) );
|
||||||
|
|
||||||
|
auto hasHole =
|
||||||
|
[]( BOARD_ITEM* aItem )
|
||||||
|
{
|
||||||
|
PAD* pad = dynamic_cast<PAD*>( aItem );
|
||||||
|
return pad && pad->GetDrillSizeX() > 0 && pad->GetDrillSizeY() > 0;
|
||||||
|
};
|
||||||
|
|
||||||
wxCHECK( a && b, 0 );
|
wxCHECK( a && b, 0 );
|
||||||
|
|
||||||
if( a->Type() == PCB_GROUP_T )
|
if( a->Type() == PCB_GROUP_T )
|
||||||
|
@ -322,16 +329,16 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||||
{
|
{
|
||||||
PAD* pad = static_cast<PAD*>( a );
|
PAD* pad = static_cast<PAD*>( a );
|
||||||
|
|
||||||
if( pad->GetAttribute() == PAD_ATTRIB_SMD && pad->IsOnLayer( F_Cu ) )
|
if( pad->IsOnLayer( F_Cu ) )
|
||||||
layer = F_Cu;
|
layer = F_Cu;
|
||||||
else
|
else
|
||||||
layer = B_Cu;
|
layer = B_Cu;
|
||||||
}
|
}
|
||||||
else if( b->Type() == PCB_PAD_T )
|
else if( b->Type() == PCB_PAD_T && static_cast<PAD*>( a )->GetAttribute() == PAD_ATTRIB_SMD )
|
||||||
{
|
{
|
||||||
PAD* pad = static_cast<PAD*>( b );
|
PAD* pad = static_cast<PAD*>( b );
|
||||||
|
|
||||||
if( pad->GetAttribute() == PAD_ATTRIB_SMD && pad->IsOnLayer( F_Cu ) )
|
if( pad->IsOnLayer( F_Cu ) )
|
||||||
layer = F_Cu;
|
layer = F_Cu;
|
||||||
else
|
else
|
||||||
layer = B_Cu;
|
layer = B_Cu;
|
||||||
|
@ -356,15 +363,45 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
else if( !( a->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() )
|
else if( !( a->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() )
|
||||||
{
|
{
|
||||||
r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
|
if( hasHole( a ) )
|
||||||
a->GetSelectMenuText( r->GetUnits() ),
|
{
|
||||||
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
r->Report( "<h7>" + _( "Hole clearance resolution for:" ) + "</h7>" );
|
||||||
|
|
||||||
|
r->Report( wxString::Format( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>",
|
||||||
|
_( "Layer" ),
|
||||||
|
EscapeHTML( m_frame->GetBoard()->GetLayerName( layer ) ),
|
||||||
|
EscapeHTML( getItemDescription( a ) ),
|
||||||
|
EscapeHTML( getItemDescription( b ) ) ) );
|
||||||
|
|
||||||
|
reportClearance( HOLE_CLEARANCE_CONSTRAINT, layer, a, b, r );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
|
||||||
|
a->GetSelectMenuText( r->GetUnits() ),
|
||||||
|
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( !( b->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() )
|
else if( !( b->GetLayerSet() & LSET( 3, layer, Edge_Cuts, Margin ) ).any() )
|
||||||
{
|
{
|
||||||
r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
|
if( hasHole( b ) )
|
||||||
b->GetSelectMenuText( r->GetUnits() ),
|
{
|
||||||
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
r->Report( "<h7>" + _( "Hole clearance resolution for:" ) + "</h7>" );
|
||||||
|
|
||||||
|
r->Report( wxString::Format( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>",
|
||||||
|
_( "Layer" ),
|
||||||
|
EscapeHTML( m_frame->GetBoard()->GetLayerName( layer ) ),
|
||||||
|
EscapeHTML( getItemDescription( b ) ),
|
||||||
|
EscapeHTML( getItemDescription( a ) ) ) );
|
||||||
|
|
||||||
|
reportClearance( HOLE_CLEARANCE_CONSTRAINT, layer, b, a, r );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r->Report( wxString::Format( _( "%s not present on layer %s. No clearance defined." ),
|
||||||
|
b->GetSelectMenuText( r->GetUnits() ),
|
||||||
|
m_frame->GetBoard()->GetLayerName( layer ) ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if( a->GetLayer() == Edge_Cuts || a->GetLayer() == Margin
|
else if( a->GetLayer() == Edge_Cuts || a->GetLayer() == Margin
|
||||||
|| b->GetLayer() == Edge_Cuts || b->GetLayer() == Margin )
|
|| b->GetLayer() == Edge_Cuts || b->GetLayer() == Margin )
|
||||||
|
|
Loading…
Reference in New Issue