7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-07 22:05:32 +00:00

Report global physical_clearance issues before moving on to layers.

Also fixes a bug in reading m_LayerSource.

Also simplifies Edge_Cuts handling to better match
actual DRC checks.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20498
This commit is contained in:
Jeff Young 2025-03-30 14:21:47 +01:00
parent 33ee9e99fe
commit 9066ad3620
3 changed files with 65 additions and 53 deletions

View File

@ -315,8 +315,8 @@ std::shared_ptr<DRC_RULE> DRC_RULES_PARSER::parseDRC_RULE()
case T_layer:
if( rule->m_LayerCondition != LSET::AllLayersMask() )
reportError( _( "'layer' keyword already present." ) );
rule->m_LayerSource = FromUTF8();
rule->m_LayerCondition = parseLayer();
rule->m_LayerCondition = parseLayer( &rule->m_LayerSource );
break;
case T_severity:
@ -765,7 +765,7 @@ void DRC_RULES_PARSER::parseValueWithUnits( const wxString& aExpr, int& aResult,
}
LSET DRC_RULES_PARSER::parseLayer()
LSET DRC_RULES_PARSER::parseLayer( wxString* aSource )
{
LSET retVal;
int token = NextTok();
@ -777,10 +777,12 @@ LSET DRC_RULES_PARSER::parseLayer()
}
else if( token == T_outer )
{
*aSource = GetTokenString( token );
retVal = LSET::ExternalCuMask();
}
else if( token == T_inner )
{
*aSource = GetTokenString( token );
retVal = LSET::InternalCuMask();
}
else
@ -793,7 +795,10 @@ LSET DRC_RULES_PARSER::parseLayer()
wxPGChoiceEntry& entry = layerMap[ii];
if( entry.GetText().Matches( layerName ) )
{
*aSource = layerName;
retVal.set( ToLAYER_ID( entry.GetValue() ) );
}
}
if( !retVal.any() )

View File

@ -56,7 +56,7 @@ private:
void parseConstraint( DRC_RULE* aRule );
void parseValueWithUnits( const wxString& aExpr, int& aResult, bool aUnitless = false );
LSET parseLayer();
LSET parseLayer( wxString* aSource );
SEVERITY parseSeverity();
void parseUnknown();

View File

@ -1218,60 +1218,67 @@ int BOARD_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
r = dialog->AddHTMLPage( _( "Physical Clearances" ) );
auto reportPhysicalClearance =
[&]( PCB_LAYER_ID aLayer )
if( compileError )
{
reportCompileError( r );
}
else if( !drcEngine->HasRulesForConstraintType( PHYSICAL_CLEARANCE_CONSTRAINT ) )
{
r->Report( "" );
r->Report( _( "No 'physical_clearance' constraints defined." ) );
}
else
{
LSET reportLayers = layerIntersection;
bool reported = false;
if( a->IsOnLayer( Edge_Cuts ) )
{
LSET edgeInteractingLayers = bFP ? LSET( { F_CrtYd, B_CrtYd } )
: LSET( b->GetLayerSet() & LSET::PhysicalLayersMask() );
reportLayers |= edgeInteractingLayers;
}
if( b->IsOnLayer( Edge_Cuts ) )
{
LSET edgeInteractingLayers = aFP ? LSET( { F_CrtYd, B_CrtYd } )
: LSET( a->GetLayerSet() & LSET::PhysicalLayersMask() );
reportLayers |= edgeInteractingLayers;
}
for( PCB_LAYER_ID layer : reportLayers )
{
reported = true;
reportHeader( _( "Physical clearance resolution for:" ), a, b, layer, r );
constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, layer, r );
clearance = constraint.m_Value.Min();
if( constraint.IsNull() )
{
reportHeader( _( "Physical clearance resolution for:" ), a, b, aLayer, r );
constraint = drcEngine->EvalRules( PHYSICAL_CLEARANCE_CONSTRAINT, a, b, aLayer, r );
clearance = constraint.m_Value.Min();
if( compileError )
{
reportCompileError( r );
}
else if( !drcEngine->HasRulesForConstraintType( PHYSICAL_CLEARANCE_CONSTRAINT ) )
{
r->Report( "" );
r->Report( _( "No 'physical_clearance' constraints defined." ) );
}
else
{
r->Report( "" );
r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
m_frame->StringFromValue( clearance, true ) ) );
}
r->Report( "" );
r->Report( wxString::Format( _( "No 'physical_clearance' constraints in effect on %s." ),
m_frame->GetBoard()->GetLayerName( layer ) ) );
}
else
{
r->Report( "" );
r->Report( "" );
};
r->Report( wxString::Format( _( "Resolved min clearance: %s." ),
m_frame->StringFromValue( clearance, true ) ) );
}
if( layerIntersection.any() )
{
PCB_LAYER_ID layer = active;
r->Report( "" );
r->Report( "" );
r->Report( "" );
}
if( !layerIntersection.test( layer ) )
layer = layerIntersection.Seq().front();
reportPhysicalClearance( layer );
}
if( aFP && b->IsOnLayer( Edge_Cuts ) )
{
if( !aFP->GetCourtyard( F_CrtYd ).IsEmpty() )
reportPhysicalClearance( F_CrtYd );
if( !aFP->GetCourtyard( B_CrtYd ).IsEmpty() )
reportPhysicalClearance( B_CrtYd );
}
else if( bFP && a->IsOnLayer( Edge_Cuts ) )
{
if( !bFP->GetCourtyard( F_CrtYd ).IsEmpty() )
reportPhysicalClearance( F_CrtYd );
if( !bFP->GetCourtyard( B_CrtYd ).IsEmpty() )
reportPhysicalClearance( B_CrtYd );
if( !reported )
{
reportHeader( _( "Physical clearance resolution for:" ), a, b, r );
r->Report( "" );
r->Report( _( "Items share no relevant layers. No 'physical_clearance' constraints will "
"be applied." ) );
}
}
if( a->HasHole() || b->HasHole() )