router: backspace key to undo last fixed segment(s)

This commit is contained in:
Tomasz Wlostowski 2020-02-07 20:57:24 +01:00
parent b5c11f21e5
commit 4525a17076
16 changed files with 322 additions and 32 deletions

View File

@ -297,7 +297,7 @@ void DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const V
LINE origLine( *l );
LINE draggedLine( *l );
draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), 0, m_freeAngleMode );
draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
draggedLine.ClearSegmentLinks();
m_draggedItems.Add( draggedLine );
@ -425,7 +425,7 @@ bool DRAGGER::dragWalkaround( const VECTOR2I& aP )
bool DRAGGER::dragShove( const VECTOR2I& aP )
{
bool ok = false;
if( m_lastNode )
{
delete m_lastNode;

View File

@ -826,7 +826,7 @@ std::unique_ptr<PNS::SEGMENT> PNS_KICAD_IFACE_BASE::syncTrack( TRACK* aTrack )
}
std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE::syncArc( ARC* aArc )
std::unique_ptr<PNS::ARC> PNS_KICAD_IFACE_BASE::syncArc( ARC* aArc )
{
std::unique_ptr< PNS::ARC > arc(
new PNS::ARC( SHAPE_ARC( aArc->GetCenter(), aArc->GetStart(),

View File

@ -228,7 +228,7 @@ bool LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
else
p = aObstacle.CSegment(j).Intersect( a );
printf("- cont_a %d cont_b %d p %d\n", !!cont_a, !!cont_b, p ? 1 : 0 );
//printf("- cont_a %d cont_b %d p %d\n", !!cont_a, !!cont_b, p ? 1 : 0 );
if ( p )
@ -238,7 +238,7 @@ bool LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
ip.their = aObstacle.CSegment(j);
ip.p = *p;
ips.push_back(ip);
printf("chb %d %d\n", p->x, p->y);
//printf("chb %d %d\n", p->x, p->y);
}
}
}

View File

@ -427,8 +427,8 @@ bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead )
//Dbg()->AddPoint( p_cw, 4 );
//Dbg()->AddPoint( p_ccw, 5 );
//Dbg()->AddLine( wr.lineCw.CLine(), 4, 1000 );
//Dbg()->AddLine( wr.lineCcw.CLine(), 5, 1000 );
Dbg()->AddLine( wr.lineCw.CLine(), 4, 1000 );
Dbg()->AddLine( wr.lineCcw.CLine(), 5, 1000 );
}
@ -841,6 +841,7 @@ void LINE_PLACER::routeStep( const VECTOR2I& aP )
n_iter++;
go_back = true;
}
}
if( !fail )
@ -943,7 +944,10 @@ bool LINE_PLACER::SetLayer( int aLayer )
else if( !m_startItem || ( m_startItem->OfKind( ITEM::VIA_T ) && m_startItem->Layers().Overlaps( aLayer ) ) )
{
m_currentLayer = aLayer;
initPlacement();
m_head.Line().Clear();
m_tail.Line().Clear();
m_head.SetLayer( m_currentLayer );
m_tail.SetLayer( m_currentLayer );
Move( m_currentEnd, NULL );
return true;
}
@ -960,10 +964,21 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
m_startItem = aStartItem;
m_placingVia = false;
m_chainedPlacement = false;
m_fixedTail.Clear();
setInitialDirection( Settings().InitialDirection() );
initPlacement();
NODE *n;
if ( m_shove )
n = m_shove->CurrentNode();
else
n = m_currentNode;
m_fixedTail.AddStage( m_currentStart, m_currentLayer, m_placingVia, m_direction, n );
return true;
}
@ -1017,8 +1032,6 @@ bool LINE_PLACER::Move( const VECTOR2I& aP, ITEM* aEndItem )
VECTOR2I p = aP;
int eiDepth = -1;
printf(" **** lp move %d %d ei %p\n", aP.x, aP.y, aEndItem );
if( aEndItem && aEndItem->Owner() )
eiDepth = static_cast<NODE*>( aEndItem->Owner() )->Depth();
@ -1090,8 +1103,6 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
if( pl.EndsWithVia() )
{
m_lastNode->Add( Clone( pl.Via() ) );
Router()->CommitRouting( m_lastNode );
m_lastNode = NULL;
m_currentNode = NULL;
@ -1150,24 +1161,37 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
}
if( pl.EndsWithVia() )
{
m_lastNode->Add( Clone( pl.Via() ) );
}
if( realEnd && lastSeg )
simplifyNewLine( m_lastNode, lastSeg );
Router()->CommitRouting( m_lastNode );
m_lastNode = NULL;
m_currentNode = NULL;
if( !realEnd )
{
setInitialDirection( d_last );
m_currentStart = m_placingVia ? p_last : p_pre_last;
m_fixedTail.AddStage( m_p_start, m_currentLayer, m_placingVia, m_direction, m_currentNode );
m_startItem = NULL;
m_placingVia = false;
m_chainedPlacement = !pl.EndsWithVia();
initPlacement();
m_p_start = m_currentStart;
m_direction = m_initial_direction;
m_head.Line().Clear();
m_tail.Line().Clear();
m_currentNode = m_lastNode;
m_lastNode = m_lastNode->Branch();
if ( m_shove )
{
m_shove->AddLockedSpringbackNode( m_currentNode );
}
}
else
{
@ -1178,6 +1202,56 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
}
bool LINE_PLACER::UnfixRoute()
{
FIXED_TAIL::STAGE st;
if ( !m_fixedTail.PopStage( st ) )
return false;
m_head.Line().Clear();
m_tail.Line().Clear();
m_startItem = NULL;
m_p_start = st.pts[0].p;
m_direction = st.pts[0].direction;
m_placingVia = st.pts[0].placingVias;
m_currentNode = st.commit;
m_currentLayer = st.pts[0].layer;
m_head.SetLayer( m_currentLayer );
m_tail.SetLayer( m_currentLayer );
m_head.RemoveVia( );
m_tail.RemoveVia( );
if (m_shove)
{
m_shove->RewindSpringbackTo( m_currentNode );
m_shove->UnlockSpringbackNode( m_currentNode );
m_currentNode = m_shove->CurrentNode();
m_currentNode->KillChildren();
}
m_lastNode = m_currentNode->Branch();
return true;
}
bool LINE_PLACER::HasPlacedAnything() const
{
return m_fixedTail.StageCount() > 1;
}
bool LINE_PLACER::CommitPlacement()
{
Router()->CommitRouting( m_lastNode );
m_lastNode = NULL;
m_currentNode = NULL;
return true;
}
void LINE_PLACER::removeLoops( NODE* aNode, LINE& aLatest )
{
if( !aLatest.SegmentCount() )
@ -1252,7 +1326,7 @@ void LINE_PLACER::UpdateSizes( const SIZES_SETTINGS& aSizes )
// initPlacement will kill the tail, don't do that unless the track size has changed
if( !m_idle && aSizes.TrackWidth() != m_sizes.TrackWidth() )
{
m_sizes = aSizes;
m_sizes = aSizes;
initPlacement();
}
@ -1266,8 +1340,8 @@ void LINE_PLACER::updateLeadingRatLine()
SHAPE_LINE_CHAIN ratLine;
TOPOLOGY topo( m_lastNode );
//if( topo.LeadingRatLine( &current, ratLine ) )
//Dbg()->AddLine( ratLine, 5, 10000 );
if( topo.LeadingRatLine( &current, ratLine ) )
Dbg()->AddLine( ratLine, 5, 10000 );
}
@ -1313,6 +1387,7 @@ bool LINE_PLACER::buildInitialLine( const VECTOR2I& aP, LINE& aHead, bool aInver
}
}
aHead.SetLayer( m_currentLayer );
aHead.SetShape( l );
if( !m_placingVia )
@ -1351,4 +1426,61 @@ void LINE_PLACER::GetModifiedNets( std::vector<int>& aNets ) const
}
bool LINE_PLACER::AbortPlacement()
{
m_world->KillChildren();
return true;
}
FIXED_TAIL::FIXED_TAIL ( int aLineCount )
{
}
FIXED_TAIL::~FIXED_TAIL()
{
}
void FIXED_TAIL::Clear()
{
m_stages.clear();
}
void FIXED_TAIL::AddStage( VECTOR2I aStart, int aLayer, bool placingVias, DIRECTION_45 direction, NODE *aNode )
{
STAGE st;
FIX_POINT pt;
pt.p = aStart;
pt.layer = aLayer;
pt.direction = direction;
pt.placingVias = placingVias;
st.pts.push_back(pt);
st.commit = aNode;
m_stages.push_back( st );
}
bool FIXED_TAIL::PopStage( FIXED_TAIL::STAGE& aStage )
{
if( !m_stages.size() )
return false;
aStage = m_stages.back();
if( m_stages.size() > 1 )
m_stages.pop_back();
return true;
}
int FIXED_TAIL::StageCount() const
{
return m_stages.size();
}
}

