From 9547c72e738d25d0eaf85db7b20852e4a9c5719b Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 26 Nov 2021 23:01:53 +0000 Subject: [PATCH] Teach router about different keepout rules. Fixes https://gitlab.com/kicad/code/kicad/issues/9786 --- include/board_item.h | 2 ++ pcbnew/board_item.cpp | 11 +++++++++++ pcbnew/router/pns_item.cpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/include/board_item.h b/include/board_item.h index fc0ff6d474..eec5547d08 100644 --- a/include/board_item.h +++ b/include/board_item.h @@ -134,6 +134,8 @@ public: BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_parent; } + BOARD_ITEM_CONTAINER* GetParentFootprint() const; + /** * Return the primary layer this item is on. */ diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp index df17729c93..b30a661443 100644 --- a/pcbnew/board_item.cpp +++ b/pcbnew/board_item.cpp @@ -176,6 +176,17 @@ std::shared_ptr BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) cons } +BOARD_ITEM_CONTAINER* BOARD_ITEM::GetParentFootprint() const +{ + BOARD_ITEM_CONTAINER* ancestor = GetParent(); + + while( ancestor && ancestor->Type() == PCB_GROUP_T ) + ancestor = ancestor->GetParent(); + + return ( ancestor && ancestor->Type() == PCB_FOOTPRINT_T ) ? ancestor : nullptr; +} + + void BOARD_ITEM::Rotate( const wxPoint& aRotCentre, double aAngle ) { wxMessageBox( wxT( "virtual BOARD_ITEM::Rotate used, should not occur" ), GetClass() ); diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index 7bae8cc154..8de76802d5 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -19,6 +19,7 @@ * with this program. If not, see . */ +#include #include "pns_node.h" #include "pns_item.h" #include "pns_line.h" @@ -54,6 +55,39 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent if( !m_layers.Overlaps( aOther->m_layers ) ) return false; + auto checkKeepout = + []( const ZONE* aKeepout, const BOARD_ITEM* aOther ) + { + constexpr KICAD_T TRACK_TYPES[] = { PCB_ARC_T, PCB_TRACE_T, EOT }; + + if( aKeepout->GetDoNotAllowTracks() && aOther->IsType( TRACK_TYPES ) ) + return true; + + if( aKeepout->GetDoNotAllowVias() && aOther->Type() == PCB_VIA_T ) + return true; + + if( aKeepout->GetDoNotAllowPads() && aOther->Type() == PCB_PAD_T ) + return true; + + // Incomplete test, but better than nothing: + if( aKeepout->GetDoNotAllowFootprints() && aOther->Type() == PCB_PAD_T ) + { + return !aKeepout->GetParentFootprint() + || aKeepout->GetParentFootprint() != aOther->GetParentFootprint(); + } + + return false; + }; + + const ZONE* zoneA = dynamic_cast( Parent() ); + const ZONE* zoneB = dynamic_cast( aOther->Parent() ); + + if( zoneA && aOther->Parent() && !checkKeepout( zoneA, aOther->Parent() ) ) + return false; + + if( zoneB && Parent() && !checkKeepout( zoneB, Parent() ) ) + return false; + if( holeA || holeB ) { int holeClearance = aNode->GetHoleClearance( this, aOther );