router: drag in walkaround mode now works

This commit is contained in:
Tomasz Wlostowski 2020-10-19 23:33:32 +02:00
parent f84836f51e
commit a4bd2ad8c6
2 changed files with 142 additions and 73 deletions

View File

@ -47,6 +47,24 @@ DRAGGER::~DRAGGER()
}
bool DRAGGER::propagateViaForces( NODE* node, std::set<VIA*>& vias )
{
VIA* via = *vias.begin();
VECTOR2I force;
VECTOR2I lead = m_mouseTrailTracer.GetTrailLeadVector();
bool solidsOnly = false;// ( m_currentMode != RM_Walkaround );
if( via->PushoutForce( node, lead, force, solidsOnly, 40 ) )
{
via->SetPos( via->Pos() + force );
return true;
}
return false;
}
bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg )
{
int w2 = aSeg->Width() / 2;
@ -153,6 +171,9 @@ bool DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
m_freeAngleMode = (m_mode & DM_FREE_ANGLE);
m_lastValidPoint = aP;
m_mouseTrailTracer.Clear();
m_mouseTrailTracer.AddTrailPoint( aP );
if( m_currentMode == RM_Shove && !m_freeAngleMode )
{
m_shove = std::make_unique<SHOVE>( m_world, Router() );
@ -241,7 +262,7 @@ bool DRAGGER::dragMarkObstacles( const VECTOR2I& aP )
}
void DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
bool DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
{
m_draggedItems.Clear();
@ -249,7 +270,7 @@ void DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, cons
if( fanout.Empty() )
{
return;
return true;
}
for( ITEM* item : fanout.Items() )
@ -278,10 +299,12 @@ void DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, cons
m_lastNode->Add( std::move( nvia ) );
}
}
return true;
}
void DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
bool DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
{
m_draggedItems.Clear();
@ -289,9 +312,11 @@ void DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const V
if( fanout.Empty() )
{
return;
return true;
}
bool viaPropOk = false;
VECTOR2I viaTargetPos;
for( ITEM* item : fanout.Items() )
{
@ -302,28 +327,61 @@ void DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const V
draggedVia->SetPos( aP );
m_draggedItems.Add( draggedVia.get() );
std::set<VIA*> vias;
vias.insert( draggedVia.get() );
bool ok = propagateViaForces( m_lastNode, vias );
if( ok )
{
viaTargetPos = draggedVia->Pos();
viaPropOk = true;
m_lastNode->Remove( via );
m_lastNode->Add( std::move(draggedVia) );
}
}
}
/*
if( !viaPropOk ) // can't force-propagate the via? bummer...
return false;
for( ITEM* item : fanout.Items() )
{
if( const LINE* l = dyn_cast<const LINE*>( item ) )
{
LINE origLine( *l );
LINE draggedLine( *l );
LINE walkLine( *l );
draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
draggedLine.DragCorner( viaTargetPos, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
draggedLine.ClearLinks();
if ( m_world->CheckColliding( &draggedLine ) )
{
bool ok = tryWalkaround( m_lastNode, draggedLine, walkLine );
if( !ok )
return false;
m_lastNode->Remove( origLine );
optimizeAndUpdateDraggedLine( walkLine, origLine, aP );
}
else
{
m_draggedItems.Add( draggedLine );
m_lastNode->Remove( origLine );
m_lastNode->Add( draggedLine );
}
else */
}
}
return true;
}
void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, SEG& aDraggedSeg, const VECTOR2I& aP )
void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, const VECTOR2I& aP )
{
VECTOR2D lockV;
aDragged.ClearLinks();
@ -337,6 +395,12 @@ void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, S
optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS | OPTIMIZER::KEEP_TOPOLOGY );
//printf("sa %d %d\n", aDraggedSeg.A.x, aDraggedSeg.A.y );
//Dbg()->AddPoint( aDraggedSeg.A, 4 );
//Dbg()->AddPoint( aDraggedSeg.B, 5 );
// Dbg()->AddLine( aDragged.CLine(), 3, 1000 );
OPT_BOX2I affectedArea = *aDragged.ChangedArea( &aOrig );
optimizer.SetPreserveVertex( aP );
@ -363,6 +427,40 @@ void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, S
}
bool DRAGGER::tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk )
{
WALKAROUND walkaround( aNode, Router() );
bool ok = false;
walkaround.SetSolidsOnly( false );
walkaround.SetDebugDecorator( Dbg() );
walkaround.SetLogger( Logger() );
walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
aWalk = aOrig;
WALKAROUND::RESULT wr = walkaround.Route( aWalk );
if( wr.statusCcw == WALKAROUND::DONE && wr.statusCw == WALKAROUND::DONE )
{
aWalk = ( wr.lineCw.CLine().Length() < wr.lineCcw.CLine().Length() ? wr.lineCw :
wr.lineCcw );
ok = true;
}
else if( wr.statusCw == WALKAROUND::DONE )
{
aWalk = wr.lineCw;
ok = true;
}
else if( wr.statusCcw == WALKAROUND::DONE )
{
aWalk = wr.lineCcw;
ok = true;
}
return ok;
}
bool DRAGGER::dragWalkaround( const VECTOR2I& aP )
{
bool ok = false;
@ -382,8 +480,11 @@ bool DRAGGER::dragWalkaround( const VECTOR2I& aP )
{
int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
LINE dragged( m_draggedLine );
LINE draggedWalk( m_draggedLine );
LINE origLine( m_draggedLine );
dragged.SetSnapThreshhold( thresh );
if( m_mode == DM_SEGMENT )
dragged.DragSegment( aP, m_draggedSegmentIndex );
else
@ -391,55 +492,28 @@ bool DRAGGER::dragWalkaround( const VECTOR2I& aP )
if ( m_world->CheckColliding( &dragged ) )
{
WALKAROUND walkaround( m_lastNode, Router() );
walkaround.SetSolidsOnly( false );
walkaround.SetDebugDecorator( Dbg() );
walkaround.SetLogger( Logger() );
walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
WALKAROUND::RESULT wr = walkaround.Route( dragged );
//Dbg()->AddLine( wr.lineCw.CLine(), 3, 200000 );
//Dbg()->AddLine( wr.lineCcw.CLine(), 2, 200000 );
if( wr.statusCcw == WALKAROUND::DONE && wr.statusCw == WALKAROUND::DONE )
{
dragged = ( wr.lineCw.CLine().Length() < wr.lineCcw.CLine().Length() ? wr.lineCw : wr.lineCcw );
ok = true;
}
else if ( wr.statusCw == WALKAROUND::DONE )
{
dragged = wr.lineCw;
ok = true;
}
else if ( wr.statusCcw == WALKAROUND::DONE )
{
dragged = wr.lineCcw;
ok = true;
}
ok = tryWalkaround( m_lastNode, dragged, draggedWalk );
}
else
{
draggedWalk = dragged;
ok = true;
}
if(ok)
{
//Dbg()->AddLine( origLine.CLine(), 4, 100000 );
m_lastNode->Remove( origLine );
SEG dummy;
optimizeAndUpdateDraggedLine( dragged, origLine, dummy, aP );
optimizeAndUpdateDraggedLine( draggedWalk, origLine, aP );
}
break;
}
case DM_VIA: // fixme...
{
dragViaWalkaround( m_initialVia, m_lastNode, aP );
ok = !m_world->CheckColliding( m_draggedItems );
}
ok = dragViaWalkaround( m_initialVia, m_lastNode, aP );
break;
}
}
m_dragStatus = ok;
@ -489,18 +563,7 @@ bool DRAGGER::dragShove( const VECTOR2I& aP )
dragged.ClearLinks();
dragged.Unmark();
lockV = dragged.CLine().NearestPoint( aP );
if( Settings().GetOptimizeDraggedTrack() )
{
OPTIMIZER::Optimize( &dragged, OPTIMIZER::MERGE_SEGMENTS
| OPTIMIZER::KEEP_TOPOLOGY
| OPTIMIZER::PRESERVE_VERTEX, m_lastNode, lockV );
}
m_lastNode->Add( dragged );
m_draggedItems.Clear();
m_draggedItems.Add( dragged );
optimizeAndUpdateDraggedLine( dragged, m_draggedLine, aP );
}
break;
@ -562,6 +625,8 @@ bool DRAGGER::FixRoute()
bool DRAGGER::Drag( const VECTOR2I& aP )
{
m_mouseTrailTracer.AddTrailPoint( aP );
bool ret = false;
if( m_freeAngleMode )

View File

@ -31,7 +31,7 @@
#include "pns_drag_algo.h"
#include "pns_itemset.h"
#include "pns_layerset.h"
#include "pns_mouse_trail_tracer.h"
namespace PNS {
@ -121,11 +121,13 @@ private:
bool startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg );
bool startDragArc( const VECTOR2D& aP, ARC* aArc );
bool startDragVia( VIA* aVia );
void dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP );
void dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP );
void optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, SEG& aDraggedSeg, const VECTOR2I& aP );
bool dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP );
bool dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP );
void optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, const VECTOR2I& aP );
bool propagateViaForces( NODE* node, std::set<VIA*>& vias );
bool tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk );
private:
VIA_HANDLE m_initialVia;
VIA_HANDLE m_draggedVia;
@ -136,6 +138,7 @@ private:
int m_draggedSegmentIndex;
bool m_dragStatus;
PNS_MODE m_currentMode;
ITEM_SET m_origViaConnections;
VECTOR2D m_lastValidPoint;
///< Contains the list of items that are currently modified by the dragger
@ -143,6 +146,7 @@ private:
///< If true, moves the connection lines without maintaining 45 degrees corners
bool m_freeAngleMode;
MOUSE_TRAIL_TRACER m_mouseTrailTracer;
};
}