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:
parent
4da0c897bc
commit
1e23ce1c95
|
@ -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
|
||||||
|
|
|
@ -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" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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,
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
Loading…
Reference in New Issue