View File

@ -40,7 +40,35 @@ class SHOVE;
class OPTIMIZER;
class VIA;
class SIZES_SETTINGS;
class NODE;
class FIXED_TAIL {
public:
FIXED_TAIL ( int aLineCount = 1);
~FIXED_TAIL();
struct FIX_POINT
{
int layer;
bool placingVias;
VECTOR2I p;
DIRECTION_45 direction;
};
struct STAGE {
NODE *commit;
std::vector<FIX_POINT> pts;
};
void Clear();
void AddStage( VECTOR2I aStart, int aLayer, bool placingVias, DIRECTION_45 direction, NODE *aNode );
bool PopStage( STAGE& aStage );
int StageCount() const;
private:
std::vector<STAGE> m_stages;
};
/**
* LINE_PLACER
@ -83,6 +111,14 @@ public:
*/
bool FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish ) override;
bool UnfixRoute() override;
bool CommitPlacement() override;
bool AbortPlacement() override;
bool HasPlacedAnything() const override;
/**
* Function ToggleVia()
*
@ -187,8 +223,6 @@ public:
void GetModifiedNets( std::vector<int>& aNets ) const override;
LOGGER* Logger() override;
/**
* Function SplitAdjacentSegments()
*
@ -398,6 +432,8 @@ private:
bool m_idle;
bool m_chainedPlacement;
bool m_orthoMode;
FIXED_TAIL m_fixedTail;
};
}

View File

@ -1276,7 +1276,6 @@ void NODE::Commit( NODE* aNode )
void NODE::KillChildren()
{
assert( isRoot() );
releaseChildren();
}

View File

@ -423,6 +423,11 @@ public:
return !m_children.empty();
}
NODE* GetParent() const
{
return m_parent;
}
///> checks if this branch contains an updated version of the m_item
///> from the root branch.
bool Overrides( ITEM* aItem ) const

View File

@ -197,7 +197,7 @@ void OPTIMIZER::removeCachedSegments( LINE* aLine, int aStartVertex, int aEndVer
for( int i = aStartVertex; i < aEndVertex - 1; i++ )
{
SEGMENT* s = segs[i];
LINKED_ITEM* s = segs[i];
m_cacheTags.erase( s );
m_cache.Remove( s );
}
@ -344,7 +344,7 @@ static bool pointInside2( const SHAPE_LINE_CHAIN& aL, const VECTOR2I& aP )
if( (ipNext.x ==aP.x) || ( ip.y ==aP.y
&& ( (ipNext.x >aP.x) == (ip.x <aP.x) ) ) )
return -1;
}
}
if( (ip.y <aP.y) != (ipNext.y <aP.y) )
{

View File

@ -78,6 +78,14 @@ public:
*/
virtual bool FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish = false ) = 0;
virtual bool UnfixRoute() { return false; };
virtual bool CommitPlacement() { return false; };
virtual bool AbortPlacement() { return false; };
virtual bool HasPlacedAnything() const { return false; }
/**
* Function ToggleVia()
*
@ -183,6 +191,8 @@ public:
virtual void GetModifiedNets( std::vector<int> &aNets ) const
{
}
};
}

View File

@ -360,6 +360,9 @@ void ROUTER::movePlacing( const VECTOR2I& aP, ITEM* aEndItem )
void ROUTER::CommitRouting( NODE* aNode )
{
if( m_state == ROUTE_TRACK && !m_placer->HasPlacedAnything() )
return;
NODE::ITEM_VECTOR removed, added;
aNode->GetUpdatedItems( removed, added );
@ -393,13 +396,26 @@ bool ROUTER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
break;
}
if( rv )
StopRouting();
return rv;
}
void ROUTER::UndoLastSegment()
{
if( !RoutingInProgress() )
return;
m_placer->UnfixRoute();
}
void ROUTER::CommitRouting()
{
m_placer->CommitPlacement();
StopRouting();
}
void ROUTER::StopRouting()
{
// Update the ratsnest with new changes

View File

@ -141,6 +141,8 @@ public:
bool FixRoute( const VECTOR2I& aP, ITEM* aItem, bool aForceFinish = false );
void BreakSegment( ITEM *aItem, const VECTOR2I& aP );
void UndoLastSegment();
void CommitRouting();
void StopRouting();
int GetClearance( const ITEM* aA, const ITEM* aB ) const;

View File

@ -626,7 +626,7 @@ NODE* SHOVE::reduceSpringback( const ITEM_SET& aHeadSet, VIA_HANDLE& aDraggedVia
auto obs = spTag.m_node->CheckColliding( aHeadSet );
if( !obs )
if( !obs && !spTag.m_locked )
{
aDraggedVia = spTag.m_draggedVia;
aDraggedVia.valid = true;
@ -670,6 +670,9 @@ bool SHOVE::pushSpringback( NODE* aNode, const OPT_BOX2I& aAffectedArea, VIA* aD
} else
st.m_affectedArea = prev_area;
st.m_seq = (m_nodeStack.empty() ? 1 : m_nodeStack.back().m_seq + 1);
st.m_locked = false;
m_nodeStack.push_back( st );
return true;
@ -1607,4 +1610,61 @@ void SHOVE::SetInitialLine( LINE& aInitial )
m_root->Remove( aInitial );
}
bool SHOVE::AddLockedSpringbackNode( NODE* aNode )
{
SPRINGBACK_TAG sp;
sp.m_node = aNode;
sp.m_locked = true;
m_nodeStack.push_back(sp);
return true;
}
bool SHOVE::RewindSpringbackTo( NODE* aNode )
{
bool found = false;
auto iter = m_nodeStack.begin();
while( iter != m_nodeStack.end() )
{
if ( iter->m_node == aNode )
{
printf("FOUND\n");
found = true;
break;
}
iter++;
}
if( !found )
return false;
auto start = iter;
aNode->KillChildren();
m_nodeStack.erase( start, m_nodeStack.end() );
return true;
}
void SHOVE::UnlockSpringbackNode( NODE* aNode )
{
auto iter = m_nodeStack.begin();
while( iter != m_nodeStack.end() )
{
if ( iter->m_node == aNode )
{
iter->m_locked = false;
break;
}
iter++;
}
}
}

View File

@ -86,6 +86,10 @@ public:
void SetInitialLine( LINE& aInitial );
bool AddLockedSpringbackNode( NODE* aNode );
void UnlockSpringbackNode( NODE* aNode );
bool RewindSpringbackTo( NODE* aNode );
private:
typedef std::vector<SHAPE_LINE_CHAIN> HULL_SET;
typedef OPT<LINE> OPT_LINE;
@ -99,6 +103,8 @@ private:
VECTOR2I m_p;
NODE* m_node;
OPT_BOX2I m_affectedArea;
int m_seq;
bool m_locked;
};
SHOVE_STATUS processHullSet( LINE& aCurrent, LINE& aObstacle,
@ -147,6 +153,7 @@ private:
NODE* m_root;
NODE* m_currentNode;
int m_restrictSpringbackTagId;
OPT_LINE m_newHead;

View File

@ -224,20 +224,20 @@ const WALKAROUND::RESULT WALKAROUND::Route( const LINE& aInitialPath )
//Dbg()->AddLine( path_cw.CLine(), 2, 10000 );
printf("iter %d s_cw %d s_ccw %d\n", m_iteration, s_cw, s_ccw );
//printf("iter %d s_cw %d s_ccw %d\n", m_iteration, s_cw, s_ccw );
auto old = path_cw.CLine();
if( clipToLoopStart( path_cw.Line() ))
{
printf("ClipCW\n");
//printf("ClipCW\n");
//Dbg()->AddLine( old, 1, 40000 );
s_cw = ALMOST_DONE;
}
if( clipToLoopStart( path_ccw.Line() ))
{
printf("ClipCCW\n");
//printf("ClipCCW\n");
s_ccw = ALMOST_DONE;
}

View File

@ -75,6 +75,12 @@ enum VIA_ACTION_FLAGS
#undef _
#define _(s) s
static const TOOL_ACTION ACT_UndoLastSegment( "pcbnew.InteractiveRouter.UndoLastSegment",
AS_CONTEXT,
WXK_BACK, "",
_( "Undo last segment" ), _( "Stops laying the current track." ),
checked_ok_xpm );
static const TOOL_ACTION ACT_EndTrack( "pcbnew.InteractiveRouter.EndTrack",
AS_CONTEXT,
WXK_END, "",
@ -389,6 +395,7 @@ public:
Add( PCB_ACTIONS::routeSingleTrack );
Add( PCB_ACTIONS::routeDiffPair );
Add( ACT_EndTrack );
Add( ACT_UndoLastSegment );
Add( PCB_ACTIONS::breakTrack );
Add( PCB_ACTIONS::drag45Degree );
@ -757,6 +764,8 @@ bool ROUTER_TOOL::finishInteractive()
void ROUTER_TOOL::performRouting()
{
bool finished = false;
if( !prepareInteractive() )
return;
@ -775,6 +784,12 @@ void ROUTER_TOOL::performRouting()
updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem );
}
else if( evt->IsAction( &ACT_UndoLastSegment ) )
{
m_router->UndoLastSegment();
updateEndItem( *evt );
m_router->Move( m_endSnapPoint, m_endItem );
}
else if( evt->IsClick( BUT_LEFT ) || evt->IsAction( &PCB_ACTIONS::routeSingleTrack ) )
{
updateEndItem( *evt );
@ -783,7 +798,10 @@ void ROUTER_TOOL::performRouting()
if( m_router->FixRoute( m_endSnapPoint, m_endItem, forceFinish ) )
{
finished = true;
break;
}
if( needLayerSwitch )
switchLayerOnViaPlacement();
@ -840,6 +858,9 @@ void ROUTER_TOOL::performRouting()
}
}
m_router->CommitRouting();
m_router->StopRouting();
finishInteractive();
}

View File

@ -189,6 +189,8 @@ public:
/// Activation of the Push and Shove router (skew tuning mode)
static TOOL_ACTION routerTuneDiffPairSkew;
static TOOL_ACTION routerUndoLastSegment;
/// Activation of the Push and Shove settings dialogs
static TOOL_ACTION routerSettingsDialog;
static TOOL_ACTION routerDiffPairDialog;