Teach router about different keepout rules.

Fixes https://gitlab.com/kicad/code/kicad/issues/9786
This commit is contained in:
Jeff Young 2021-11-26 23:01:53 +00:00
parent 698a668af7
commit 9547c72e73
3 changed files with 47 additions and 0 deletions

View File

@ -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.
*/

View File

@ -176,6 +176,17 @@ std::shared_ptr<SHAPE> 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() );

View File

@ -19,6 +19,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <zone.h>
#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<ZONE*>( Parent() );
const ZONE* zoneB = dynamic_cast<ZONE*>( 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 );