From 74a9d79a8d6d15ad349f5119e35e578f107e260d Mon Sep 17 00:00:00 2001 From: Mike Williams Date: Mon, 6 Mar 2023 14:48:42 -0500 Subject: [PATCH] Router: fix Continue From End/ Attempt Finish work for diff pairs Fixes: https://gitlab.com/kicad/code/kicad/-/issues/13772 --- pcbnew/router/pns_diff_pair_placer.cpp | 9 ++++++++ pcbnew/router/pns_kicad_iface.cpp | 14 ++++++++++--- pcbnew/router/pns_router.cpp | 29 +++++++++++++++++--------- pcbnew/router/pns_router.h | 3 ++- pcbnew/router/pns_topology.cpp | 7 +++++-- pcbnew/router/pns_topology.h | 4 ++-- pcbnew/router/router_tool.cpp | 4 ++++ 7 files changed, 52 insertions(+), 18 deletions(-) diff --git a/pcbnew/router/pns_diff_pair_placer.cpp b/pcbnew/router/pns_diff_pair_placer.cpp index b0dada09fd..6e00e4ee2d 100644 --- a/pcbnew/router/pns_diff_pair_placer.cpp +++ b/pcbnew/router/pns_diff_pair_placer.cpp @@ -435,6 +435,15 @@ OPT_VECTOR2I getDanglingAnchor( NODE* aNode, ITEM* aItem ) { switch( aItem->Kind() ) { + case ITEM::LINE_T: + { + LINE* l = static_cast( aItem ); + + if( !l->PointCount() ) + return OPT_VECTOR2I(); + else + return l->CPoint( 0 ); + } case ITEM::VIA_T: case ITEM::SOLID_T: return aItem->Anchor( 0 ); diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 38ee215bef..7a740bc80b 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -63,6 +63,7 @@ #include "pns_routing_settings.h" #include "pns_sizes_settings.h" #include "pns_item.h" +#include "pns_line.h" #include "pns_solid.h" #include "pns_segment.h" #include "pns_node.h" @@ -862,11 +863,18 @@ int PNS_PCBNEW_RULE_RESOLVER::DpNetPolarity( int aNet ) bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( const PNS::ITEM* aItem, int& aNetP, int& aNetN ) { - if( !aItem || !aItem->Parent() || !aItem->Parent()->IsConnected() ) + if( !aItem ) return false; - BOARD_CONNECTED_ITEM* cItem = static_cast( aItem->Parent() ); - NETINFO_ITEM* netInfo = cItem->GetNet(); + NETINFO_ITEM* netInfo = nullptr; + + if( aItem->Parent() && aItem->Parent()->IsConnected() ) + { + BOARD_CONNECTED_ITEM* cItem = static_cast( aItem->Parent() ); + netInfo = cItem->GetNet(); + } + else + netInfo = m_board->FindNet( aItem->Net() ); if( !netInfo ) return false; diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index d81f013783..7de2f64dd8 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -480,7 +480,8 @@ bool ROUTER::Move( const VECTOR2I& aP, ITEM* endItem ) } -bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEndLayers ) +bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEndLayers, + ITEM*& aOtherEndItem ) { // Can't finish something with no connections if( GetCurrentNets().empty() ) @@ -501,7 +502,8 @@ bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEn // If the user has drawn a line, get the anchor nearest to the line end if( trace->SegmentCount() > 0 ) - return topo.NearestUnconnectedAnchorPoint( trace, aOtherEnd, aOtherEndLayers ); + return topo.NearestUnconnectedAnchorPoint( trace, aOtherEnd, aOtherEndLayers, + aOtherEndItem ); // Otherwise, find the closest anchor to our start point @@ -521,6 +523,7 @@ bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEn aOtherEnd = it->Anchor( anchor ); aOtherEndLayers = it->Layers(); + aOtherEndItem = it; return true; } @@ -531,19 +534,24 @@ bool ROUTER::Finish() if( m_state != ROUTE_TRACK ) return false; - LINE_PLACER* placer = dynamic_cast( Placer() ); + PLACEMENT_ALGO* placer = Placer(); - if( placer == nullptr ) + if( placer == nullptr || placer->Traces().Size() == 0 ) + return false; + + LINE* current = dynamic_cast( placer->Traces()[0] ); + + if( current == nullptr ) return false; // Get our current line and position and nearest ratsnest to them if it exists - PNS::LINE current = placer->Trace(); VECTOR2I currentEnd = placer->CurrentEnd(); VECTOR2I otherEnd; LAYER_RANGE otherEndLayers; + ITEM* otherEndItem = nullptr; // Get the anchor nearest to the end of the trace the user is routing - if( !getNearestRatnestAnchor( otherEnd, otherEndLayers ) ) + if( !getNearestRatnestAnchor( otherEnd, otherEndLayers, otherEndItem ) ) return false; // Keep moving until we don't change position or hit the limit @@ -553,14 +561,14 @@ bool ROUTER::Finish() do { moveResultPoint = Placer()->CurrentEnd(); - Move( otherEnd, ¤t ); + Move( otherEnd, otherEndItem ); triesLeft--; } while( Placer()->CurrentEnd() != moveResultPoint && triesLeft ); // If we've made it, fix the route and we're done if( moveResultPoint == otherEnd && otherEndLayers.Overlaps( GetCurrentLayer() ) ) { - return FixRoute( otherEnd, ¤t, false ); + return FixRoute( otherEnd, otherEndItem, false ); } return false; @@ -583,9 +591,10 @@ bool ROUTER::ContinueFromEnd() VECTOR2I currentEnd = placer->CurrentEnd(); VECTOR2I otherEnd; LAYER_RANGE otherEndLayers; + ITEM* otherEndItem = nullptr; // Get the anchor nearest to the end of the trace the user is routing - if( !getNearestRatnestAnchor( otherEnd, otherEndLayers ) ) + if( !getNearestRatnestAnchor( otherEnd, otherEndLayers, otherEndItem ) ) return false; CommitRouting(); @@ -593,7 +602,7 @@ bool ROUTER::ContinueFromEnd() // Commit whatever we've fixed and restart routing from the other end int nextLayer = otherEndLayers.Overlaps( currentLayer ) ? currentLayer : otherEndLayers.Start(); - if( !StartRouting( otherEnd, current, nextLayer ) ) + if( !StartRouting( otherEnd, otherEndItem, nextLayer ) ) return false; // Attempt to route to our current position diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 6abb28178b..390f237a6b 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -228,7 +228,8 @@ private: void markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved ); bool isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aItem, int aLayer ); - bool getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEndLayers ); + bool getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEndLayers, + ITEM*& aOtherEndItem ); private: diff --git a/pcbnew/router/pns_topology.cpp b/pcbnew/router/pns_topology.cpp index ecdb91bb91..168414e3f9 100644 --- a/pcbnew/router/pns_topology.cpp +++ b/pcbnew/router/pns_topology.cpp @@ -94,7 +94,7 @@ const TOPOLOGY::JOINT_SET TOPOLOGY::ConnectedJoints( JOINT* aStart ) bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, - LAYER_RANGE& aLayers ) + LAYER_RANGE& aLayers, ITEM*& aItem ) { LINE track( *aTrack ); VECTOR2I end; @@ -115,6 +115,7 @@ bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoi { end = jt->Pos(); aLayers = jt->Layers(); + aItem = jt->LinkList()[0]; } else { @@ -128,6 +129,7 @@ bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoi end = it->Anchor( anchor ); aLayers = it->Layers(); + aItem = it; } aPoint = end; @@ -140,8 +142,9 @@ bool TOPOLOGY::LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine ) VECTOR2I end; // Ratline doesn't care about the layer LAYER_RANGE layers; + ITEM* unusedItem; - if( !NearestUnconnectedAnchorPoint( aTrack, end, layers ) ) + if( !NearestUnconnectedAnchorPoint( aTrack, end, layers, unusedItem ) ) return false; aRatLine.Clear(); diff --git a/pcbnew/router/pns_topology.h b/pcbnew/router/pns_topology.h index 842791125a..b786751a01 100644 --- a/pcbnew/router/pns_topology.h +++ b/pcbnew/router/pns_topology.h @@ -50,8 +50,8 @@ public: ITEM* NearestUnconnectedItem( JOINT* aStart, int* aAnchor = nullptr, int aKindMask = ITEM::ANY_T ); - bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, - LAYER_RANGE& aLayers ); + bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, LAYER_RANGE& aLayers, + ITEM*& aItem ); bool LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine ); const JOINT_SET ConnectedJoints( JOINT* aStart ); diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 1254432155..d7f370856c 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -1369,6 +1369,10 @@ void ROUTER_TOOL::performRouting() // We want the next router commit to be one undo at the UI layer m_iface->SetCommitFlags( needsAppend ? APPEND_UNDO : 0 ); } + else + { + frame()->ShowInfoBarError( m_router->FailureReason(), true ); + } } else if( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) ) {