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 "???";
}
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 )
{
return m_valueDbl == b->m_valueDbl;
}
else if( m_type == VT_STRING && b->m_type == VT_STRING )
{
if( b->m_stringIsWildcard )
{
return WildCompareString( b->m_valueStr, m_valueStr, false );
}
else
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 str;
@ -1120,7 +1133,7 @@ void UOP::Exec( CONTEXT* ctx )
result = arg1 && arg2 && arg1->EqualTo( arg2 ) ? 1 : 0;
break;
case TR_OP_NOT_EQUAL:
result = arg1 && arg2 && arg1->EqualTo( arg2 ) ? 0 : 1;
result = arg1 && arg2 && arg1->NotEqualTo( arg2 ) ? 1 : 0;
break;
case TR_OP_BOOL_AND:
result = arg1Value != 0.0 && arg2Value != 0.0 ? 1 : 0;

View File

@ -218,6 +218,9 @@ public:
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; };
void Set( double aValue )

View File

@ -277,7 +277,7 @@ protected:
wxAny a = getter( aObject );
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);
}

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
* std::shared_ptr stuff shows up large in performance profiling.
*/
NETCLASS* GetNetClass() const;
virtual NETCLASS* GetNetClass() const;
/**
* 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
* std::shared_ptr stuff shows up large in performance profiling.
*/
NETCLASS* GetEffectiveNetclass() const;
virtual NETCLASS* GetEffectiveNetclass() const;
/**
* Function GetNetClassName
@ -194,7 +194,7 @@ public:
* (should not return a null pointer).
* @return the Net Class name of this item
*/
wxString GetNetClassName() const;
virtual wxString GetNetClassName() const;
void SetLocalRatsnestVisible( bool aVisible )
{

View File

@ -706,10 +706,16 @@ 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* connectedB = dynamic_cast<const BOARD_CONNECTED_ITEM*>( b );
const DRC_CONSTRAINT* constraintRef = nullptr;
bool implicit = false;
const BOARD_CONNECTED_ITEM* ac = a && a->IsConnected() ?
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;
bool implicit = false;
// Local overrides take precedence
if( aConstraintId == CLEARANCE_CONSTRAINT )
@ -717,9 +723,9 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
int overrideA = 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( 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 ) ) )
}
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( 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( 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;
}
}
@ -956,8 +962,8 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
if( constraintRef && aConstraintId == CLEARANCE_CONSTRAINT && implicit )
{
int global = constraintRef->m_Value.Min();
int localA = connectedA ? connectedA->GetLocalClearance( nullptr ) : 0;
int localB = connectedB ? connectedB->GetLocalClearance( nullptr ) : 0;
int localA = ac ? ac->GetLocalClearance( nullptr ) : 0;
int localB = bc ? bc->GetLocalClearance( nullptr ) : 0;
int clearance = global;
if( localA > 0 )
@ -968,7 +974,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
MessageTextFromValue( UNITS, localA ) ) )
if( localA > clearance )
clearance = connectedA->GetLocalClearance( &m_msg );
clearance = ac->GetLocalClearance( &m_msg );
}
if( localB > 0 )
@ -979,7 +985,7 @@ DRC_CONSTRAINT DRC_ENGINE::EvalRulesForItems( DRC_CONSTRAINT_TYPE_T aConstraintI
MessageTextFromValue( UNITS, localB ) ) )
if( localB > clearance )
clearance = connectedB->GetLocalClearance( &m_msg );
clearance = bc->GetLocalClearance( &m_msg );
}
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
// value when the property doesn't appear on a particular object.
return LIBEVAL::VALUE( "UNDEFINED" );
return LIBEVAL::VALUE();
}
else
{
@ -564,7 +564,10 @@ LIBEVAL::VALUE PCB_EXPR_VAR_REF::GetValue( LIBEVAL::CONTEXT* aCtx )
any.GetAs<wxString>( &str );
}
return LIBEVAL::VALUE( str );
if( str == "UNDEFINED" )
return LIBEVAL::VALUE();
else
return LIBEVAL::VALUE( str );
}
}
}

View File

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

View File

@ -77,6 +77,29 @@ public:
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
*/