PNS: Make DIRECTION_45 North be up everywhere

Fixes https://gitlab.com/kicad/code/kicad/-/issues/6935
This commit is contained in:
Jon Evans 2021-01-06 21:47:06 -05:00
parent eef16fe717
commit 0234b7278a
2 changed files with 41 additions and 25 deletions

View File

@ -39,9 +39,10 @@ class DIRECTION_45
public: public:
/** /**
* Enum Directions
* Represents available directions - there are 8 of them, as on a rectilinear map (north = up) + * Represents available directions - there are 8 of them, as on a rectilinear map (north = up) +
* an extra undefined direction, reserved for traces that don't respect 45-degree routing regime. * an extra undefined direction, reserved for traces that don't respect 45-degree routing regime.
* NOTE: North represents "up" to the user looking at the application, which is the negative-y
* direction in the world coordinate space!
*/ */
enum Directions : int enum Directions : int
{ {
@ -75,11 +76,13 @@ public:
/** /**
* Constructor * Constructor
* @param aVec vector, whose direction will be translated into a DIRECTION_45. * @param aVec vector in world space, whose direction will be translated into a DIRECTION_45.
*/ */
DIRECTION_45( const VECTOR2I &aVec, bool a90 = false ) : DIRECTION_45( const VECTOR2I &aVec, bool a90 = false ) :
m_90deg( a90 ) m_90deg( a90 )
{ {
VECTOR2I vec( aVec );
vec.y = -vec.y;
construct_( aVec ); construct_( aVec );
} }
@ -90,8 +93,9 @@ public:
DIRECTION_45( const SEG& aSeg, bool a90 = false ) : DIRECTION_45( const SEG& aSeg, bool a90 = false ) :
m_90deg( a90 ) m_90deg( a90 )
{ {
VECTOR2I vec( aSeg.B - aSeg.A );
construct_( aSeg.B - aSeg.A ); vec.y = -vec.y;
construct_( vec );
} }
/** /**
@ -101,7 +105,9 @@ public:
DIRECTION_45( const SHAPE_ARC& aArc, bool a90 = false ) : DIRECTION_45( const SHAPE_ARC& aArc, bool a90 = false ) :
m_90deg( a90 ) m_90deg( a90 )
{ {
construct_( aArc.GetP1() - aArc.GetP0() ); VECTOR2I vec( aArc.GetP1() - aArc.GetP0() );
vec.y = -vec.y;
construct_( vec );
} }
/** /**

View File

@ -897,17 +897,10 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
// direction so that the posture solver is not biased. // direction so that the posture solver is not biased.
SEG seg = static_cast<SEGMENT*>( aStartItem )->Seg(); SEG seg = static_cast<SEGMENT*>( aStartItem )->Seg();
// 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.A.y = -seg.A.y;
seg.B.y = -seg.B.y;
if( aP == seg.A ) if( aP == seg.A )
lastSegDir = DIRECTION_45( seg );
else if( aP == seg.B )
lastSegDir = DIRECTION_45( seg.Reversed() ); lastSegDir = DIRECTION_45( seg.Reversed() );
else if( aP == seg.B )
lastSegDir = DIRECTION_45( seg );
} }
else if( aStartItem && aStartItem->Kind() == ITEM::SOLID_T && else if( aStartItem && aStartItem->Kind() == ITEM::SOLID_T &&
static_cast<SOLID*>( aStartItem )->Parent()->Type() == PCB_PAD_T ) static_cast<SOLID*>( aStartItem )->Parent()->Type() == PCB_PAD_T )
@ -917,6 +910,8 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
initialDir = DIRECTION_45( static_cast<DIRECTION_45::Directions>( int( angle ) ) ); initialDir = DIRECTION_45( static_cast<DIRECTION_45::Directions>( int( angle ) ) );
} }
wxLogTrace( "PNS", "Posture: init %s, last seg %s", initialDir.Format(), lastSegDir.Format() );
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() );
@ -1100,8 +1095,6 @@ bool LINE_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinis
// TODO: lastDirSeg will be calculated incorrectly if we end on an arc // TODO: lastDirSeg will be calculated incorrectly if we end on an arc
SEG lastDirSeg = ( !fixAll && l.SegmentCount() > 1 ) ? l.CSegment( -2 ) : l.CSegment( -1 ); SEG lastDirSeg = ( !fixAll && l.SegmentCount() > 1 ) ? l.CSegment( -2 ) : l.CSegment( -1 );
lastDirSeg.A.y = -lastDirSeg.A.y;
lastDirSeg.B.y = -lastDirSeg.B.y;
DIRECTION_45 d_last( lastDirSeg ); DIRECTION_45 d_last( lastDirSeg );
int lastV; int lastV;
@ -1589,6 +1582,7 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
// in this case, we cancel any forced posture and restart the trail // in this case, we cancel any forced posture and restart the trail
if( m_forced && refLength < unlockDistanceFactor * m_tolerance ) if( m_forced && refLength < unlockDistanceFactor * m_tolerance )
{ {
wxLogTrace( "PNS", "Posture: Unlocked and reset" );
m_forced = false; m_forced = false;
VECTOR2I start = p0; VECTOR2I start = p0;
m_trail.Clear(); m_trail.Clear();
@ -1613,15 +1607,8 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
DIRECTION_45 diagDirection; DIRECTION_45 diagDirection;
DIRECTION_45 newDirection = m_direction; DIRECTION_45 newDirection = m_direction;
SEG seg = straight.CSegment( 0 ); straightDirection = DIRECTION_45( straight.CSegment( 0 ) );
seg.A.y = -seg.A.y; diagDirection = DIRECTION_45( diag.CSegment( 0 ) );
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 ) if( !m_forced && areaOk && ratio > areaRatioThreshold + areaRatioEpsilon )
newDirection = diagDirection; newDirection = diagDirection;
@ -1630,6 +1617,12 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
else else
newDirection = m_direction.IsDiagonal() ? diagDirection : straightDirection; newDirection = m_direction.IsDiagonal() ? diagDirection : straightDirection;
if( newDirection != m_direction )
{
wxLogTrace( "PNS", "Posture: direction update %s => %s", m_direction.Format(),
newDirection.Format() );
}
m_direction = newDirection; m_direction = newDirection;
// If we have a last segment, correct the direction relative to it. For segment exit, we want // If we have a last segment, correct the direction relative to it. For segment exit, we want
@ -1638,10 +1631,20 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
{ {
if( straightDirection == m_lastSegDirection ) if( straightDirection == m_lastSegDirection )
{ {
if( m_direction != straightDirection )
{
wxLogTrace( "PNS", "Posture: forcing straight => %s", straightDirection.Format() );
}
m_direction = straightDirection; m_direction = straightDirection;
} }
else if( diagDirection == m_lastSegDirection ) else if( diagDirection == m_lastSegDirection )
{ {
if( m_direction != straightDirection )
{
wxLogTrace( "PNS", "Posture: forcing diagonal => %s", diagDirection.Format() );
}
m_direction = diagDirection; m_direction = diagDirection;
} }
else else
@ -1651,6 +1654,7 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
case DIRECTION_45::ANG_HALF_FULL: case DIRECTION_45::ANG_HALF_FULL:
// Force a better (acute) connection // Force a better (acute) connection
m_direction = m_direction.IsDiagonal() ? straightDirection : diagDirection; m_direction = m_direction.IsDiagonal() ? straightDirection : diagDirection;
wxLogTrace( "PNS", "Posture: correcting half full => %s", m_direction.Format() );
break; break;
case DIRECTION_45::ANG_ACUTE: case DIRECTION_45::ANG_ACUTE:
@ -1660,7 +1664,10 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
: diagDirection; : diagDirection;
if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_RIGHT ) if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_RIGHT )
{
wxLogTrace( "PNS", "Posture: correcting right => %s", candidate.Format() );
m_direction = candidate; m_direction = candidate;
}
break; break;
} }
@ -1672,7 +1679,10 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP )
: diagDirection; : diagDirection;
if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_OBTUSE ) if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_OBTUSE )
{
wxLogTrace( "PNS", "Posture: correcting obtuse => %s", candidate.Format() );
m_direction = candidate; m_direction = candidate;
}
break; break;
} }