router: initial attempt at improved 'aim at mouse cursor' strategy in walkaround mode, wip...
This commit is contained in:
parent
43b71cd9e3
commit
37a754c4dd
|
@ -366,10 +366,32 @@ bool LINE_PLACER::mergeHead()
|
|||
}
|
||||
|
||||
|
||||
VECTOR2I closestProjectedPoint( const SHAPE_LINE_CHAIN& line, const VECTOR2I& p )
|
||||
{
|
||||
int min_dist = INT_MAX;
|
||||
VECTOR2I closest;
|
||||
|
||||
for(int i = 0; i < line.SegmentCount(); i++ )
|
||||
{
|
||||
const auto& s = line.CSegment(i);
|
||||
auto a = s.NearestPoint( p );
|
||||
auto d = (a - p).EuclideanNorm();
|
||||
|
||||
if( d < min_dist )
|
||||
{
|
||||
min_dist = d;
|
||||
closest = a;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
|
||||
bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead )
|
||||
{
|
||||
LINE initTrack( m_head );
|
||||
LINE walkFull;
|
||||
LINE walkFull( m_head );
|
||||
int effort = 0;
|
||||
bool rv = true, viaOk;
|
||||
|
||||
|
@ -379,9 +401,40 @@ bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead )
|
|||
|
||||
walkaround.SetSolidsOnly( false );
|
||||
walkaround.SetDebugDecorator( Dbg() );
|
||||
walkaround.SetLogger( Logger() );
|
||||
walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
|
||||
|
||||
WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false );
|
||||
WALKAROUND::RESULT wr = walkaround.Route( initTrack );
|
||||
//WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false );
|
||||
|
||||
auto l_cw = wr.lineCw.CLine();
|
||||
auto l_ccw = wr.lineCcw.CLine();
|
||||
|
||||
if( wr.statusCcw == WALKAROUND::ALMOST_DONE || wr.statusCw == WALKAROUND::ALMOST_DONE )
|
||||
{
|
||||
|
||||
auto p_cw = closestProjectedPoint( l_cw, aP );
|
||||
auto p_ccw = closestProjectedPoint( l_ccw, aP );
|
||||
|
||||
int idx_cw = l_cw.Split( p_cw );
|
||||
int idx_ccw = l_ccw.Split( p_ccw );
|
||||
|
||||
l_cw = l_cw.Slice( 0, idx_cw );
|
||||
l_ccw = l_ccw.Slice( 0, idx_ccw );
|
||||
|
||||
//Dbg()->AddLine( wr.lineCw.CLine(), 3, 40000 );
|
||||
|
||||
//Dbg()->AddPoint( p_cw, 4 );
|
||||
//Dbg()->AddPoint( p_ccw, 5 );
|
||||
|
||||
//Dbg()->AddLine( wr.lineCw.CLine(), 4, 1000 );
|
||||
//Dbg()->AddLine( wr.lineCcw.CLine(), 5, 1000 );
|
||||
|
||||
}
|
||||
|
||||
walkFull.SetShape( l_ccw.Length() < l_cw.Length() ? l_ccw : l_cw );
|
||||
|
||||
Dbg()->AddLine( walkFull.CLine(), 2, 100000, "walk-full" );
|
||||
|
||||
switch( Settings().OptimizerEffort() )
|
||||
{
|
||||
|
@ -398,7 +451,7 @@ bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead )
|
|||
if( Settings().SmartPads() )
|
||||
effort |= OPTIMIZER::SMART_PADS;
|
||||
|
||||
if( wf == WALKAROUND::STUCK )
|
||||
if( wr.statusCw == WALKAROUND::STUCK || wr.statusCcw == WALKAROUND::STUCK )
|
||||
{
|
||||
walkFull = walkFull.ClipToNearestObstacle( m_currentNode );
|
||||
rv = true;
|
||||
|
@ -578,6 +631,10 @@ bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead )
|
|||
bool viaOk = buildInitialLine( aP, initTrack );
|
||||
|
||||
m_currentNode = m_shove->CurrentNode();
|
||||
|
||||
m_shove->SetLogger( Logger() );
|
||||
m_shove->SetDebugDecorator( Dbg() );
|
||||
|
||||
OPTIMIZER optimizer( m_currentNode );
|
||||
|
||||
WALKAROUND walkaround( m_currentNode, Router() );
|
||||
|
@ -585,6 +642,7 @@ bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead )
|
|||
walkaround.SetSolidsOnly( true );
|
||||
walkaround.SetIterationLimit( 10 );
|
||||
walkaround.SetDebugDecorator( Dbg() );
|
||||
walkaround.SetLogger( Logger() );
|
||||
WALKAROUND::WALKAROUND_STATUS stat_solids = walkaround.Route( initTrack, walkSolids );
|
||||
|
||||
optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS );
|
||||
|
@ -1204,8 +1262,8 @@ void LINE_PLACER::updateLeadingRatLine()
|
|||
SHAPE_LINE_CHAIN ratLine;
|
||||
TOPOLOGY topo( m_lastNode );
|
||||
|
||||
if( topo.LeadingRatLine( ¤t, ratLine ) )
|
||||
Dbg()->AddLine( ratLine, 5, 10000 );
|
||||
//if( topo.LeadingRatLine( ¤t, ratLine ) )
|
||||
//Dbg()->AddLine( ratLine, 5, 10000 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1288,12 +1346,5 @@ void LINE_PLACER::GetModifiedNets( std::vector<int>& aNets ) const
|
|||
aNets.push_back( m_currentNet );
|
||||
}
|
||||
|
||||
LOGGER* LINE_PLACER::Logger()
|
||||
{
|
||||
if( m_shove )
|
||||
return m_shove->Logger();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "pns_optimizer.h"
|
||||
#include "pns_utils.h"
|
||||
#include "pns_router.h"
|
||||
#include "pns_debug_decorator.h"
|
||||
|
||||
namespace PNS {
|
||||
|
||||
|
@ -57,8 +58,6 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::singleStep( LINE& aPath,
|
|||
OPT<OBSTACLE>& current_obs =
|
||||
aWindingDirection ? m_currentObstacle[0] : m_currentObstacle[1];
|
||||
|
||||
bool& prev_recursive = aWindingDirection ? m_recursiveCollision[0] : m_recursiveCollision[1];
|
||||
|
||||
if( !current_obs )
|
||||
return DONE;
|
||||
|
||||
|
@ -79,23 +78,36 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::singleStep( LINE& aPath,
|
|||
}
|
||||
}
|
||||
|
||||
if( ! aPath.Walkaround( current_obs->m_hull, path_pre[0], path_walk[0],
|
||||
path_post[0], aWindingDirection ) )
|
||||
return STUCK;
|
||||
aPath.Walkaround( current_obs->m_hull, path_pre[0], path_walk[0],
|
||||
path_post[0], aWindingDirection );
|
||||
aPath.Walkaround( current_obs->m_hull, path_pre[1], path_walk[1],
|
||||
path_post[1], !aWindingDirection );
|
||||
|
||||
if( ! aPath.Walkaround( current_obs->m_hull, path_pre[1], path_walk[1],
|
||||
path_post[1], !aWindingDirection ) )
|
||||
return STUCK;
|
||||
|
||||
auto l =aPath.CLine();
|
||||
#ifdef DEBUG
|
||||
m_logger.NewGroup( aWindingDirection ? "walk-cw" : "walk-ccw", m_iteration );
|
||||
m_logger.Log( &path_walk[0], 0, "path-walk" );
|
||||
m_logger.Log( &path_pre[0], 1, "path-pre" );
|
||||
m_logger.Log( &path_post[0], 4, "path-post" );
|
||||
m_logger.Log( ¤t_obs->m_hull, 2, "hull" );
|
||||
m_logger.Log( current_obs->m_item, 3, "item" );
|
||||
if( m_logger )
|
||||
{
|
||||
m_logger->NewGroup( aWindingDirection ? "walk-cw" : "walk-ccw", m_iteration );
|
||||
m_logger->Log( &path_walk[0], 0, "path_walk" );
|
||||
m_logger->Log( &path_pre[0], 1, "path_pre" );
|
||||
m_logger->Log( &path_post[0], 4, "path_post" );
|
||||
m_logger->Log( ¤t_obs->m_hull, 2, "hull" );
|
||||
m_logger->Log( current_obs->m_item, 3, "item" );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( Dbg() )
|
||||
{
|
||||
char name[128];
|
||||
snprintf(name, sizeof(name), "hull-%s-%d", aWindingDirection ? "cw" : "ccw", m_iteration );
|
||||
Dbg()->AddLine( current_obs->m_hull, 0, 1, name);
|
||||
snprintf(name, sizeof(name), "path-%s-%d", aWindingDirection ? "cw" : "ccw", m_iteration );
|
||||
Dbg()->AddLine( aPath.CLine(), 1, 1, name );
|
||||
}
|
||||
|
||||
int len_pre = path_walk[0].Length();
|
||||
int len_alt = path_walk[1].Length();
|
||||
|
||||
|
@ -105,7 +117,7 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::singleStep( LINE& aPath,
|
|||
|
||||
SHAPE_LINE_CHAIN pnew;
|
||||
|
||||
if( !m_forceLongerPath && len_alt < len_pre && !alt_collides && !prev_recursive )
|
||||
/*if( !m_forceLongerPath && len_alt < len_pre && !alt_collides && !prev_recursive )
|
||||
{
|
||||
pnew = path_pre[1];
|
||||
pnew.Append( path_walk[1] );
|
||||
|
@ -115,26 +127,22 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::singleStep( LINE& aPath,
|
|||
current_obs = nearestObstacle( LINE( aPath, path_pre[1] ) );
|
||||
else
|
||||
current_obs = nearestObstacle( LINE( aPath, path_post[1] ) );
|
||||
prev_recursive = false;
|
||||
}
|
||||
else
|
||||
else*/
|
||||
{
|
||||
pnew = path_pre[0];
|
||||
pnew.Append( path_walk[0] );
|
||||
pnew.Append( path_post[0] );
|
||||
|
||||
if( !path_post[0].PointCount() || !path_walk[0].PointCount() )
|
||||
if( path_post[0].PointCount() == 0 || path_walk[0].PointCount() == 0 )
|
||||
current_obs = nearestObstacle( LINE( aPath, path_pre[0] ) );
|
||||
else
|
||||
current_obs = nearestObstacle( LINE( aPath, path_walk[0] ) );
|
||||
|
||||
if( !current_obs )
|
||||
{
|
||||
prev_recursive = false;
|
||||
current_obs = nearestObstacle( LINE( aPath, path_post[0] ) );
|
||||
}
|
||||
else
|
||||
prev_recursive = true;
|
||||
}
|
||||
|
||||
pnew.Simplify();
|
||||
|
@ -144,6 +152,154 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::singleStep( LINE& aPath,
|
|||
}
|
||||
|
||||
|
||||
|
||||
bool clipToLoopStart( SHAPE_LINE_CHAIN& l )
|
||||
{
|
||||
auto ip = l.SelfIntersecting();
|
||||
|
||||
if(!ip)
|
||||
return false;
|
||||
else {
|
||||
int pidx = l.Split( ip->p );
|
||||
auto lead = l.Slice(0, pidx);
|
||||
auto tail = l.Slice(pidx + 1, -1);
|
||||
|
||||
int pidx2 = tail.Split( ip->p );
|
||||
|
||||
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
|
||||
dbg->AddPoint( ip->p, 5 );
|
||||
|
||||
l = lead;
|
||||
l.Append( tail.Slice( 0, pidx2 ) );
|
||||
//l = l.Slice(0, pidx);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const WALKAROUND::RESULT WALKAROUND::Route( const LINE& aInitialPath )
|
||||
{
|
||||
LINE path_cw( aInitialPath ), path_ccw( aInitialPath );
|
||||
WALKAROUND_STATUS s_cw = IN_PROGRESS, s_ccw = IN_PROGRESS;
|
||||
SHAPE_LINE_CHAIN best_path;
|
||||
RESULT result;
|
||||
|
||||
// special case for via-in-the-middle-of-track placement
|
||||
if( aInitialPath.PointCount() <= 1 )
|
||||
{
|
||||
if( aInitialPath.EndsWithVia() && m_world->CheckColliding( &aInitialPath.Via(), m_itemMask ) )
|
||||
return RESULT( STUCK, STUCK );
|
||||
|
||||
return RESULT( DONE, DONE, aInitialPath, aInitialPath );
|
||||
}
|
||||
|
||||
start( aInitialPath );
|
||||
|
||||
m_currentObstacle[0] = m_currentObstacle[1] = nearestObstacle( aInitialPath );
|
||||
m_recursiveBlockageCount = 0;
|
||||
|
||||
result.lineCw = aInitialPath;
|
||||
result.lineCcw = aInitialPath;
|
||||
|
||||
if( m_forceWinding )
|
||||
{
|
||||
s_cw = m_forceCw ? IN_PROGRESS : STUCK;
|
||||
s_ccw = m_forceCw ? STUCK : IN_PROGRESS;
|
||||
m_forceSingleDirection = true;
|
||||
} else {
|
||||
m_forceSingleDirection = false;
|
||||
}
|
||||
|
||||
while( m_iteration < m_iterationLimit )
|
||||
{
|
||||
if( s_cw != STUCK )
|
||||
s_cw = singleStep( path_cw, true );
|
||||
|
||||
if( s_ccw != STUCK )
|
||||
s_ccw = singleStep( path_ccw, false );
|
||||
|
||||
//Dbg()->AddLine( path_cw.CLine(), 2, 10000 );
|
||||
|
||||
|
||||
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");
|
||||
//Dbg()->AddLine( old, 1, 40000 );
|
||||
s_cw = ALMOST_DONE;
|
||||
}
|
||||
|
||||
if( clipToLoopStart( path_ccw.Line() ))
|
||||
{
|
||||
printf("ClipCCW\n");
|
||||
s_ccw = ALMOST_DONE;
|
||||
}
|
||||
|
||||
|
||||
if( s_cw != IN_PROGRESS )
|
||||
{
|
||||
result.lineCw = path_cw;
|
||||
result.statusCw = s_cw;
|
||||
}
|
||||
|
||||
if( s_ccw != IN_PROGRESS )
|
||||
{
|
||||
result.lineCcw = path_ccw;
|
||||
result.statusCcw = s_ccw;
|
||||
}
|
||||
|
||||
if( s_cw != IN_PROGRESS && s_ccw != IN_PROGRESS )
|
||||
break;
|
||||
|
||||
m_iteration++;
|
||||
}
|
||||
|
||||
if( s_cw == IN_PROGRESS )
|
||||
{
|
||||
result.lineCw = path_cw;
|
||||
result.statusCw = ALMOST_DONE;
|
||||
}
|
||||
|
||||
if( s_ccw == IN_PROGRESS )
|
||||
{
|
||||
result.lineCcw = path_ccw;
|
||||
result.statusCcw = ALMOST_DONE;
|
||||
}
|
||||
|
||||
result.lineCw.Line().Simplify();
|
||||
result.lineCcw.Line().Simplify();
|
||||
|
||||
if( result.lineCw.SegmentCount() < 1 || result.lineCw.CPoint( 0 ) != aInitialPath.CPoint( 0 ) )
|
||||
{
|
||||
result.statusCw = STUCK;
|
||||
}
|
||||
|
||||
if( result.lineCw.PointCount() > 0 && result.lineCw.CPoint( -1 ) != aInitialPath.CPoint( -1 ) )
|
||||
{
|
||||
result.statusCw = ALMOST_DONE;
|
||||
}
|
||||
|
||||
if( result.lineCcw.SegmentCount() < 1 || result.lineCcw.CPoint( 0 ) != aInitialPath.CPoint( 0 ) )
|
||||
{
|
||||
result.statusCcw = STUCK;
|
||||
}
|
||||
|
||||
if( result.lineCcw.PointCount() > 0 && result.lineCcw.CPoint( -1 ) != aInitialPath.CPoint( -1 ) )
|
||||
{
|
||||
result.statusCcw = ALMOST_DONE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WALKAROUND::WALKAROUND_STATUS WALKAROUND::Route( const LINE& aInitialPath,
|
||||
LINE& aWalkPath, bool aOptimize )
|
||||
{
|
||||
|
@ -261,7 +417,7 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::Route( const LINE& aInitialPath,
|
|||
if( aWalkPath.SegmentCount() < 1 )
|
||||
return STUCK;
|
||||
if( aWalkPath.CPoint( -1 ) != aInitialPath.CPoint( -1 ) )
|
||||
return STUCK;
|
||||
return ALMOST_DONE;
|
||||
if( aWalkPath.CPoint( 0 ) != aInitialPath.CPoint( 0 ) )
|
||||
return STUCK;
|
||||
|
||||
|
|
|
@ -60,10 +60,25 @@ public:
|
|||
enum WALKAROUND_STATUS
|
||||
{
|
||||
IN_PROGRESS = 0,
|
||||
ALMOST_DONE,
|
||||
DONE,
|
||||
STUCK
|
||||
};
|
||||
|
||||
struct RESULT
|
||||
{
|
||||
RESULT( WALKAROUND_STATUS aStatusCw = STUCK, WALKAROUND_STATUS aStatusCcw = STUCK, const LINE& aLineCw = LINE(), const LINE& aLineCcw = LINE() )
|
||||
{
|
||||
statusCw = aStatusCw;
|
||||
statusCcw = aStatusCcw;
|
||||
lineCw = aLineCw;
|
||||
lineCcw = aLineCcw;
|
||||
}
|
||||
|
||||
WALKAROUND_STATUS statusCw, statusCcw;
|
||||
LINE lineCw, lineCcw;
|
||||
};
|
||||
|
||||
void SetWorld( NODE* aNode )
|
||||
{
|
||||
m_world = aNode;
|
||||
|
@ -121,10 +136,7 @@ public:
|
|||
WALKAROUND_STATUS Route( const LINE& aInitialPath, LINE& aWalkPath,
|
||||
bool aOptimize = true );
|
||||
|
||||
virtual LOGGER* Logger() override
|
||||
{
|
||||
return &m_logger;
|
||||
}
|
||||
const RESULT Route( const LINE& aInitialPath );
|
||||
|
||||
private:
|
||||
void start( const LINE& aInitialPath );
|
||||
|
@ -142,10 +154,10 @@ private:
|
|||
bool m_cursorApproachMode;
|
||||
bool m_forceWinding;
|
||||
bool m_forceCw;
|
||||
bool m_forceUniqueWindingDirection;
|
||||
VECTOR2I m_cursorPos;
|
||||
NODE::OPT_OBSTACLE m_currentObstacle[2];
|
||||
bool m_recursiveCollision[2];
|
||||
LOGGER m_logger;
|
||||
std::set<ITEM*> m_restrictedSet;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue