From e28f6ecc00f05a238a5a0eb024ea3c6db33da836 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Wed, 21 Dec 2022 18:20:04 +0000 Subject: [PATCH] Fetch a better location for keepout area collsions. Fixes https://gitlab.com/kicad/code/kicad/issues/13220 --- common/kiid.cpp | 14 ++++++++---- pcbnew/drc/drc_engine.cpp | 4 +++- pcbnew/drc/drc_rule.cpp | 2 ++ pcbnew/drc/drc_rule.h | 2 ++ pcbnew/drc/drc_test_provider_disallow.cpp | 26 ++++++++++++++++++----- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/common/kiid.cpp b/common/kiid.cpp index cd6f8acc56..a9a4c63f9a 100644 --- a/common/kiid.cpp +++ b/common/kiid.cpp @@ -101,13 +101,17 @@ KIID::KIID() } -KIID::KIID( int null ) : m_uuid( nilGenerator() ), m_cached_timestamp( 0 ) +KIID::KIID( int null ) : + m_uuid( nilGenerator() ), + m_cached_timestamp( 0 ) { wxASSERT( null == 0 ); } -KIID::KIID( const std::string& aString ) : m_uuid(), m_cached_timestamp( 0 ) +KIID::KIID( const std::string& aString ) : + m_uuid(), + m_cached_timestamp( 0 ) { if( aString.length() == 8 && std::all_of( aString.begin(), aString.end(), @@ -160,12 +164,14 @@ KIID::KIID( const std::string& aString ) : m_uuid(), m_cached_timestamp( 0 ) } -KIID::KIID( const char* aString ) : KIID( std::string( aString ) ) +KIID::KIID( const char* aString ) : + KIID( std::string( aString ) ) { } -KIID::KIID( const wxString& aString ) : KIID( std::string( aString.ToUTF8() ) ) +KIID::KIID( const wxString& aString ) : + KIID( std::string( aString.ToUTF8() ) ) { } diff --git a/pcbnew/drc/drc_engine.cpp b/pcbnew/drc/drc_engine.cpp index 6cb0b124f8..977dde1c0d 100644 --- a/pcbnew/drc/drc_engine.cpp +++ b/pcbnew/drc/drc_engine.cpp @@ -423,7 +423,9 @@ void DRC_ENGINE::loadImplicitRules() else rule = createImplicitRule( wxString::Format( _( "keepout area '%s'" ), name ) ); - rule->m_Condition = new DRC_RULE_CONDITION( wxString::Format( wxT( "A.insideArea('%s')" ), + rule->m_ImplicitItemId = zone->m_Uuid; + + rule->m_Condition = new DRC_RULE_CONDITION( wxString::Format( wxT( "A.intersectsArea('%s')" ), zone->m_Uuid.AsString() ) ); rule->m_LayerCondition = zone->GetLayerSet(); diff --git a/pcbnew/drc/drc_rule.cpp b/pcbnew/drc/drc_rule.cpp index acd3a3ed77..2e2574e7e8 100644 --- a/pcbnew/drc/drc_rule.cpp +++ b/pcbnew/drc/drc_rule.cpp @@ -31,6 +31,7 @@ DRC_RULE::DRC_RULE() : m_Unary( false ), m_Implicit( false ), + m_ImplicitItemId( 0 ), m_LayerCondition( LSET::AllLayersMask() ), m_Condition( nullptr ), m_Severity( RPT_SEVERITY_UNDEFINED ) @@ -41,6 +42,7 @@ DRC_RULE::DRC_RULE() : DRC_RULE::DRC_RULE( const wxString& aName ) : m_Unary( false ), m_Implicit( false ), + m_ImplicitItemId( 0 ), m_Name( aName ), m_LayerCondition( LSET::AllLayersMask() ), m_Condition( nullptr ), diff --git a/pcbnew/drc/drc_rule.h b/pcbnew/drc/drc_rule.h index 2a4929d36d..62d79c4d16 100644 --- a/pcbnew/drc/drc_rule.h +++ b/pcbnew/drc/drc_rule.h @@ -24,6 +24,7 @@ #ifndef DRC_RULE_PROTO_H #define DRC_RULE_PROTO_H +#include #include #include #include @@ -107,6 +108,7 @@ public: public: bool m_Unary; bool m_Implicit; + KIID m_ImplicitItemId; wxString m_Name; wxString m_LayerSource; LSET m_LayerCondition; diff --git a/pcbnew/drc/drc_test_provider_disallow.cpp b/pcbnew/drc/drc_test_provider_disallow.cpp index b755dbb458..70aa256508 100644 --- a/pcbnew/drc/drc_test_provider_disallow.cpp +++ b/pcbnew/drc/drc_test_provider_disallow.cpp @@ -214,20 +214,36 @@ bool DRC_TEST_PROVIDER_DISALLOW::Run() if( constraint.m_DisallowFlags && constraint.GetSeverity() != RPT_SEVERITY_IGNORE ) { std::shared_ptr drcItem = DRC_ITEM::Create( DRCE_ALLOWED_ITEMS ); - wxString msg; + DRC_RULE* rule = constraint.GetParentRule(); + VECTOR2I pos = item->GetPosition(); + PCB_LAYER_ID layer = UNDEFINED_LAYER; + wxString msg; msg.Printf( drcItem->GetErrorText() + wxS( " (%s)" ), constraint.GetName() ); drcItem->SetErrorMessage( msg ); drcItem->SetItems( item ); - drcItem->SetViolatingRule( constraint.GetParentRule() ); - - PCB_LAYER_ID layer = UNDEFINED_LAYER; + drcItem->SetViolatingRule( rule ); if( item->GetLayerSet().count() ) layer = item->GetLayerSet().Seq().front(); - reportViolation( drcItem, item->GetPosition(), layer ); + if( rule->m_Implicit ) + { + // Provide a better location for keepout area collisions. + BOARD_ITEM* ruleItem = board->GetItem( rule->m_ImplicitItemId ); + + if( ZONE* keepout = dynamic_cast( ruleItem ) ) + { + std::shared_ptr shape = item->GetEffectiveShape( layer ); + int dummyActual; + + keepout->Outline()->Collide( shape.get(), board->m_DRCMaxClearance, + &dummyActual, &pos ); + } + } + + reportViolation( drcItem, pos, layer ); } };