Sort synthetic netclass rules by min clearance.

This way when 'A' and 'B' have different netclasses the largest will
fire (rather than just a random one of the two).

Fixes https://gitlab.com/kicad/code/kicad/issues/5926
This commit is contained in:
Jeff Young 2020-10-08 23:40:11 +01:00
parent 38cef95da9
commit 6550e01318
2 changed files with 44 additions and 24 deletions

View File

@ -179,37 +179,32 @@ void DRC_ENGINE::loadImplicitRules()
// 3) per-netclass rules
int ruleCount = 0;
std::vector<DRC_RULE*> netclassRules;
auto makeNetclassRule =
[&]( const NETCLASSPTR& nc, bool isDefault )
[&]( const NETCLASSPTR& netclass, bool isDefault )
{
wxString className = nc->GetName();
wxString expr;
// Only add rules for netclass clearances which are larger than board minimums.
// That way board minimums will still enforce a global minimum.
if( !isDefault )
if( netclass->GetClearance() > bds.m_MinClearance )
{
expr = wxString::Format( "A.NetClass == '%s' || B.NetClass == '%s'",
className, className );
}
DRC_RULE* rule = new DRC_RULE;
wxString name = netclass->GetName();
DRC_RULE_CONDITION* inNetclassCondition = new DRC_RULE_CONDITION ( expr );
DRC_RULE* nc_rule = createImplicitRule( wxString::Format( _( "netclass '%s'" ),
className ));
rule->m_Name = wxString::Format( _( "netclass '%s'" ), name );
rule->m_Implicit = true;
nc_rule->m_Condition = inNetclassCondition;
wxString expr = wxString::Format( "A.NetClass == '%s'", name );
DRC_RULE_CONDITION* condition = new DRC_RULE_CONDITION( expr );
// Only add netclass clearances if they're larger than board minimums. That way
// board minimums will still enforce a global minimum.
rule->m_Condition = condition;
netclassRules.push_back( rule );
if( nc->GetClearance() > bds.m_MinClearance )
{
DRC_CONSTRAINT ncClearanceConstraint( DRC_CONSTRAINT_TYPE_CLEARANCE );
ncClearanceConstraint.Value().SetMin( nc->GetClearance() );
nc_rule->AddConstraint( ncClearanceConstraint );
ncClearanceConstraint.Value().SetMin( netclass->GetClearance() );
rule->AddConstraint( ncClearanceConstraint );
}
ruleCount++;
};
m_board->SynchronizeNetsAndNetClasses();
@ -218,7 +213,20 @@ void DRC_ENGINE::loadImplicitRules()
for( const std::pair<const wxString, NETCLASSPTR>& netclass : bds.GetNetClasses() )
makeNetclassRule( netclass.second, false );
ReportAux( wxString::Format( "Building %d implicit netclass rules", ruleCount ) );
// These have to be sorted by min clearance so the right one fires if 'A' and 'B' belong
// to two different netclasses.
std::sort( netclassRules.begin(), netclassRules.end(),
[]( DRC_RULE* lhs, DRC_RULE* rhs )
{
return lhs->m_Constraints[0].m_Value.Min()
< rhs->m_Constraints[0].m_Value.Min();
} );
for( DRC_RULE* netclassRule : netclassRules )
addRule( netclassRule );
ReportAux( wxString::Format( "Building %d implicit netclass rules", netclassRules.size() ) );
}
static wxString formatConstraint( const DRC_CONSTRAINT& constraint )

View File

@ -271,12 +271,24 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
}
else
{
auto getItemDescription =
[&]( BOARD_ITEM* aItem )
{
wxString s = aItem->GetSelectMenuText( r->GetUnits() );
if( auto* cItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( aItem ) )
s += wxString::Format( _( " [netclass %s]" ), cItem->GetNetClassName() );
return s;
};
r->Report( _( "<h7>Clearance resolution for:</h7>" ) );
r->Report( wxString::Format( _( "<ul><li>Layer %s</li><li>%s</li><li>%s</li></ul>" ),
r->Report( wxString::Format( wxT( "<ul><li>%s %s</li><li>%s</li><li>%s</li></ul>" ),
_( "Layer" ),
m_frame->GetBoard()->GetLayerName( layer ),
a->GetSelectMenuText( r->GetUnits() ),
b->GetSelectMenuText( r->GetUnits() ) ) );
getItemDescription( a ),
getItemDescription( b ) ) );
BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a );
BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b );