PNS/Router Tool: Refactor Finish Route

This commit is contained in:
Mike Williams 2022-09-12 09:12:11 -04:00
parent b1f2273bc6
commit 1be0deb58f
3 changed files with 113 additions and 45 deletions

View File

@ -462,6 +462,86 @@ bool ROUTER::Move( const VECTOR2I& aP, ITEM* endItem )
} }
bool ROUTER::getNearestRatnestAnchor( VECTOR2I& aOtherEnd, LAYER_RANGE& aOtherEndLayers )
{
// Can't finish something with no connections
if( GetCurrentNets().empty() )
return false;
PNS::LINE_PLACER* placer = dynamic_cast<PNS::LINE_PLACER*>( Placer() );
if( placer == nullptr )
return false;
PNS::LINE trace = placer->Trace();
PNS::NODE* lastNode = placer->CurrentNode( true );
PNS::TOPOLOGY topo( lastNode );
// 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 );
// Otherwise, find the closest anchor to our start point
// Get joint from placer start item
JOINT* jt = lastNode->FindJoint( placer->CurrentStart(), placer->CurrentLayer(),
placer->CurrentNets()[0] );
if( !jt )
return false;
// Get unconnected item from joint
int anchor;
PNS::ITEM* it = topo.NearestUnconnectedItem( jt, &anchor );
if( !it )
return false;
aOtherEnd = it->Anchor( anchor );
aOtherEndLayers = it->Layers();
return true;
}
bool ROUTER::Finish()
{
if( m_state != ROUTE_TRACK )
return false;
LINE_PLACER* placer = dynamic_cast<LINE_PLACER*>( Placer() );
if( placer == 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;
// Get the anchor nearest to the end of the trace the user is routing
if( !getNearestRatnestAnchor( otherEnd, otherEndLayers ) )
return false;
// Keep moving until we don't change position
VECTOR2I moveResultPoint;
do
{
moveResultPoint = Placer()->CurrentEnd();
Move( otherEnd, &current );
} while( Placer()->CurrentEnd() != moveResultPoint );
// If we've made it, fix the route and we're done
if( moveResultPoint == otherEnd && otherEndLayers.Overlaps( GetCurrentLayer() ) )
{
return FixRoute( otherEnd, &current, false );
}
return false;
}
bool ROUTER::moveDragging( const VECTOR2I& aP, ITEM* aEndItem ) bool ROUTER::moveDragging( const VECTOR2I& aP, ITEM* aEndItem )
{ {
m_iface->EraseView(); m_iface->EraseView();

View File

@ -143,6 +143,7 @@ public:
bool RoutingInProgress() const; bool RoutingInProgress() const;
bool StartRouting( const VECTOR2I& aP, ITEM* aItem, int aLayer ); bool StartRouting( const VECTOR2I& aP, ITEM* aItem, int aLayer );
bool Move( const VECTOR2I& aP, ITEM* aItem ); bool Move( const VECTOR2I& aP, ITEM* aItem );
bool Finish();
bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish = false ); bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish = false );
void BreakSegment( ITEM *aItem, const VECTOR2I& aP ); void BreakSegment( ITEM *aItem, const VECTOR2I& aP );
@ -221,6 +222,9 @@ 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 );
private: private:
BOX2I m_visibleViewArea; BOX2I m_visibleViewArea;
RouterState m_state; RouterState m_state;

View File

@ -1263,8 +1263,35 @@ void ROUTER_TOOL::performRouting()
updateEndItem( *evt ); updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem ); m_router->Move( m_endSnapPoint, m_endItem );
} }
else if( evt->IsAction( &PCB_ACTIONS::routerAttemptFinish ) else if( evt->IsAction( &PCB_ACTIONS::routerAttemptFinish ) )
|| evt->IsAction( &PCB_ACTIONS::routerContinueFromEnd ) ) {
bool* autoRouted = evt->Parameter<bool*>();
if( m_router->Finish() )
{
// When we're routing a group of signals automatically we want
// to break up the undo stack every time we have to manually route
// so the user gets nice checkpoints. Remove the APPEND_UNDO flag.
if( autoRouted != nullptr )
*autoRouted = true;
break;
}
else
{
// This acts as check if we were called by the autorouter; we don't want
// to reset APPEND_UNDO if we're auto finishing after route-other-end
if( autoRouted != nullptr )
{
*autoRouted = false;
m_iface->SetCommitFlags( 0 );
}
// Warp the mouse so the user is at the point we managed to route to
controls()->WarpMouseCursor( m_router->Placer()->CurrentEnd(), true, true );
}
}
else if( evt->IsAction( &PCB_ACTIONS::routerContinueFromEnd ) )
{ {
PNS::LINE_PLACER* placer = dynamic_cast<PNS::LINE_PLACER*>( m_router->Placer() ); PNS::LINE_PLACER* placer = dynamic_cast<PNS::LINE_PLACER*>( m_router->Placer() );
@ -1311,49 +1338,6 @@ void ROUTER_TOOL::performRouting()
// Warp the mouse to wherever we actually ended up routing to // Warp the mouse to wherever we actually ended up routing to
controls()->WarpMouseCursor( currentEnd, true, true ); controls()->WarpMouseCursor( currentEnd, true, true );
} }
else
{
VECTOR2I moveResultPoint;
bool* autoRouted = evt->Parameter<bool*>();
if( autoRouted != nullptr )
*autoRouted = false;
// Keep moving until we don't change position
do
{
moveResultPoint = m_router->Placer()->CurrentEnd();
m_router->Move( otherEnd, &current );
} while( m_router->Placer()->CurrentEnd() != moveResultPoint );
// Fix the route and end routing if we made it to the destination
if( moveResultPoint == otherEnd
&& otherEndLayers.Overlaps( m_router->GetCurrentLayer() ) )
{
if( m_router->FixRoute( otherEnd, &current, false ) )
{
// When we're routing a group of signals automatically we want
// to break up the undo stack every time we have to manually route
// so the user gets nice checkpoints. Remove the APPEND_UNDO flag.
if( autoRouted != nullptr )
{
*autoRouted = true;
}
break;
}
// This acts as check if we were called by the autorouter; we don't want
// to reset APPEND_UNDO if we're auto finishing after route-other-end
else if( autoRouted != nullptr )
m_iface->SetCommitFlags( 0 );
}
// Otherwise warp the mouse so the user is at the point we managed to route to
else
{
m_iface->SetCommitFlags( 0 );
controls()->WarpMouseCursor( moveResultPoint, true, 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 ) )
{ {