diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index 5b9dc706ea..dc225436ec 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -45,27 +45,48 @@ static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles ) } // prune self-collisions, i.e. a via/pad annular ring with its own hole -static bool shouldWeConsiderHoleCollisions( const ITEM* aItem, const ITEM *aHead ) +static bool shouldWeConsiderHoleCollisions( const ITEM* aItem, const ITEM* aHead ) { - const HOLE *hi = aItem->OfKind( ITEM::HOLE_T ) ? static_cast( aItem ) : nullptr; - const HOLE *hh = aHead->OfKind( ITEM::HOLE_T ) ? static_cast( aHead ) : nullptr; + const HOLE* holeI = aItem->OfKind( ITEM::HOLE_T ) ? static_cast( aItem ) : nullptr; + const HOLE* holeH = aHead->OfKind( ITEM::HOLE_T ) ? static_cast( aHead ) : nullptr; - if( hi && hh ) // hole-to-hole case + if( holeI && holeH ) // hole-to-hole case { - if ( !hi->ParentPadVia() || !hh->ParentPadVia() ) + const ITEM* parentI = holeI->ParentPadVia(); + const ITEM* parentH = holeH->ParentPadVia(); + if( !parentH || !parentI ) return true; - return hi->ParentPadVia() != hh->ParentPadVia(); + const VIA* parentViaI = dyn_cast( parentI ); + const VIA* parentViaH = dyn_cast( parentH ); + + // Note to self: the if() below is an ugly heuristic to determine if we aren't trying to check for collisions + // of the hole of the via with another (although identical) copy of it. Such case occurs when + // checking a LINE against a NODE where this LINE has been already added. LINE has no notion of + // ownership of it's via (it's just a copy) and before hole-to-hole clearance support has been introduced + // it didn't matter becasue we didn't consider collisions of the objects belonging to the same net anyway + // Now that hole clearance check doesn't care about the nets assigned to the parent vias/solids, I'll probably + // have to refactor the LINE class to manage ownership of its (optional) VIA. For the moment, we just treat + // via holes that are geometrically identical and belonging to the same net as non-colliding. + + if( parentViaI && parentViaH && parentViaI->Pos() == parentViaH->Pos() + && parentViaI->Diameter() == parentViaH->Diameter() + && parentViaI->Net() == parentViaH->Net() + && parentViaI->Drill() == parentViaH->Drill() ) + return false; + + return parentI != parentH; } - if( hi ) - return hi->ParentPadVia() != aHead; - else if( hh ) - return hh->ParentPadVia() != aItem; + if( holeI ) + return holeI->ParentPadVia() != aHead; + else if( holeH ) + return holeH->ParentPadVia() != aItem; else return true; } + bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode, COLLISION_SEARCH_CONTEXT* aCtx ) const { @@ -275,4 +296,13 @@ const std::string ITEM::Format() const return ss.str(); } + +const NODE* ITEM::OwningNode() const +{ + if( ParentPadVia() ) + return static_cast( ParentPadVia()->Owner() ); + else + return static_cast( Owner() ); } + +} // namespace PNS diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index e0ecac1fa5..0b70cf9c26 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -50,7 +50,10 @@ class ITEM; class HOLE; struct COLLISION_SEARCH_CONTEXT; -class ITEM_OWNER {}; +class ITEM_OWNER { +public: + virtual ~ITEM_OWNER() {}; +}; class OWNABLE_ITEM { @@ -266,6 +269,8 @@ public: virtual const std::string Format() const; + virtual const NODE* OwningNode() const; + private: bool collideSimple( const ITEM* aHead, const NODE* aNode, COLLISION_SEARCH_CONTEXT* aCtx ) const;