From 0234b7278aac977838d91364560e3d3eda28a4e2 Mon Sep 17 00:00:00 2001 From: Jon Evans Date: Wed, 6 Jan 2021 21:47:06 -0500 Subject: [PATCH] PNS: Make DIRECTION_45 North be up everywhere Fixes https://gitlab.com/kicad/code/kicad/-/issues/6935 --- libs/kimath/include/geometry/direction45.h | 16 ++++--- pcbnew/router/pns_line_placer.cpp | 50 +++++++++++++--------- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/libs/kimath/include/geometry/direction45.h b/libs/kimath/include/geometry/direction45.h index 6b1627c7d4..b3ea9ab9ea 100644 --- a/libs/kimath/include/geometry/direction45.h +++ b/libs/kimath/include/geometry/direction45.h @@ -39,9 +39,10 @@ class DIRECTION_45 public: /** - * Enum Directions * 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. + * 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 { @@ -75,11 +76,13 @@ public: /** * 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 ) : m_90deg( a90 ) { + VECTOR2I vec( aVec ); + vec.y = -vec.y; construct_( aVec ); } @@ -90,8 +93,9 @@ public: DIRECTION_45( const SEG& aSeg, bool a90 = false ) : m_90deg( a90 ) { - - construct_( aSeg.B - aSeg.A ); + VECTOR2I vec( aSeg.B - aSeg.A ); + vec.y = -vec.y; + construct_( vec ); } /** @@ -101,7 +105,9 @@ public: DIRECTION_45( const SHAPE_ARC& aArc, bool a90 = false ) : m_90deg( a90 ) { - construct_( aArc.GetP1() - aArc.GetP0() ); + VECTOR2I vec( aArc.GetP1() - aArc.GetP0() ); + vec.y = -vec.y; + construct_( vec ); } /** diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index 31ce47d8e9..21739e82ec 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -897,17 +897,10 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem ) // direction so that the posture solver is not biased. SEG seg = static_cast( 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 ) - lastSegDir = DIRECTION_45( seg ); - else if( aP == seg.B ) lastSegDir = DIRECTION_45( seg.Reversed() ); + else if( aP == seg.B ) + lastSegDir = DIRECTION_45( seg ); } else if( aStartItem && aStartItem->Kind() == ITEM::SOLID_T && static_cast( aStartItem )->Parent()->Type() == PCB_PAD_T ) @@ -917,6 +910,8 @@ bool LINE_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem ) initialDir = DIRECTION_45( static_cast( int( angle ) ) ); } + wxLogTrace( "PNS", "Posture: init %s, last seg %s", initialDir.Format(), lastSegDir.Format() ); + m_postureSolver.Clear(); m_postureSolver.AddTrailPoint( aP ); 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 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 ); 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 if( m_forced && refLength < unlockDistanceFactor * m_tolerance ) { + wxLogTrace( "PNS", "Posture: Unlocked and reset" ); m_forced = false; VECTOR2I start = p0; m_trail.Clear(); @@ -1613,15 +1607,8 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP ) 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 ); + straightDirection = DIRECTION_45( straight.CSegment( 0 ) ); + diagDirection = DIRECTION_45( diag.CSegment( 0 ) ); if( !m_forced && areaOk && ratio > areaRatioThreshold + areaRatioEpsilon ) newDirection = diagDirection; @@ -1630,6 +1617,12 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP ) else 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; // 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( m_direction != straightDirection ) + { + wxLogTrace( "PNS", "Posture: forcing straight => %s", straightDirection.Format() ); + } + m_direction = straightDirection; } else if( diagDirection == m_lastSegDirection ) { + if( m_direction != straightDirection ) + { + wxLogTrace( "PNS", "Posture: forcing diagonal => %s", diagDirection.Format() ); + } + m_direction = diagDirection; } else @@ -1651,6 +1654,7 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP ) case DIRECTION_45::ANG_HALF_FULL: // Force a better (acute) connection m_direction = m_direction.IsDiagonal() ? straightDirection : diagDirection; + wxLogTrace( "PNS", "Posture: correcting half full => %s", m_direction.Format() ); break; case DIRECTION_45::ANG_ACUTE: @@ -1660,7 +1664,10 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP ) : diagDirection; if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_RIGHT ) + { + wxLogTrace( "PNS", "Posture: correcting right => %s", candidate.Format() ); m_direction = candidate; + } break; } @@ -1672,7 +1679,10 @@ DIRECTION_45 POSTURE_SOLVER::GetPosture( const VECTOR2I& aP ) : diagDirection; if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_OBTUSE ) + { + wxLogTrace( "PNS", "Posture: correcting obtuse => %s", candidate.Format() ); m_direction = candidate; + } break; }