From 88f2318c9cd48946988024bc2cc4a298822ba0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Wed, 7 Aug 2019 23:48:09 +0200 Subject: [PATCH] router: add VIA_HANDLE to refer to VIAs going in/out the SHOVE algorithm without raw pointers --- pcbnew/router/pns_shove.cpp | 93 ++++++++++++++++++++++++++++--------- pcbnew/router/pns_shove.h | 7 +-- pcbnew/router/pns_via.cpp | 10 ++++ pcbnew/router/pns_via.h | 13 ++++++ 4 files changed, 97 insertions(+), 26 deletions(-) diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index 03a442ab9e..133ab3e4e0 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -24,6 +24,7 @@ #include "pns_line.h" #include "pns_node.h" +#include "pns_debug_decorator.h" #include "pns_walkaround.h" #include "pns_shove.h" #include "pns_solid.h" @@ -82,6 +83,7 @@ SHOVE::SHOVE( NODE* aWorld, ROUTER* aRouter ) : m_forceClearance = -1; m_root = aWorld; m_currentNode = aWorld; + SetDebugDecorator( aRouter->GetInterface()->GetDebugDecorator() ); // Initialize other temporary variables: m_draggedVia = NULL; @@ -553,16 +555,18 @@ SHOVE::SHOVE_STATUS SHOVE::onCollidingSolid( LINE& aCurrent, ITEM* aObstacle ) * Pops NODE stackframes which no longer collide with aHeadSet. Optionally sets aDraggedVia * to the dragged via of the last unpopped state. */ -NODE* SHOVE::reduceSpringback( const ITEM_SET& aHeadSet, VIA** aDraggedVia ) +NODE* SHOVE::reduceSpringback( const ITEM_SET& aHeadSet, VIA_HANDLE& aDraggedVia ) { while( !m_nodeStack.empty() ) { - SPRINGBACK_TAG spTag = m_nodeStack.back(); + SPRINGBACK_TAG& spTag = m_nodeStack.back(); - if( !spTag.m_node->CheckColliding( aHeadSet ) ) + auto obs = spTag.m_node->CheckColliding( aHeadSet ); + + if( !obs ) { - if( aDraggedVia ) - *aDraggedVia = spTag.m_draggedVia; + aDraggedVia = spTag.m_draggedVia; + aDraggedVia.valid = true; delete spTag.m_node; m_nodeStack.pop_back(); @@ -587,7 +591,11 @@ bool SHOVE::pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea, VIA* aD if( !m_nodeStack.empty() ) prev_area = m_nodeStack.back().m_affectedArea; - st.m_draggedVia = aDraggedVia; + if( aDraggedVia ) + { + st.m_draggedVia = aDraggedVia->MakeHandle(); + } + st.m_node = aNode; if( aAffectedArea ) @@ -1166,7 +1174,9 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveLines( const LINE& aCurrentHead ) ITEM_SET headSet; headSet.Add( aCurrentHead ); - NODE* parent = reduceSpringback( headSet, nullptr ); + VIA_HANDLE dummyVia; + + NODE* parent = reduceSpringback( headSet, dummyVia ); // Create a new NODE to store this version of the world // @@ -1268,7 +1278,9 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveMultiLines( const ITEM_SET& aHeadSet ) m_optimizerQueue.clear(); m_logger.Clear(); - NODE* parent = reduceSpringback( headSet, nullptr ); + VIA_HANDLE dummyVia; + + NODE* parent = reduceSpringback( headSet, dummyVia ); m_currentNode = parent->Branch(); m_currentNode->ClearRanks(); @@ -1325,34 +1337,67 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveMultiLines( const ITEM_SET& aHeadSet ) return st; } - -SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere, VIA** aNewVia ) +static VIA* findViaByHandle ( NODE *aNode, const VIA_HANDLE& handle ) { - SHOVE_STATUS st = SH_OK; + JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net ); + + if( !jt ) + return nullptr; + + for( ITEM* item : jt->LinkList() ) + { + if ( item->OfKind( ITEM::VIA_T )) + { + if( item->Net() == handle.net && item->Layers().Overlaps(handle.layers) ) + return static_cast( item ); + } + } + + return nullptr; +} + +SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( const VIA_HANDLE aOldVia, const VECTOR2I& aWhere, VIA_HANDLE& aNewVia ) +{ + SHOVE_STATUS st = SH_OK; m_lineStack.clear(); m_optimizerQueue.clear(); m_newHead = OPT_LINE(); m_draggedVia = NULL; - // Pop NODEs containing previous shoves which are no longer necessary - // - ITEM_SET headSet; - headSet.Add( *aVia ); + auto viaToDrag = findViaByHandle( m_currentNode, aOldVia ); - NODE* parent = reduceSpringback( headSet, &aVia ); + if( !viaToDrag ) + { + return SH_INCOMPLETE; + } + + // Pop NODEs containing previous shoves which are no longer necessary + ITEM_SET headSet; + + VIA headVia ( *viaToDrag ); + headVia.SetPos( aWhere ); + headSet.Add( headVia ); + VIA_HANDLE prevViaHandle; + NODE* parent = reduceSpringback( headSet, prevViaHandle ); + + if( prevViaHandle.valid ) + { + aNewVia = prevViaHandle; + viaToDrag = findViaByHandle( parent, prevViaHandle ); + } // Create a new NODE to store this version of the world // m_currentNode = parent->Branch(); m_currentNode->ClearRanks(); - aVia->Mark( MK_HEAD ); - aVia->SetRank( 100000 ); + viaToDrag->Mark( MK_HEAD ); + viaToDrag->SetRank( 100000 ); // Push the via to its new location // - st = pushOrShoveVia( aVia, ( aWhere - aVia->Pos()), 0 ); + st = pushOrShoveVia( viaToDrag, ( aWhere - viaToDrag->Pos()), 0 ); // Shove any colliding objects out of the way // @@ -1365,14 +1410,16 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere, if( st == SH_OK || st == SH_HEAD_MODIFIED ) { wxLogTrace( "PNS","setNewV %p", m_draggedVia ); - *aNewVia = m_draggedVia; - pushSpringback( m_currentNode, m_affectedArea, aVia ); + if (!m_draggedVia) + m_draggedVia = viaToDrag; + + aNewVia = m_draggedVia->MakeHandle(); + + pushSpringback( m_currentNode, m_affectedArea, viaToDrag ); } else { - *aNewVia = nullptr; - delete m_currentNode; m_currentNode = parent; } diff --git a/pcbnew/router/pns_shove.h b/pcbnew/router/pns_shove.h index e468bf9224..44264ea3bb 100644 --- a/pcbnew/router/pns_shove.h +++ b/pcbnew/router/pns_shove.h @@ -67,7 +67,7 @@ public: SHOVE_STATUS ShoveLines( const LINE& aCurrentHead ); SHOVE_STATUS ShoveMultiLines( const ITEM_SET& aHeadSet ); - SHOVE_STATUS ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere, VIA** aNewVia ); + SHOVE_STATUS ShoveDraggingVia( const VIA_HANDLE aOldVia, const VECTOR2I& aWhere, VIA_HANDLE& aNewVia ); SHOVE_STATUS ProcessSingleLine( LINE& aCurrent, LINE& aObstacle, LINE& aShoved ); void ForceClearance ( bool aEnabled, int aClearance ) @@ -93,7 +93,7 @@ private: struct SPRINGBACK_TAG { int64_t m_length; - VIA* m_draggedVia; + VIA_HANDLE m_draggedVia; VECTOR2I m_p; NODE* m_node; OPT_BOX2I m_affectedArea; @@ -102,7 +102,8 @@ private: SHOVE_STATUS processHullSet( LINE& aCurrent, LINE& aObstacle, LINE& aShoved, const HULL_SET& hulls ); - NODE* reduceSpringback( const ITEM_SET& aHeadItems, VIA** aDraggedVia ); + NODE* reduceSpringback( const ITEM_SET& aHeadSet, VIA_HANDLE& aDraggedVia ); + bool pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea, VIA* aDraggedVia ); SHOVE_STATUS walkaroundLoneVia( LINE& aCurrent, LINE& aObstacle, LINE& aShoved ); diff --git a/pcbnew/router/pns_via.cpp b/pcbnew/router/pns_via.cpp index 14b3b77aef..c60d1759ab 100644 --- a/pcbnew/router/pns_via.cpp +++ b/pcbnew/router/pns_via.cpp @@ -112,4 +112,14 @@ OPT_BOX2I VIA::ChangedArea( const VIA* aOther ) const return OPT_BOX2I(); } +const VIA_HANDLE VIA::MakeHandle() const +{ + VIA_HANDLE h; + h.pos = Pos(); + h.layers = Layers(); + h.net = Net(); + h.valid = true; + return h; +} + } diff --git a/pcbnew/router/pns_via.h b/pcbnew/router/pns_via.h index 0443ae2d5b..524389b3cc 100644 --- a/pcbnew/router/pns_via.h +++ b/pcbnew/router/pns_via.h @@ -33,6 +33,17 @@ namespace PNS { class NODE; +// uniquely identifies a VIA within a NODE without using pointers. Used to +// simplify (or complexifiy, depending on the point of view) the pointer management +// in PNS::NODE. Sooner or later I'll have to fix it for good using smart pointers - twl +struct VIA_HANDLE +{ + bool valid = false; + VECTOR2I pos; + LAYER_RANGE layers; + int net; +}; + class VIA : public ITEM { public: @@ -154,6 +165,8 @@ public: OPT_BOX2I ChangedArea( const VIA* aOther ) const; + const VIA_HANDLE MakeHandle() const; + private: int m_diameter; int m_drill;