Router: fix Continue From End/ Attempt Finish work for diff pairs

Fixes: https://gitlab.com/kicad/code/kicad/-/issues/13772
This commit is contained in:
Mike Williams 2023-03-06 14:48:42 -05:00
parent 8d3e1eb52a
commit 74a9d79a8d
7 changed files with 52 additions and 18 deletions

View File

@ -435,6 +435,15 @@ OPT_VECTOR2I getDanglingAnchor( NODE* aNode, ITEM* aItem )
{ {
switch( aItem->Kind() ) switch( aItem->Kind() )
{ {
case ITEM::LINE_T:
{
LINE* l = static_cast<LINE*>( aItem );
if( !l->PointCount() )
return OPT_VECTOR2I();
else
return l->CPoint( 0 );
}
case ITEM::VIA_T: case ITEM::VIA_T:
case ITEM::SOLID_T: case ITEM::SOLID_T:
return aItem->Anchor( 0 ); return aItem->Anchor( 0 );

View File

@ -63,6 +63,7 @@
#include "pns_routing_settings.h" #include "pns_routing_settings.h"
#include "pns_sizes_settings.h" #include "pns_sizes_settings.h"
#include "pns_item.h" #include "pns_item.h"
#include "pns_line.h"
#include "pns_solid.h" #include "pns_solid.h"
#include "pns_segment.h" #include "pns_segment.h"
#include "pns_node.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 ) 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; return false;
BOARD_CONNECTED_ITEM* cItem = static_cast<BOARD_CONNECTED_ITEM*>( aItem->Parent() ); NETINFO_ITEM* netInfo = nullptr;
NETINFO_ITEM* netInfo = cItem->GetNet();
if( aItem->Parent() && aItem->Parent()->IsConnected() )
{
BOARD_CONNECTED_ITEM* cItem = static_cast<BOARD_CONNECTED_ITEM*>( aItem->Parent() );
netInfo = cItem->GetNet();
}
else
netInfo = m_board->FindNet( aItem->Net() );
if( !netInfo ) if( !netInfo )
return false; return false;

View File

@ -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 // Can't finish something with no connections
if( GetCurrentNets().empty() ) 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 the user has drawn a line, get the anchor nearest to the line end
if( trace->SegmentCount() > 0 ) 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 // 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 ); aOtherEnd = it->Anchor( anchor );
aOtherEndLayers = it->Layers(); aOtherEndLayers = it->Layers();
aOtherEndItem = it;
return true; return true;
} }
@ -531,19 +534,24 @@ bool ROUTER::Finish()
if( m_state != ROUTE_TRACK ) if( m_state != ROUTE_TRACK )
return false; return false;
LINE_PLACER* placer = dynamic_cast<LINE_PLACER*>( Placer() ); PLACEMENT_ALGO* placer = Placer();
if( placer == nullptr ) if( placer == nullptr || placer->Traces().Size() == 0 )
return false;
LINE* current = dynamic_cast<LINE*>( placer->Traces()[0] );
if( current == nullptr )
return false; return false;
// Get our current line and position and nearest ratsnest to them if it exists // Get our current line and position and nearest ratsnest to them if it exists
PNS::LINE current = placer->Trace();
VECTOR2I currentEnd = placer->CurrentEnd(); VECTOR2I currentEnd = placer->CurrentEnd();
VECTOR2I otherEnd; VECTOR2I otherEnd;
LAYER_RANGE otherEndLayers; LAYER_RANGE otherEndLayers;
ITEM* otherEndItem = nullptr;
// Get the anchor nearest to the end of the trace the user is routing // 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; return false;
// Keep moving until we don't change position or hit the limit // Keep moving until we don't change position or hit the limit
@ -553,14 +561,14 @@ bool ROUTER::Finish()
do do
{ {
moveResultPoint = Placer()->CurrentEnd(); moveResultPoint = Placer()->CurrentEnd();
Move( otherEnd, &current ); Move( otherEnd, otherEndItem );
triesLeft--; triesLeft--;
} while( Placer()->CurrentEnd() != moveResultPoint && triesLeft ); } while( Placer()->CurrentEnd() != moveResultPoint && triesLeft );
// If we've made it, fix the route and we're done // If we've made it, fix the route and we're done
if( moveResultPoint == otherEnd && otherEndLayers.Overlaps( GetCurrentLayer() ) ) if( moveResultPoint == otherEnd && otherEndLayers.Overlaps( GetCurrentLayer() ) )
{ {
return FixRoute( otherEnd, &current, false ); return FixRoute( otherEnd, otherEndItem, false );
} }
return false; return false;
@ -583,9 +591,10 @@ bool ROUTER::ContinueFromEnd()
VECTOR2I currentEnd = placer->CurrentEnd(); VECTOR2I currentEnd = placer->CurrentEnd();
VECTOR2I otherEnd; VECTOR2I otherEnd;
LAYER_RANGE otherEndLayers; LAYER_RANGE otherEndLayers;
ITEM* otherEndItem = nullptr;
// Get the anchor nearest to the end of the trace the user is routing // 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; return false;
CommitRouting(); CommitRouting();
@ -593,7 +602,7 @@ bool ROUTER::ContinueFromEnd()
// Commit whatever we've fixed and restart routing from the other end // Commit whatever we've fixed and restart routing from the other end
int nextLayer = otherEndLayers.Overlaps( currentLayer ) ? currentLayer : otherEndLayers.Start(); int nextLayer = otherEndLayers.Overlaps( currentLayer ) ? currentLayer : otherEndLayers.Start();
if( !StartRouting( otherEnd, current, nextLayer ) ) if( !StartRouting( otherEnd, otherEndItem, nextLayer ) )
return false; return false;
// Attempt to route to our current position // Attempt to route to our current position

View File

@ -228,7 +228,8 @@ private:
void markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved ); void markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved );
bool isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aItem, int aLayer ); 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: private:

