From c1fcb1d8959997a7409de506e98a28878308b6e8 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 22 Jul 2019 17:46:20 -0600 Subject: [PATCH] Allow shoving and springback when dragging vias (either connected or free). Fixes: lp:1833216 * https://bugs.launchpad.net/kicad/+bug/1833216 --- pcbnew/router/pns_line.h | 16 ++++++++++ pcbnew/router/pns_shove.cpp | 59 ++++++++++++++++++++++++++----------- pcbnew/router/pns_shove.h | 6 ++-- 3 files changed, 61 insertions(+), 20 deletions(-) diff --git a/pcbnew/router/pns_line.h b/pcbnew/router/pns_line.h index c52f4343ae..dabbe1830b 100644 --- a/pcbnew/router/pns_line.h +++ b/pcbnew/router/pns_line.h @@ -89,6 +89,22 @@ public: m_hasVia = false; } + /** + * Constructor + * Constructs a LINE for a lone VIA (ie a stitching via). + * @param aVia + */ + LINE( const VIA& aVia ) : + ITEM( LINE_T ) + { + m_hasVia = true; + m_via = aVia; + m_width = aVia.Diameter(); + m_net = aVia.Net(); + m_layers = aVia.Layers(); + m_rank = aVia.Rank(); + } + ~LINE(); static inline bool ClassOf( const ITEM* aItem ) diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index 0c3154ad6c..b5210a7d31 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -530,17 +530,20 @@ SHOVE::SHOVE_STATUS SHOVE::onCollidingSolid( LINE& aCurrent, ITEM* aObstacle ) } -bool SHOVE::reduceSpringback( const ITEM_SET& aHeadSet ) +/* + * 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 ) { - bool rv = false; - while( !m_nodeStack.empty() ) { SPRINGBACK_TAG spTag = m_nodeStack.back(); if( !spTag.m_node->CheckColliding( aHeadSet ) ) { - rv = true; + if( aDraggedVia ) + *aDraggedVia = spTag.m_draggedVia; delete spTag.m_node; m_nodeStack.pop_back(); @@ -549,11 +552,15 @@ bool SHOVE::reduceSpringback( const ITEM_SET& aHeadSet ) break; } - return rv; + return m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node; } -bool SHOVE::pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea ) +/* + * Push the current NODE on to the stack. aDraggedVia is the dragged via *before* the push + * (which will be restored in the event the stackframe is popped). + */ +bool SHOVE::pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea, VIA* aDraggedVia ) { SPRINGBACK_TAG st; OPT_BOX2I prev_area; @@ -561,6 +568,7 @@ bool SHOVE::pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea ) if( !m_nodeStack.empty() ) prev_area = m_nodeStack.back().m_affectedArea; + st.m_draggedVia = aDraggedVia; st.m_node = aNode; if( aAffectedArea ) @@ -1026,6 +1034,13 @@ SHOVE::SHOVE_STATUS SHOVE::shoveMainLoop() timeLimit.Restart(); + if( m_lineStack.empty() && m_draggedVia ) + { + // If we're shoving a free via then push a proxy LINE (with the via on the end) onto + // the stack. + pushLine( LINE( *m_draggedVia ) ); + } + while( !m_lineStack.empty() ) { st = shoveIteration( m_iter ); @@ -1081,9 +1096,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveLines( const LINE& aCurrentHead ) ITEM_SET headSet; headSet.Add( aCurrentHead ); - reduceSpringback( headSet ); - - NODE* parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node; + NODE* parent = reduceSpringback( headSet, nullptr ); m_currentNode = parent->Branch(); m_currentNode->ClearRanks(); @@ -1136,7 +1149,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveLines( const LINE& aCurrentHead ) if( st == SH_OK || st == SH_HEAD_MODIFIED ) { - pushSpringback( m_currentNode, m_affectedArea ); + pushSpringback( m_currentNode, m_affectedArea, nullptr ); } else { @@ -1183,9 +1196,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveMultiLines( const ITEM_SET& aHeadSet ) m_optimizerQueue.clear(); m_logger.Clear(); - reduceSpringback( headSet ); - - NODE* parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node; + NODE* parent = reduceSpringback( headSet, nullptr ); m_currentNode = parent->Branch(); m_currentNode->ClearRanks(); @@ -1231,7 +1242,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveMultiLines( const ITEM_SET& aHeadSet ) if( st == SH_OK ) { - pushSpringback( m_currentNode, m_affectedArea ); + pushSpringback( m_currentNode, m_affectedArea, nullptr ); } else { @@ -1252,15 +1263,29 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere, m_newHead = OPT_LINE(); m_draggedVia = NULL; - NODE* parent = m_nodeStack.empty() ? m_root : m_nodeStack.back().m_node; + ITEM_SET headSet; + headSet.Add( *aVia ); + // Pop NODEs containing previous shoves which are no longer necessary + // + NODE* parent = reduceSpringback( headSet, &aVia ); + + // Create a new NODE + // m_currentNode = parent->Branch(); m_currentNode->ClearRanks(); aVia->Mark( MK_HEAD ); + aVia->SetRank( 100000 ); + // Push the via to its new location + // st = pushVia( aVia, ( aWhere - aVia->Pos() ), 0 ); - st = shoveMainLoop(); + + // Shove any colliding objects out of the way + // + if( st == SH_OK ) + st = shoveMainLoop(); if( st == SH_OK ) runOptimizer( m_currentNode ); @@ -1270,7 +1295,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere, wxLogTrace( "PNS","setNewV %p", m_draggedVia ); *aNewVia = m_draggedVia; - pushSpringback( m_currentNode, m_affectedArea ); + pushSpringback( m_currentNode, m_affectedArea, aVia ); } else { diff --git a/pcbnew/router/pns_shove.h b/pcbnew/router/pns_shove.h index 2be6826141..8c14460f85 100644 --- a/pcbnew/router/pns_shove.h +++ b/pcbnew/router/pns_shove.h @@ -93,7 +93,7 @@ private: struct SPRINGBACK_TAG { int64_t m_length; - int m_segments; + VIA* m_draggedVia; VECTOR2I m_p; NODE* m_node; OPT_BOX2I m_affectedArea; @@ -102,8 +102,8 @@ private: SHOVE_STATUS processHullSet( LINE& aCurrent, LINE& aObstacle, LINE& aShoved, const HULL_SET& hulls ); - bool reduceSpringback( const ITEM_SET& aHeadItems ); - bool pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea ); + NODE* reduceSpringback( const ITEM_SET& aHeadItems, VIA** aDraggedVia ); + bool pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea, VIA* aDraggedVia ); SHOVE_STATUS walkaroundLoneVia( LINE& aCurrent, LINE& aObstacle, LINE& aShoved ); bool checkBumpDirection( const LINE& aCurrent, const LINE& aShoved ) const;