From 726bceecfd9981c89d8dcac7ea328db4af5db78d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Wed, 7 Aug 2019 23:49:35 +0200 Subject: [PATCH] router: springback now works for dragging vias in shove mode Fixes: lp:1837766 * https://bugs.launchpad.net/kicad/+bug/1837766 --- pcbnew/router/pns_dragger.cpp | 129 ++++++++++++++++++---------------- pcbnew/router/pns_dragger.h | 20 ++++-- 2 files changed, 83 insertions(+), 66 deletions(-) diff --git a/pcbnew/router/pns_dragger.cpp b/pcbnew/router/pns_dragger.cpp index 27b5edf1d9..2ac808b37e 100644 --- a/pcbnew/router/pns_dragger.cpp +++ b/pcbnew/router/pns_dragger.cpp @@ -31,20 +31,15 @@ DRAGGER::DRAGGER( ROUTER* aRouter ) : m_world = NULL; m_lastNode = NULL; m_mode = DM_SEGMENT; - m_draggedVia = NULL; - m_shove = NULL; m_draggedSegmentIndex = 0; m_dragStatus = false; m_currentMode = RM_MarkObstacles; - m_initialVia = NULL; m_freeAngleMode = false; } DRAGGER::~DRAGGER() { - if( m_shove ) - delete m_shove; } @@ -59,14 +54,15 @@ bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg ) int w2 = aSeg->Width() / 2; m_draggedLine = m_world->AssembleLine( aSeg, &m_draggedSegmentIndex ); - m_shove->SetInitialLine( m_draggedLine ); - m_lastValidDraggedLine = m_draggedLine; - m_lastValidDraggedLine.ClearSegmentLinks(); + + if( m_shove ) + { + m_shove->SetInitialLine( m_draggedLine ); + } auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm(); auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm(); - if( distA <= w2 ) { m_mode = DM_CORNER; @@ -93,17 +89,24 @@ bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg ) } -bool DRAGGER::startDragVia( const VECTOR2D& aP, VIA* aVia ) +bool DRAGGER::startDragVia( VIA* aVia ) { - m_draggedVia = aVia; - m_initialVia = aVia; + m_initialVia = aVia->MakeHandle(); + m_draggedVia = m_initialVia; + m_mode = DM_VIA; - VECTOR2I p0( aVia->Pos() ); - JOINT* jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() ); + return true; +} + +const ITEM_SET DRAGGER::findViaFanoutByHandle ( NODE *aNode, const VIA_HANDLE& handle ) +{ + ITEM_SET rv; + + JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net ); if( !jt ) - return false; + return rv; for( ITEM* item : jt->LinkList() ) { @@ -111,27 +114,33 @@ bool DRAGGER::startDragVia( const VECTOR2D& aP, VIA* aVia ) { int segIndex; SEGMENT* seg = ( SEGMENT*) item; - LINE l = m_world->AssembleLine( seg, &segIndex ); + LINE l = aNode->AssembleLine( seg, &segIndex ); if( segIndex != 0 ) l.Reverse(); - m_origViaConnections.Add( l ); + rv.Add( l ); + } else if ( item->OfKind( ITEM::VIA_T )) + { + rv.Add( item ); } } - return true; + return rv; } - bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem ) { - m_shove = new SHOVE( m_world, Router() ); m_lastNode = NULL; m_draggedItems.Clear(); m_currentMode = Settings().Mode(); m_freeAngleMode = (m_mode & DM_FREE_ANGLE); + if( m_currentMode == RM_Shove ) + { + m_shove.reset( new SHOVE( m_world, Router() ) ); + } + aStartItem->Unmark( MK_LOCKED ); wxLogTrace( "PNS", "StartDragging: item %p [kind %d]", aStartItem, (int) aStartItem->Kind() ); @@ -142,7 +151,7 @@ bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem ) return startDragSegment( aP, static_cast( aStartItem ) ); case ITEM::VIA_T: - return startDragVia( aP, static_cast( aStartItem ) ); + return startDragVia( static_cast( aStartItem ) ); default: return false; @@ -158,18 +167,22 @@ void DRAGGER::SetMode( int aMode ) bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) { + // fixme: rewrite using shared_ptr... if( m_lastNode ) { delete m_lastNode; - m_lastNode = NULL; + m_lastNode = nullptr; } + m_lastNode = m_world->Branch(); + switch( m_mode ) { case DM_SEGMENT: case DM_CORNER: { int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0; + LINE origLine( m_draggedLine ); LINE dragged( m_draggedLine ); if( m_mode == DM_SEGMENT ) @@ -177,22 +190,17 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) else dragged.DragCorner( aP, m_draggedSegmentIndex, thresh, m_freeAngleMode ); - m_lastNode = m_shove->CurrentNode()->Branch(); + m_lastNode->Remove( origLine ); + m_lastNode->Add( dragged ); - m_lastValidDraggedLine = dragged; - m_lastValidDraggedLine.ClearSegmentLinks(); - m_lastValidDraggedLine.Unmark(); - - m_lastNode->Add( m_lastValidDraggedLine ); m_draggedItems.Clear(); - m_draggedItems.Add( m_lastValidDraggedLine ); + m_draggedItems.Add( dragged ); break; } case DM_VIA: // fixme... { - m_lastNode = m_shove->CurrentNode()->Branch(); dumbDragVia( m_initialVia, m_lastNode, aP ); break; @@ -208,29 +216,25 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP ) } -void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP ) +void DRAGGER::dumbDragVia( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP ) { m_draggedItems.Clear(); - // fixme: this is awful. - auto via_clone = Clone( *aVia ); + ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle ); - m_draggedVia = via_clone.get(); - m_draggedVia->SetPos( aP ); - - m_draggedItems.Add( m_draggedVia ); - - m_lastNode->Remove( aVia ); - m_lastNode->Add( std::move( via_clone ) ); - - for( ITEM* item : m_origViaConnections.Items() ) + if( fanout.Empty() ) + { + return; + } + + for( ITEM* item : fanout.Items() ) { if( const LINE* l = dyn_cast( item ) ) { LINE origLine( *l ); LINE draggedLine( *l ); - draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ), 0, m_freeAngleMode ); + draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), 0, m_freeAngleMode ); draggedLine.ClearSegmentLinks(); m_draggedItems.Add( draggedLine ); @@ -238,6 +242,16 @@ void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP ) m_lastNode->Remove( origLine ); m_lastNode->Add( draggedLine ); } + else if ( VIA *via = dyn_cast( item ) ) + { + auto nvia = Clone( *via ); + + nvia->SetPos( aP ); + m_draggedItems.Add( nvia.get() ); + + m_lastNode->Remove( via ); + m_lastNode->Add( std::move( nvia ) ); + } } } @@ -278,35 +292,32 @@ bool DRAGGER::dragShove( const VECTOR2I& aP ) m_lastNode = m_shove->CurrentNode()->Branch(); if( ok ) - m_lastValidDraggedLine = dragged; - - m_lastValidDraggedLine.ClearSegmentLinks(); - m_lastValidDraggedLine.Unmark(); - m_lastNode->Add( m_lastValidDraggedLine ); - m_draggedItems.Clear(); - m_draggedItems.Add( m_lastValidDraggedLine ); + { + dragged.ClearSegmentLinks(); + dragged.Unmark(); + m_lastNode->Add( dragged ); + m_draggedItems.Clear(); + m_draggedItems.Add( dragged ); + } break; } case DM_VIA: { - VIA* newVia; - SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, &newVia ); + VIA_HANDLE newVia; + + SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, newVia ); if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED ) ok = true; m_lastNode = m_shove->CurrentNode()->Branch(); - if( ok ) - { - if( newVia ) - m_draggedVia = newVia; - - m_draggedItems.Clear(); - } + if( newVia.valid ) + m_draggedVia = newVia; + m_draggedItems.Clear(); break; } } diff --git a/pcbnew/router/pns_dragger.h b/pcbnew/router/pns_dragger.h index 90e00cb740..53a5a95a05 100644 --- a/pcbnew/router/pns_dragger.h +++ b/pcbnew/router/pns_dragger.h @@ -22,6 +22,7 @@ #ifndef __PNS_DRAGGER_H #define __PNS_DRAGGER_H +#include #include #include "pns_node.h" @@ -29,6 +30,8 @@ #include "pns_line.h" #include "pns_algo_base.h" #include "pns_itemset.h" +#include "pns_layerset.h" + namespace PNS { @@ -101,25 +104,28 @@ public: private: - + const ITEM_SET findViaFanoutByHandle ( NODE *aNode, const VIA_HANDLE& handle ); + bool dragMarkObstacles( const VECTOR2I& aP ); bool dragShove(const VECTOR2I& aP ); bool startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg ); - bool startDragVia( const VECTOR2D& aP, VIA* aVia ); - void dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP ); + bool startDragVia( VIA* aVia ); + void dumbDragVia( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP ); + + VIA_HANDLE m_initialVia; + VIA_HANDLE m_draggedVia; NODE* m_world; NODE* m_lastNode; int m_mode; LINE m_draggedLine; - VIA* m_draggedVia; - LINE m_lastValidDraggedLine; - SHOVE* m_shove; + //VIA* m_draggedVia; + //LINE m_lastValidDraggedLine; + std::unique_ptr m_shove; int m_draggedSegmentIndex; bool m_dragStatus; PNS_MODE m_currentMode; ITEM_SET m_origViaConnections; - VIA* m_initialVia; ITEM_SET m_draggedItems; bool m_freeAngleMode; };