A rule zone is not really a BOARD_CONNECTED_ITEM.

Or at least it shouldn't always be treated as one.

Fixes https://gitlab.com/kicad/code/kicad/issues/6382
This commit is contained in:
Jeff Young 2020-11-15 17:48:25 +00:00
parent b227d2b910
commit 1ce1e493d6
8 changed files with 87 additions and 30 deletions

View File

@ -107,16 +107,20 @@ static const wxString formatOpName( int op )
return "???"; return "???";
} }
bool VALUE::EqualTo( const VALUE* b ) const bool VALUE::EqualTo( const VALUE* b ) const
{ {
if( m_type == VT_UNDEFINED || b->m_type == VT_UNDEFINED )
return false;
if( m_type == VT_NUMERIC && b->m_type == VT_NUMERIC ) if( m_type == VT_NUMERIC && b->m_type == VT_NUMERIC )
{
return m_valueDbl == b->m_valueDbl; return m_valueDbl == b->m_valueDbl;
}
else if( m_type == VT_STRING && b->m_type == VT_STRING ) else if( m_type == VT_STRING && b->m_type == VT_STRING )
{ {
if( b->m_stringIsWildcard ) if( b->m_stringIsWildcard )
{
return WildCompareString( b->m_valueStr, m_valueStr, false ); return WildCompareString( b->m_valueStr, m_valueStr, false );
}
else else
return !m_valueStr.CmpNoCase( b->m_valueStr ); return !m_valueStr.CmpNoCase( b->m_valueStr );
} }
@ -125,6 +129,15 @@ bool VALUE::EqualTo( const VALUE* b ) const
} }
bool VALUE::NotEqualTo( const VALUE* b ) const
{
if( m_type == VT_UNDEFINED || b->m_type == VT_UNDEFINED )
return false;
return !EqualTo( b );
}
wxString UOP::Format() const wxString UOP::Format() const
{ {
wxString str; wxString str;
@ -1120,7 +1133,7 @@ void UOP::Exec( CONTEXT* ctx )
result = arg1 && arg2 && arg1->EqualTo( arg2 ) ? 1 : 0; result = arg1 && arg2 && arg1->EqualTo( arg2 ) ? 1 : 0;
break; break;
case TR_OP_NOT_EQUAL: case TR_OP_NOT_EQUAL:
result = arg1 && arg2 && arg1->EqualTo( arg2 ) ? 0 : 1; result = arg1 && arg2 && arg1->NotEqualTo( arg2 ) ? 1 : 0;
break; break;
case TR_OP_BOOL_AND: case TR_OP_BOOL_AND:
result = arg1Value != 0.0 && arg2Value != 0.0 ? 1 : 0; result = arg1Value != 0.0 && arg2Value != 0.0 ? 1 : 0;

View File

@ -218,6 +218,9 @@ public:
virtual bool EqualTo( const VALUE* b ) const; virtual bool EqualTo( const VALUE* b ) const;
// NB: this is not an inverse of EqualTo as they both return false for undefined values.
virtual bool NotEqualTo( const VALUE* b ) const;
VAR_TYPE_T GetType() const { return m_type; }; VAR_TYPE_T GetType() const { return m_type; };
void Set( double aValue ) void Set( double aValue )

View File

@ -277,7 +277,7 @@ protected:
wxAny a = getter( aObject ); wxAny a = getter( aObject );
if ( !( std::is_enum<T>::value && a.CheckType<int>() ) && !a.CheckType<T>() ) if ( !( std::is_enum<T>::value && a.CheckType<int>() ) && !a.CheckType<T>() )
throw std::invalid_argument("Invalid requested type"); throw std::invalid_argument( "Invalid requested type" );
return wxANY_AS(a, T); return wxANY_AS(a, T);
} }

View File

