PNS: Improved auto-posture when starting from a segment
The previous auto-posture algorithm worked great for pads but not so great when starting routing from a segment. Now we can optimize the posture based on the starting segment if one exists, to maximize the "obtuseness" of the posture.
This commit is contained in:
parent
f2c5856124
commit
96d49d1473
|
@ -982,10 +982,24 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
|
||||||
|
|
||||||
initPlacement();
|
initPlacement();
|
||||||
|
|
||||||
|
DIRECTION_45 lastSegDir = DIRECTION_45::UNDEFINED;
|
||||||
|
|
||||||
|
if( aStartItem && aStartItem->Kind() == ITEM::SEGMENT_T )
|
||||||
|
{
|
||||||
|
// NOTE: have to flip this over at the moment because DIRECTION_45(SEG) assumes +y is
|
||||||
|
// North but a SEG will have -y be North in KiCad world coordinate system.
|
||||||
|
// This should probably be fixed in DIRECTION_45 but it's used in a lot of PNS code
|
||||||
|
// that would need to be checked carefully for such a change...
|
||||||
|
SEG seg = static_cast<SEGMENT*>( aStartItem )->Seg();
|
||||||
|
seg.A.y = -seg.A.y;
|
||||||
|
seg.B.y = -seg.B.y;
|
||||||
|
lastSegDir = DIRECTION_45( seg );
|
||||||
|
}
|
||||||
|
|
||||||
m_postureSolver.Clear();
|
m_postureSolver.Clear();
|
||||||
m_postureSolver.AddTrailPoint( aP );
|
m_postureSolver.AddTrailPoint( aP );
|
||||||
m_postureSolver.SetTolerance( m_head.Width() );
|
m_postureSolver.SetTolerance( m_head.Width() );
|
||||||
m_postureSolver.SetDefaultDirections( m_initial_direction, DIRECTION_45::UNDEFINED );
|
m_postureSolver.SetDefaultDirections( m_initial_direction, lastSegDir );
|
||||||
m_postureSolver.SetDisabled( !Settings().GetAutoPosture() );
|
m_postureSolver.SetDisabled( !Settings().GetAutoPosture() );
|
||||||
|
|
||||||
NODE *n;
|
NODE *n;
|
||||||
|
@ -1139,7 +1153,11 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
|
||||||
|
|
||||||
VECTOR2I p_pre_last = l.CPoint( -1 );
|
VECTOR2I p_pre_last = l.CPoint( -1 );
|
||||||
const VECTOR2I p_last = l.CPoint( -1 );
|
const VECTOR2I p_last = l.CPoint( -1 );
|
||||||
DIRECTION_45 d_last( l.CSegment( -1 ) );
|
|
||||||
|
SEG lastDirSeg = l.CSegment( -1 );
|
||||||
|
lastDirSeg.A.y = -lastDirSeg.A.y;
|
||||||
|
lastDirSeg.B.y = -lastDirSeg.B.y;
|
||||||
|
DIRECTION_45 d_last( lastDirSeg );
|
||||||
|
|
||||||
if( l.PointCount() > 2 )
|
if( l.PointCount() > 2 )
|
||||||
p_pre_last = l.CPoint( -2 );
|
p_pre_last = l.CPoint( -2 );
|
||||||
|
@ -1219,8 +1237,7 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
|
||||||
m_postureSolver.Clear();
|
m_postureSolver.Clear();
|
||||||
m_postureSolver.SetTolerance( 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,
|
m_postureSolver.SetDefaultDirections( m_initial_direction, d_last );
|
||||||
fixAll ? d_last.Right() : d_last );
|
|
||||||
|
|
||||||
m_placementCorrect = true;
|
m_placementCorrect = true;
|
||||||
}
|
}
|
||||||
|
@ -1525,9 +1542,9 @@ int FIXED_TAIL::StageCount() const
|
||||||
|
|
||||||
POSTURE_SOLVER::POSTURE_SOLVER()
|
POSTURE_SOLVER::POSTURE_SOLVER()
|
||||||
{
|
{
|
||||||
m_forced = false;
|
|
||||||
m_tolerance = 0;
|
m_tolerance = 0;
|
||||||
m_disabled = false;
|
m_disabled = false;
|
||||||
|
Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1536,7 +1553,8 @@ POSTURE_SOLVER::~POSTURE_SOLVER() {}
|
||||||
|
|
||||||
void POSTURE_SOLVER::Clear()
|
void POSTURE_SOLVER::Clear()
|
||||||
{
|
{
|
||||||
m_forced = false;
|
m_forced = false;
|
||||||
|
m_manuallyForced = false;
|
||||||
m_trail.Clear();
|
m_trail.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1591,7 +1609,12 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
|
||||||
const int unlockDistanceFactor = 4;
|
const int unlockDistanceFactor = 4;
|
||||||
|
|
||||||
if( m_disabled || m_trail.PointCount() < 2 )
|
if( m_disabled || m_trail.PointCount() < 2 )
|
||||||
|
{
|
||||||
|
if( m_lastSegDirection != DIRECTION_45::UNDEFINED )
|
||||||
|
m_direction = m_lastSegDirection;
|
||||||
|
|
||||||
return m_direction;
|
return m_direction;
|
||||||
|
}
|
||||||
|
|
||||||
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
|
auto dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
|
||||||
|
|
||||||
|
@ -1640,19 +1663,84 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
|
||||||
areaOk = false;
|
areaOk = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DIRECTION_45 straightDirection;
|
||||||
|
DIRECTION_45 diagDirection;
|
||||||
|
DIRECTION_45 newDirection = m_direction;
|
||||||
|
|
||||||
|
SEG seg = straight.CSegment( 0 );
|
||||||
|
seg.A.y = -seg.A.y;
|
||||||
|
seg.B.y = -seg.B.y;
|
||||||
|
straightDirection = DIRECTION_45( seg );
|
||||||
|
|
||||||
|
seg = diag.CSegment( 0 );
|
||||||
|
seg.A.y = -seg.A.y;
|
||||||
|
seg.B.y = -seg.B.y;
|
||||||
|
diagDirection = DIRECTION_45( seg );
|
||||||
|
|
||||||
|
if( !m_forced && areaOk && ratio > areaRatioThreshold + areaRatioEpsilon )
|
||||||
|
newDirection = diagDirection;
|
||||||
|
else if( !m_forced && areaOk && ratio < ( 1.0 / areaRatioThreshold ) - areaRatioEpsilon )
|
||||||
|
newDirection = straightDirection;
|
||||||
|
else
|
||||||
|
newDirection = m_direction.IsDiagonal() ? diagDirection : straightDirection;
|
||||||
|
|
||||||
|
m_direction = newDirection;
|
||||||
|
|
||||||
|
// If we have a last segment, correct the direction relative to it. For segment exit, we want
|
||||||
|
// to correct to the least obtuse
|
||||||
|
if( !m_manuallyForced && m_lastSegDirection != DIRECTION_45::UNDEFINED )
|
||||||
|
{
|
||||||
|
if( straightDirection == m_lastSegDirection )
|
||||||
|
{
|
||||||
|
m_direction = straightDirection;
|
||||||
|
}
|
||||||
|
else if( diagDirection == m_lastSegDirection )
|
||||||
|
{
|
||||||
|
m_direction = diagDirection;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch( m_direction.Angle( m_lastSegDirection ) )
|
||||||
|
{
|
||||||
|
case DIRECTION_45::ANG_HALF_FULL:
|
||||||
|
// Force a better (acute) connection
|
||||||
|
m_direction = m_direction.IsDiagonal() ? straightDirection : diagDirection;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DIRECTION_45::ANG_ACUTE:
|
||||||
|
{
|
||||||
|
// Force a better connection by flipping if possible
|
||||||
|
DIRECTION_45 candidate = m_direction.IsDiagonal() ? straightDirection
|
||||||
|
: diagDirection;
|
||||||
|
|
||||||
|
if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_RIGHT )
|
||||||
|
m_direction = candidate;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DIRECTION_45::ANG_RIGHT:
|
||||||
|
{
|
||||||
|
// Force a better connection by flipping if possible
|
||||||
|
DIRECTION_45 candidate = m_direction.IsDiagonal() ? straightDirection
|
||||||
|
: diagDirection;
|
||||||
|
|
||||||
|
if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_OBTUSE )
|
||||||
|
m_direction = candidate;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If we get far away from the initial point, lock in the current solution to prevent flutter
|
// If we get far away from the initial point, lock in the current solution to prevent flutter
|
||||||
if( !m_forced && refLength > lockDistanceFactor * m_tolerance )
|
if( !m_forced && refLength > lockDistanceFactor * m_tolerance )
|
||||||
m_forced = true;
|
m_forced = true;
|
||||||
|
|
||||||
if( m_forced )
|
|
||||||
return m_direction;
|
|
||||||
else if( areaOk && ratio > areaRatioThreshold + areaRatioEpsilon )
|
|
||||||
m_direction = DIRECTION_45::NE;
|
|
||||||
else if( areaOk && ratio < ( 1.0 / areaRatioThreshold ) - areaRatioEpsilon )
|
|
||||||
m_direction = DIRECTION_45::N;
|
|
||||||
else if( m_lastSegDirection != DIRECTION_45::UNDEFINED )
|
|
||||||
m_direction = m_lastSegDirection;
|
|
||||||
|
|
||||||
return m_direction;
|
return m_direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1661,6 +1749,7 @@ void POSTURE_SOLVER::FlipPosture()
|
||||||
{
|
{
|
||||||
m_direction = m_direction.Right();
|
m_direction = m_direction.Right();
|
||||||
m_forced = true;
|
m_forced = true;
|
||||||
|
m_manuallyForced = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ private:
|
||||||
DIRECTION_45 m_lastSegDirection;
|
DIRECTION_45 m_lastSegDirection;
|
||||||
bool m_forced;
|
bool m_forced;
|
||||||
bool m_disabled;
|
bool m_disabled;
|
||||||
|
bool m_manuallyForced;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue