router: improved heuristics in via force propagation algorithm

This commit is contained in:
Tomasz Wlostowski 2022-10-27 00:24:05 +02:00
parent 1ddabd4eaf
commit 363d606503
2 changed files with 49 additions and 15 deletions

View File

@ -23,6 +23,7 @@
#include "pns_node.h" #include "pns_node.h"
#include "pns_utils.h" #include "pns_utils.h"
#include "pns_router.h" #include "pns_router.h"
#include "pns_debug_decorator.h"
#include <geometry/shape_rect.h> #include <geometry/shape_rect.h>
#include <math/box2.h> #include <math/box2.h>
@ -63,35 +64,66 @@ bool VIA::PushoutForce( NODE* aNode, const ITEM* aOther, VECTOR2I& aForce )
} }
bool VIA::PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForce, bool VIA::PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForce,
bool aSolidsOnly, int aMaxIterations ) int aCollisionMask, int aMaxIterations )
{ {
int iter = 0; int iter = 0;
VIA mv( *this ); VIA mv( *this );
VECTOR2I totalForce; VECTOR2I totalForce;
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
PNS_DBG( dbg, AddPoint, Pos(), YELLOW, 100000, wxString::Format( "via-force-init-pos" ) );
while( iter < aMaxIterations ) while( iter < aMaxIterations )
{ {
NODE::OPT_OBSTACLE obs = aNode->CheckColliding( &mv, aSolidsOnly ? ITEM::SOLID_T NODE::OPT_OBSTACLE obs = aNode->CheckColliding( &mv, aCollisionMask );
: ITEM::ANY_T );
if( !obs ) if( !obs )
break; break;
if( iter > aMaxIterations / 2 )
{
VECTOR2I l = aDirection.Resize( m_diameter / 2 );
totalForce += l;
mv.SetPos( mv.Pos() + l );
}
VECTOR2I force; VECTOR2I force;
bool collFound = PushoutForce( aNode, obs->m_item, force ); bool collFound = PushoutForce( aNode, obs->m_item, force );
if( collFound ) if( !collFound )
break;
const int threshold = Diameter() / 4; // another stupid heuristic.
const int forceMag = force.EuclideanNorm();
// We've been through a lot of iterations already and our pushout force is still too big?
// Perhaps the barycentric force goes in the wrong direction, let's try to move along
// the 'lead' vector instead (usually backwards to the cursor)
if( iter > aMaxIterations / 2 && forceMag > threshold )
{ {
VECTOR2I l = aDirection.Resize( threshold );
totalForce += l;
SHAPE_LINE_CHAIN ff;
ff.Append( mv.Pos() );
ff.Append( mv.Pos() + l );
mv.SetPos( mv.Pos() + l );
PNS_DBG( dbg, AddShape, &ff, YELLOW, 100000, "via-force-lead" );
}
else if( collFound ) // push along the minmum translation vector
{
// Limit the force magnitude to, say, 25% of the via diameter
// This adds a few iterations for large areas (e.g. keepouts)
// But makes the algorithm more predictable and less 'jumpy'
if( forceMag > threshold )
{
force.Resize( threshold );
}
totalForce += force; totalForce += force;
SHAPE_LINE_CHAIN ff;
ff.Append( mv.Pos() );
ff.Append( mv.Pos() + force );
mv.SetPos( mv.Pos() + force ); mv.SetPos( mv.Pos() + force );
PNS_DBG( dbg, AddShape, &ff, WHITE, 100000, "via-force-coll" );
} }
iter++; iter++;
@ -100,6 +132,8 @@ bool VIA::PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForc
if( iter == aMaxIterations ) if( iter == aMaxIterations )
return false; return false;
PNS_DBG( dbg, AddPoint, ( Pos() + totalForce ), WHITE, 1000000, "via-force-new" );
aForce = totalForce; aForce = totalForce;
return true; return true;

View File

@ -129,7 +129,7 @@ public:
void SetIsFree( bool aIsFree ) { m_isFree = aIsFree; } void SetIsFree( bool aIsFree ) { m_isFree = aIsFree; }
bool PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForce, bool PushoutForce( NODE* aNode, const VECTOR2I& aDirection, VECTOR2I& aForce,
bool aSolidsOnly = true, int aMaxIterations = 10 ); int aCollisionMask = ITEM::ANY_T, int aMaxIterations = 10 );
bool PushoutForce( NODE* aNode, const ITEM* aOther, VECTOR2I& aForce ); bool PushoutForce( NODE* aNode, const ITEM* aOther, VECTOR2I& aForce );