@ -175,7 +175,7 @@ public:
* Note: do NOT return a std::shared_ptr from this. It is used heavily in DRC, and the * Note: do NOT return a std::shared_ptr from this. It is used heavily in DRC, and the
* std::shared_ptr stuff shows up large in performance profiling. * std::shared_ptr stuff shows up large in performance profiling.
*/ */
NETCLASS* GetNetClass() const; virtual NETCLASS* GetNetClass() const;
/** /**
* Function GetEffectiveNetclass * Function GetEffectiveNetclass
@ -184,7 +184,7 @@ public:
* Note: do NOT return a std::shared_ptr from this. It is used heavily in DRC, and the * Note: do NOT return a std::shared_ptr from this. It is used heavily in DRC, and the
* std::shared_ptr stuff shows up large in performance profiling. * std::shared_ptr stuff shows up large in performance profiling.
*/ */
NETCLASS* GetEffectiveNetclass() const; virtual NETCLASS* GetEffectiveNetclass() const;
/** /**
* Function GetNetClassName * Function GetNetClassName
@ -194,7 +194,7 @@ public:
* (should not return a null pointer). * (should not return a null pointer).
* @return the Net Class name of this item * @return the Net Class name of this item
*/ */
wxString GetNetClassName() const; virtual wxString GetNetClassName() const;
void SetLocalRatsnestVisible( bool aVisible ) void SetLocalRatsnestVisible( bool aVisible )
{ {

View File

@ -706,8 +706,14 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
} }
} }
const BOARD_CONNECTED_ITEM* connectedA = dynamic_cast<const BOARD_CONNECTED_ITEM*>( a ); const BOARD_CONNECTED_ITEM* ac = a && a->IsConnected() ?
const BOARD_CONNECTED_ITEM* connectedB = dynamic_cast<const BOARD_CONNECTED_ITEM*>( b ); static_cast<const BOARD_CONNECTED_ITEM*>( a ) : nullptr;
const BOARD_CONNECTED_ITEM* bc = b && b->IsConnected() ?
static_cast<const BOARD_CONNECTED_ITEM*>( b ) : nullptr;
bool a_is_unconnected = a && !ac;
bool b_is_unconnected = b && !bc;
const DRC_CONSTRAINT* constraintRef = nullptr; const DRC_CONSTRAINT* constraintRef = nullptr;
bool implicit = false; bool implicit = false;
@ -717,9 +723,9 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
int overrideA = 0; int overrideA = 0;
int overrideB = 0; int overrideB = 0;
if( connectedA && connectedA->GetLocalClearanceOverrides( nullptr ) > 0 ) if( ac && !b_is_unconnected && ac->GetLocalClearanceOverrides( nullptr ) > 0 )
{ {
overrideA = connectedA->GetLocalClearanceOverrides( &m_msg ); 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." ),
@ -727,9 +733,9 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
MessageTextFromValue( UNITS, overrideA ) ) ) MessageTextFromValue( UNITS, overrideA ) ) )
} }
if( connectedB && connectedB->GetLocalClearanceOverrides( nullptr ) > 0 ) if( bc && !a_is_unconnected && bc->GetLocalClearanceOverrides( nullptr ) > 0 )
{ {
overrideB = connectedB->GetLocalClearanceOverrides( &m_msg ); 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." ),
@ -794,9 +800,9 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
if( aConstraintId == CLEARANCE_CONSTRAINT ) if( aConstraintId == CLEARANCE_CONSTRAINT )
{ {
if( implicit && ( isKeepoutZone( a ) || isKeepoutZone( b ) ) ) if( implicit && ( a_is_unconnected || b_is_unconnected ) )
{ {
REPORT( _( "Board and netclass clearances not applied to keepout zones" ) ); REPORT( _( "Board and netclass clearances apply only to connected items." ) );
return true; return true;
} }
} }
@ -956,8 +962,8 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
if( constraintRef && aConstraintId == CLEARANCE_CONSTRAINT && implicit ) if( constraintRef && aConstraintId == CLEARANCE_CONSTRAINT && implicit )
{ {
int global = constraintRef->m_Value.Min(); int global = constraintRef->m_Value.Min();
int localA = connectedA ? connectedA->GetLocalClearance( nullptr ) : 0; int localA = ac ? ac->GetLocalClearance( nullptr ) : 0;
int localB = connectedB ? connectedB->GetLocalClearance( nullptr ) : 0; int localB = bc ? bc->GetLocalClearance( nullptr ) : 0;
int clearance = global; int clearance = global;
if( localA > 0 ) if( localA > 0 )
@ -968,7 +974,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
MessageTextFromValue( UNITS, localA ) ) ) MessageTextFromValue( UNITS, localA ) ) )
if( localA > clearance ) if( localA > clearance )
clearance = connectedA->GetLocalClearance( &m_msg ); clearance = ac->GetLocalClearance( &m_msg );
} }
if( localB > 0 ) if( localB > 0 )
@ -979,7 +985,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
MessageTextFromValue( UNITS, localB ) ) ) MessageTextFromValue( UNITS, localB ) ) )
if( localB > clearance ) if( localB > clearance )
clearance = connectedB->GetLocalClearance( &m_msg ); clearance = bc->GetLocalClearance( &m_msg );
} }
if( localA > global || localB > global ) if( localA > global || localB > global )

View File

@ -544,7 +544,7 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
// simplier "A.Via_Type == 'buried'" is perfectly clear. Instead, return an undefined // simplier "A.Via_Type == 'buried'" is perfectly clear. Instead, return an undefined
// value when the property doesn't appear on a particular object. // value when the property doesn't appear on a particular object.
return LIBEVAL::VALUE( "UNDEFINED" ); return LIBEVAL::VALUE();
} }
else else
{ {
@ -564,6 +564,9 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
any.GetAs<wxString>( &str ); any.GetAs<wxString>( &str );
} }
if( str == "UNDEFINED" )
return LIBEVAL::VALUE();
else
return LIBEVAL::VALUE( str ); return LIBEVAL::VALUE( str );
} }
} }

View File

@ -212,12 +212,15 @@ void PCB_INSPECTION_TOOL::reportClearance( DRC_CONSTRAINT_TYPE_T aClearanceType,
int clearance = 0; int clearance = 0;
if( aClearanceType == CLEARANCE_CONSTRAINT ) if( aClearanceType == CLEARANCE_CONSTRAINT )
{
if( ( aA && aA->GetLayer() == Edge_Cuts ) || ( aB && aB->GetLayer() == Edge_Cuts ) )
{ {
auto edgeConstraint = drcEngine.EvalRulesForItems( EDGE_CLEARANCE_CONSTRAINT, aA, aB, auto edgeConstraint = drcEngine.EvalRulesForItems( EDGE_CLEARANCE_CONSTRAINT, aA, aB,
aLayer, r ); aLayer, r );
clearance = edgeConstraint.m_Value.HasMin() ? edgeConstraint.m_Value.Min() : 0; clearance = edgeConstraint.m_Value.HasMin() ? edgeConstraint.m_Value.Min() : 0;
} }
}
auto constraint = drcEngine.EvalRulesForItems( aClearanceType, aA, aB, aLayer, r ); auto constraint = drcEngine.EvalRulesForItems( aClearanceType, aA, aB, aLayer, r );
@ -293,8 +296,12 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
{ {
wxString s = aItem->GetSelectMenuText( r->GetUnits() ); wxString s = aItem->GetSelectMenuText( r->GetUnits() );
if( auto* cItem = dynamic_cast<BOARD_CONNECTED_ITEM*>( aItem ) ) if( aItem->IsConnected() )
s += wxS( " " ) + wxString::Format( _( "[netclass %s]" ), cItem->GetNetClassName() ); {
BOARD_CONNECTED_ITEM* cItem = static_cast<BOARD_CONNECTED_ITEM*>( aItem );
s += wxS( " " ) + wxString::Format( _( "[netclass %s]" ),
cItem->GetNetClassName() );
}
return s; return s;
}; };
@ -333,8 +340,10 @@ int PCB_INSPECTION_TOOL::InspectClearance( const TOOL_EVENT& aEvent )
getItemDescription( a ), getItemDescription( a ),
getItemDescription( b ) ) ); getItemDescription( b ) ) );
BOARD_CONNECTED_ITEM* ac = dynamic_cast<BOARD_CONNECTED_ITEM*>( a ); BOARD_CONNECTED_ITEM* ac = a && a->IsConnected() ?
BOARD_CONNECTED_ITEM* bc = dynamic_cast<BOARD_CONNECTED_ITEM*>( b ); static_cast<BOARD_CONNECTED_ITEM*>( a ) : nullptr;
BOARD_CONNECTED_ITEM* bc = b && b->IsConnected() ?
static_cast<BOARD_CONNECTED_ITEM*>( b ) : nullptr;
if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() ) if( ac && bc && ac->GetNetCode() > 0 && ac->GetNetCode() == bc->GetNetCode() )
{ {

View File

@ -77,6 +77,29 @@ public:
return aItem && aItem->Type() == PCB_ZONE_T; return aItem && aItem->Type() == PCB_ZONE_T;
} }
/**
* Not all ZONEs are *really* BOARD_CONNECTED_ITEMs....
*/
bool IsConnected() const override
{
return !GetIsRuleArea();
}
NETCLASS* GetNetClass() const override
{
if( GetIsRuleArea() )
return nullptr;
return BOARD_CONNECTED_ITEM::GetNetClass();
}
wxString GetNetClassName() const override
{
if( GetIsRuleArea() )
return "UNDEFINED";
return BOARD_CONNECTED_ITEM::GetNetClassName();
}
/** /**
* Copy aZone data to me * Copy aZone data to me
*/ */