View File

@ -94,7 +94,7 @@ const TOPOLOGY::JOINT_SET TOPOLOGY::ConnectedJoints( JOINT* aStart )
bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint,
LAYER_RANGE& aLayers ) LAYER_RANGE& aLayers, ITEM*& aItem )
{ {
LINE track( *aTrack ); LINE track( *aTrack );
VECTOR2I end; VECTOR2I end;
@ -115,6 +115,7 @@ bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoi
{ {
end = jt->Pos(); end = jt->Pos();
aLayers = jt->Layers(); aLayers = jt->Layers();
aItem = jt->LinkList()[0];
} }
else else
{ {
@ -128,6 +129,7 @@ bool TOPOLOGY::NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoi
end = it->Anchor( anchor ); end = it->Anchor( anchor );
aLayers = it->Layers(); aLayers = it->Layers();
aItem = it;
} }
aPoint = end; aPoint = end;
@ -140,8 +142,9 @@ bool TOPOLOGY::LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine )
VECTOR2I end; VECTOR2I end;
// Ratline doesn't care about the layer // Ratline doesn't care about the layer
LAYER_RANGE layers; LAYER_RANGE layers;
ITEM* unusedItem;
if( !NearestUnconnectedAnchorPoint( aTrack, end, layers ) ) if( !NearestUnconnectedAnchorPoint( aTrack, end, layers, unusedItem ) )
return false; return false;
aRatLine.Clear(); aRatLine.Clear();

View File

@ -50,8 +50,8 @@ public:
ITEM* NearestUnconnectedItem( JOINT* aStart, int* aAnchor = nullptr, ITEM* NearestUnconnectedItem( JOINT* aStart, int* aAnchor = nullptr,
int aKindMask = ITEM::ANY_T ); int aKindMask = ITEM::ANY_T );
bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, bool NearestUnconnectedAnchorPoint( const LINE* aTrack, VECTOR2I& aPoint, LAYER_RANGE& aLayers,
LAYER_RANGE& aLayers ); ITEM*& aItem );
bool LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine ); bool LeadingRatLine( const LINE* aTrack, SHAPE_LINE_CHAIN& aRatLine );
const JOINT_SET ConnectedJoints( JOINT* aStart ); const JOINT_SET ConnectedJoints( JOINT* aStart );

View File

@ -1369,6 +1369,10 @@ void ROUTER_TOOL::performRouting()
// We want the next router commit to be one undo at the UI layer // We want the next router commit to be one undo at the UI layer
m_iface->SetCommitFlags( needsAppend ? APPEND_UNDO : 0 ); 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 ) ) else if( evt->IsClick( BUT_LEFT ) || evt->IsDrag( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
{ {