Pull some fixes back from 7.0.

1) An earlier 6.0 fix to apply pad clearance overrides to NPTH pads
got broken, so this replaces it.

2) Allow min/max/opt to be set by different rules.

3) Fixes a bug where board minimum enforcement over a local override
didn't get the right message text.
This commit is contained in:
Jeff Young 2021-08-21 01:58:21 +01:00
parent 4da0c897bc
commit 1e23ce1c95
7 changed files with 52547 additions and 47590 deletions

View File

@ -782,49 +782,69 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
bool a_is_non_copper = a && ( !a->IsOnCopperLayer() || isKeepoutZone( a, false ) ); bool a_is_non_copper = a && ( !a->IsOnCopperLayer() || isKeepoutZone( a, false ) );
bool b_is_non_copper = b && ( !b->IsOnCopperLayer() || isKeepoutZone( b, false ) ); bool b_is_non_copper = b && ( !b->IsOnCopperLayer() || isKeepoutZone( b, false ) );
const DRC_CONSTRAINT* constraintRef = nullptr; DRC_CONSTRAINT constraint;
bool implicit = false; constraint.m_Type = aConstraintType;
// Local overrides take precedence over everything *except* board min clearance // Local overrides take precedence over everything *except* board min clearance
if( aConstraintType == CLEARANCE_CONSTRAINT ) if( aConstraintType == CLEARANCE_CONSTRAINT || aConstraintType == HOLE_CLEARANCE_CONSTRAINT )
{ {
int overrideA = 0; int override = 0;
int overrideB = 0;
if( ac && !b_is_non_copper && ac->GetLocalClearanceOverrides( nullptr ) > 0 ) if( ac && !b_is_non_copper )
{
if( int overrideA = ac->GetLocalClearanceOverrides( nullptr ) > 0 )
{ {
overrideA = ac->GetLocalClearanceOverrides( &m_msg );
REPORT( "" ) REPORT( "" )
REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ), REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
EscapeHTML( a->GetSelectMenuText( UNITS ) ), EscapeHTML( a->GetSelectMenuText( UNITS ) ),
REPORT_VALUE( overrideA ) ) ) REPORT_VALUE( overrideA ) ) )
override = ac->GetLocalClearanceOverrides( &m_msg );
}
} }
if( bc && !a_is_non_copper && bc->GetLocalClearanceOverrides( nullptr ) > 0 ) if( bc && !a_is_non_copper )
{
if( int overrideB = bc->GetLocalClearanceOverrides( nullptr ) > 0 )
{ {
overrideB = bc->GetLocalClearanceOverrides( &m_msg );
REPORT( "" ) REPORT( "" )
REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ), REPORT( wxString::Format( _( "Local override on %s; clearance: %s." ),
EscapeHTML( b->GetSelectMenuText( UNITS ) ), EscapeHTML( b->GetSelectMenuText( UNITS ) ),
REPORT_VALUE( overrideB ) ) ) EscapeHTML( REPORT_VALUE( overrideB ) ) ) )
if( overrideB > override )
override = bc->GetLocalClearanceOverrides( &m_msg );
}
} }
if( overrideA || overrideB ) if( override )
{
if( aConstraintType == CLEARANCE_CONSTRAINT )
{ {
int override = std::max( overrideA, overrideB );
if( override < m_designSettings->m_MinClearance ) if( override < m_designSettings->m_MinClearance )
{ {
override = m_designSettings->m_MinClearance; override = m_designSettings->m_MinClearance;
m_msg = _( "board minimum" );
REPORT( "" ) REPORT( "" )
REPORT( wxString::Format( _( "Board minimum clearance: %s." ), REPORT( wxString::Format( _( "Board minimum clearance: %s." ),
REPORT_VALUE( override ) ) ) REPORT_VALUE( override ) ) )
} }
}
else
{
if( override < m_designSettings->m_HoleClearance )
{
override = m_designSettings->m_HoleClearance;
m_msg = _( "board minimum hole" );
DRC_CONSTRAINT constraint( aConstraintType, m_msg ); REPORT( "" )
REPORT( wxString::Format( _( "Board minimum hole clearance: %s." ),
REPORT_VALUE( override ) ) )
}
}
constraint.SetName( m_msg );
constraint.m_Value.SetMin( override ); constraint.m_Value.SetMin( override );
return constraint; return constraint;
} }
@ -833,7 +853,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
auto processConstraint = auto processConstraint =
[&]( const DRC_ENGINE_CONSTRAINT* c ) -> bool [&]( const DRC_ENGINE_CONSTRAINT* c ) -> bool
{ {
implicit = c->parentRule && c->parentRule->m_Implicit; bool implicit = c->parentRule && c->parentRule->m_Implicit;
REPORT( "" ) REPORT( "" )
@ -1021,7 +1041,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
REPORT( implicit ? _( "Unconditional constraint applied." ) REPORT( implicit ? _( "Unconditional constraint applied." )
: _( "Unconditional rule applied." ) ); : _( "Unconditional rule applied." ) );
constraintRef = &c->constraint; constraint = c->constraint;
return true; return true;
} }
else else
@ -1041,7 +1061,22 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
REPORT( implicit ? _( "Constraint applied." ) REPORT( implicit ? _( "Constraint applied." )
: _( "Rule applied; overrides previous constraints." ) ) : _( "Rule applied; overrides previous constraints." ) )
constraintRef = &c->constraint; if( c->constraint.m_Value.HasMin() )
constraint.m_Value.SetMin( c->constraint.m_Value.Min() );
if( c->constraint.m_Value.HasOpt() )
constraint.m_Value.SetOpt( c->constraint.m_Value.Opt() );
if( c->constraint.m_Value.HasMax() )
constraint .m_Value.SetMax( c->constraint.m_Value.Max() );
// While the expectation would be to OR the disallow flags, we've already
// masked them down to aItem's type -- so we're really only looking for a
// boolean here.
constraint.m_DisallowFlags = c->constraint.m_DisallowFlags;
constraint.SetParentRule( c->constraint.GetParentRule() );
return true; return true;
} }
else else
@ -1077,14 +1112,15 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
} }
} }
bool explicitConstraintFound = constraintRef && !implicit; if( constraint.GetParentRule() && !constraint.GetParentRule()->m_Implicit )
return constraint;
// Unfortunately implicit rules don't work for local clearances (such as zones) because // Unfortunately implicit rules don't work for local clearances (such as zones) because
// they have to be max'ed with netclass values (which are already implicit rules), and our // they have to be max'ed with netclass values (which are already implicit rules), and our
// rule selection paradigm is "winner takes all". // rule selection paradigm is "winner takes all".
if( aConstraintType == CLEARANCE_CONSTRAINT && !explicitConstraintFound ) if( aConstraintType == CLEARANCE_CONSTRAINT )
{ {
int global = constraintRef ? constraintRef->m_Value.Min() : 0; int global = constraint.m_Value.Min();
int localA = ac ? ac->GetLocalClearance( nullptr ) : 0; int localA = ac ? ac->GetLocalClearance( nullptr ) : 0;
int localB = bc ? bc->GetLocalClearance( nullptr ) : 0; int localB = bc ? bc->GetLocalClearance( nullptr ) : 0;
int clearance = global; int clearance = global;
@ -1113,16 +1149,20 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRules( DRC_CONSTRAINT_T aConstraintType, const BO
if( localA > global || localB > global ) if( localA > global || localB > global )
{ {
DRC_CONSTRAINT constraint( CLEARANCE_CONSTRAINT, m_msg ); constraint.SetName( m_msg );
constraint.m_Value.SetMin( clearance ); constraint.m_Value.SetMin( clearance );
return constraint; return constraint;
} }
} }
else if( constraint.GetParentRule() )
{
return constraint;
}
static DRC_CONSTRAINT nullConstraint( NULL_CONSTRAINT ); constraint.m_Type = NULL_CONSTRAINT;
nullConstraint.m_DisallowFlags = 0; constraint.m_DisallowFlags = 0;
return constraintRef ? *constraintRef : nullConstraint; return constraint;
#undef REPORT #undef REPORT
#undef UNITS #undef UNITS

View File

@ -318,7 +318,7 @@ wxString DRC_ITEM::GetViolatingRuleDesc() const
{ {
if( m_violatingRule ) if( m_violatingRule )
return wxString::Format( _( "Rule: %s" ), m_violatingRule->m_Name ); return wxString::Format( _( "Rule: %s" ), m_violatingRule->m_Name );
else
return wxEmptyString; return _("Local override" );
} }

View File

@ -125,6 +125,8 @@ class DRC_CONSTRAINT
void SetParentRule( DRC_RULE *aParentRule ) { m_parentRule = aParentRule; } void SetParentRule( DRC_RULE *aParentRule ) { m_parentRule = aParentRule; }
DRC_RULE* GetParentRule() const { return m_parentRule; } DRC_RULE* GetParentRule() const { return m_parentRule; }
void SetName( const wxString& aName ) { m_name = aName; }
wxString GetName() const wxString GetName() const
{ {
if( m_parentRule ) if( m_parentRule )

View File

@ -688,7 +688,7 @@ int PAD::GetLocalClearanceOverrides( wxString* aSource ) const
int PAD::GetLocalClearance( wxString* aSource ) const int PAD::GetLocalClearance( wxString* aSource ) const
{ {
if( aSource ) if( aSource )
*aSource = wxString::Format( _( "pad %s" ), GetName() ); *aSource = _( "pad" );
return m_localClearance; return m_localClearance;
} }

96313
qa/data/issue7325.kicad_pcb Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -101,7 +101,7 @@
"allow_blind_buried_vias": false, "allow_blind_buried_vias": false,
"allow_microvias": false, "allow_microvias": false,
"max_error": 0.005, "max_error": 0.005,
"min_clearance": 0.2032, "min_clearance": 0.17779999999999999,
"min_copper_edge_clearance": 0.19999999999999998, "min_copper_edge_clearance": 0.19999999999999998,
"min_hole_clearance": 0.0, "min_hole_clearance": 0.0,
"min_hole_to_hole": 0.25, "min_hole_to_hole": 0.25,

View File

@ -110,7 +110,7 @@ BOOST_FIXTURE_TEST_CASE( DRCFalseNegativeRegressions, DRC_REGRESSION_TEST_FIXTUR
{ "issue6945", 2 }, { "issue6945", 2 },
{ "issue7241", 1 }, { "issue7241", 1 },
{ "issue7267", 4 }, { "issue7267", 4 },
{ "issue7325", 21 }, { "issue7325", 2 },
{ "issue8003", 2 } }; { "issue8003", 2 } };
for( const std::pair<wxString, int>& entry : tests ) for( const std::pair<wxString, int>& entry : tests )