Tweak the mouse-based posture solver
Add an epsilon to reduce flutter Add a lock after a certain distance Forget the old trail when unlocking Fixes https://gitlab.com/kicad/code/kicad/-/issues/5381
This commit is contained in:
parent
14a9c8dc42
commit
7a5c99ee0f
|
@ -980,7 +980,7 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
||||||
|
|
||||||
m_postureSolver.Clear();
|
m_postureSolver.Clear();
|
||||||
m_postureSolver.AddTrailPoint( aP );
|
m_postureSolver.AddTrailPoint( aP );
|
||||||
m_postureSolver.SetTollerance( m_head.Width() );
|
m_postureSolver.SetTolerance( m_head.Width() );
|
||||||
m_postureSolver.SetDefaultDirections( m_initial_direction, DIRECTION_45::UNDEFINED );
|
m_postureSolver.SetDefaultDirections( m_initial_direction, DIRECTION_45::UNDEFINED );
|
||||||
|
|
||||||
NODE *n;
|
NODE *n;
|
||||||
|
@ -1211,7 +1211,7 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
|
||||||
|
|
||||||
|
|
||||||
m_postureSolver.Clear();
|
m_postureSolver.Clear();
|
||||||
m_postureSolver.SetTollerance( m_head.Width() );
|
m_postureSolver.SetTolerance( m_head.Width() );
|
||||||
m_postureSolver.AddTrailPoint( m_currentStart );
|
m_postureSolver.AddTrailPoint( m_currentStart );
|
||||||
m_postureSolver.SetDefaultDirections( m_initial_direction, d_last );
|
m_postureSolver.SetDefaultDirections( m_initial_direction, d_last );
|
||||||
|
|
||||||
|
@ -1512,32 +1512,39 @@ int FIXED_TAIL::StageCount() const
|
||||||
return m_stages.size();
|
return m_stages.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
POSTURE_SOLVER::POSTURE_SOLVER()
|
POSTURE_SOLVER::POSTURE_SOLVER()
|
||||||
{
|
{
|
||||||
m_forced = false;
|
m_forced = false;
|
||||||
m_tollerance = 0;
|
m_tolerance = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
POSTURE_SOLVER::~POSTURE_SOLVER() {}
|
POSTURE_SOLVER::~POSTURE_SOLVER() {}
|
||||||
|
|
||||||
|
|
||||||
void POSTURE_SOLVER::Clear()
|
void POSTURE_SOLVER::Clear()
|
||||||
{
|
{
|
||||||
m_forced = false;
|
m_forced = false;
|
||||||
m_trail.Clear();
|
m_trail.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void POSTURE_SOLVER::AddTrailPoint( const VECTOR2I& aP )
|
void POSTURE_SOLVER::AddTrailPoint( const VECTOR2I& aP )
|
||||||
{
|
{
|
||||||
if( m_trail.SegmentCount() == 0 )
|
if( m_trail.SegmentCount() == 0 )
|
||||||
{
|
{
|
||||||
m_trail.Append(aP);
|
m_trail.Append( aP );
|
||||||
} else {
|
}
|
||||||
SEG s_new ( m_trail.CPoint(-1), aP );
|
else
|
||||||
|
{
|
||||||
|
SEG s_new( m_trail.CPoint( -1 ), aP );
|
||||||
|
|
||||||
for( int i = 0; i < m_trail.SegmentCount() - 1; i++ )
|
for( int i = 0; i < m_trail.SegmentCount() - 1; i++ )
|
||||||
{
|
{
|
||||||
const auto& s_trail = m_trail.CSegment(i);
|
const auto& s_trail = m_trail.CSegment( i );
|
||||||
if( s_trail.Distance( s_new ) <= m_tollerance )
|
|
||||||
|
if( s_trail.Distance( s_new ) <= m_tolerance )
|
||||||
{
|
{
|
||||||
m_trail = m_trail.Slice( 0, i );
|
m_trail = m_trail.Slice( 0, i );
|
||||||
break;
|
break;
|
||||||
|
@ -1551,62 +1558,72 @@ void POSTURE_SOLVER::AddTrailPoint( const VECTOR2I& aP )
|
||||||
|
|
||||||
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
|
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
|
||||||
|
|
||||||
dbg->AddLine(m_trail, 5, 100000 );
|
dbg->AddLine( m_trail, 5, 100000 );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
|
DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
|
||||||
{
|
{
|
||||||
if( m_trail.PointCount() < 2)
|
// Adjusts how far away from p0 we get before whatever posture we solved is locked in
|
||||||
return m_initDirection;
|
const int lockDistanceFactor = 40;
|
||||||
|
|
||||||
|
// Adjusts how close to p0 we unlock the posture again if one was locked already
|
||||||
|
const int unlockDistanceFactor = 4;
|
||||||
|
|
||||||
|
if( m_trail.PointCount() < 2 )
|
||||||
|
return m_direction;
|
||||||
|
|
||||||
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
|
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
|
||||||
|
|
||||||
auto p0 = m_trail.CPoint(0);
|
auto p0 = m_trail.CPoint( 0 );
|
||||||
auto bb = m_trail.BBox();
|
|
||||||
|
|
||||||
double refArea = bb.GetArea();
|
|
||||||
|
|
||||||
|
double refLength = SEG( p0, aP ).Length();
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN straight( DIRECTION_45().BuildInitialTrace( p0, aP, false ) );
|
SHAPE_LINE_CHAIN straight( DIRECTION_45().BuildInitialTrace( p0, aP, false ) );
|
||||||
straight.SetClosed(true);
|
straight.SetClosed( true );
|
||||||
straight.Append(m_trail.Reverse());
|
straight.Append( m_trail.Reverse() );
|
||||||
dbg->AddLine(straight, 2, 100000 );
|
dbg->AddLine( straight, m_forced ? 3 : 2, 100000 );
|
||||||
|
|
||||||
double areaS = straight.Area();
|
double areaS = straight.Area();
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN diag ( DIRECTION_45().BuildInitialTrace( p0, aP, true ) );
|
SHAPE_LINE_CHAIN diag( DIRECTION_45().BuildInitialTrace( p0, aP, true ) );
|
||||||
diag.Append(m_trail.Reverse());
|
diag.Append( m_trail.Reverse() );
|
||||||
diag.SetClosed(true);
|
diag.SetClosed( true );
|
||||||
dbg->AddLine(diag, 1, 100000 );
|
dbg->AddLine( diag, 1, 100000 );
|
||||||
|
|
||||||
double areaDiag = diag.Area();
|
double areaDiag = diag.Area();
|
||||||
double ratio = abs(areaS) / (fabs(areaDiag) + 1.0);
|
double ratio = abs( areaS ) / ( fabs( areaDiag ) + 1.0 );
|
||||||
|
|
||||||
// heuristic to detect that the user dragged back the cursor to the beginning of the trace
|
// heuristic to detect that the user dragged back the cursor to the beginning of the trace
|
||||||
// in this case, we cancel any forced posture
|
// in this case, we cancel any forced posture and restart the trail
|
||||||
if( sqrt(refArea) < 4 * m_tollerance )
|
if( m_forced && refLength < unlockDistanceFactor * m_tolerance )
|
||||||
{
|
{
|
||||||
m_forced = false;
|
m_forced = false;
|
||||||
|
VECTOR2I start = p0;
|
||||||
|
m_trail.Clear();
|
||||||
|
m_trail.Append( start );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( m_forced )
|
// If we get far away from the initial point, lock in the current solution to prevent flutter
|
||||||
return m_initDirection;
|
if( !m_forced && refLength > lockDistanceFactor * m_tolerance )
|
||||||
else if( ratio > areaRatioThreshold)
|
m_forced = true;
|
||||||
return DIRECTION_45::NE;
|
|
||||||
else if ( ratio < 1.0 / areaRatioThreshold )
|
|
||||||
return DIRECTION_45::N;
|
|
||||||
else if ( m_lastSegDirection != DIRECTION_45::UNDEFINED )
|
|
||||||
return m_lastSegDirection;
|
|
||||||
else
|
|
||||||
return m_initDirection;
|
|
||||||
|
|
||||||
|
if( m_forced )
|
||||||
|
return m_direction;
|
||||||
|
else if( ratio > areaRatioThreshold + areaRatioEpsilon )
|
||||||
|
m_direction = DIRECTION_45::NE;
|
||||||
|
else if( ratio < ( 1.0 / areaRatioThreshold ) - areaRatioEpsilon )
|
||||||
|
m_direction = DIRECTION_45::N;
|
||||||
|
else if( m_lastSegDirection != DIRECTION_45::UNDEFINED )
|
||||||
|
m_direction = m_lastSegDirection;
|
||||||
|
|
||||||
|
return m_direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void POSTURE_SOLVER::FlipPosture()
|
void POSTURE_SOLVER::FlipPosture()
|
||||||
{
|
{
|
||||||
m_initDirection = m_initDirection.Right();
|
m_direction = m_direction.Right();
|
||||||
m_forced = true;
|
m_forced = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,11 +78,14 @@ public:
|
||||||
~POSTURE_SOLVER();
|
~POSTURE_SOLVER();
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
void AddTrailPoint( const VECTOR2I& aP );
|
void AddTrailPoint( const VECTOR2I& aP );
|
||||||
void SetTollerance( int toll ) { m_tollerance = toll; }
|
|
||||||
|
void SetTolerance( int toll ) { m_tolerance = toll; }
|
||||||
|
|
||||||
void SetDefaultDirections( DIRECTION_45 aInitDirection, DIRECTION_45 aLastSegDir )
|
void SetDefaultDirections( DIRECTION_45 aInitDirection, DIRECTION_45 aLastSegDir )
|
||||||
{
|
{
|
||||||
m_initDirection = aInitDirection;
|
m_direction = aInitDirection;
|
||||||
m_lastSegDirection = aLastSegDir;
|
m_lastSegDirection = aLastSegDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,10 +95,11 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const double areaRatioThreshold = 1.5;
|
const double areaRatioThreshold = 1.5;
|
||||||
|
const double areaRatioEpsilon = 0.2;
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN m_trail;
|
SHAPE_LINE_CHAIN m_trail;
|
||||||
int m_tollerance;
|
int m_tolerance;
|
||||||
DIRECTION_45 m_initDirection;
|
DIRECTION_45 m_direction;
|
||||||
DIRECTION_45 m_lastSegDirection;
|
DIRECTION_45 m_lastSegDirection;
|
||||||
bool m_forced;
|
bool m_forced;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue