KiCad PCB EDA Suite
PNS::MOUSE_TRAIL_TRACER Class Reference

#include <pns_mouse_trail_tracer.h>

Public Member Functions

 MOUSE_TRAIL_TRACER ()
 
 ~MOUSE_TRAIL_TRACER ()
 
void Clear ()
 
void AddTrailPoint (const VECTOR2I &aP)
 
void SetTolerance (int toll)
 
void SetDefaultDirections (DIRECTION_45 aInitDirection, DIRECTION_45 aLastSegDir)
 
DIRECTION_45 GetPosture (const VECTOR2I &aP)
 
void FlipPosture ()
 
void SetMouseDisabled (bool aDisabled=true)
 Disables the mouse-trail portion of the posture solver; leaving only the manual posture switch and the previous-segment posture algorithm. More...
 
bool IsManuallyForced () const
 
VECTOR2I GetTrailLeadVector () const
 

Private Attributes

SHAPE_LINE_CHAIN m_trail
 
int m_tolerance
 
DIRECTION_45 m_direction
 
DIRECTION_45 m_lastSegDirection
 
bool m_forced
 
bool m_disableMouse
 
bool m_manuallyForced
 

Detailed Description

Definition at line 31 of file pns_mouse_trail_tracer.h.

Constructor & Destructor Documentation

◆ MOUSE_TRAIL_TRACER()

PNS::MOUSE_TRAIL_TRACER::MOUSE_TRAIL_TRACER ( )

◆ ~MOUSE_TRAIL_TRACER()

PNS::MOUSE_TRAIL_TRACER::~MOUSE_TRAIL_TRACER ( )

Definition at line 35 of file pns_mouse_trail_tracer.cpp.

35 {}

Member Function Documentation

◆ AddTrailPoint()

void PNS::MOUSE_TRAIL_TRACER::AddTrailPoint ( const VECTOR2I aP)

Definition at line 46 of file pns_mouse_trail_tracer.cpp.

47 {
48  if( m_trail.SegmentCount() == 0 )
49  {
50  m_trail.Append( aP );
51  }
52  else
53  {
54  SEG s_new( m_trail.CPoint( -1 ), aP );
55 
56  if( m_trail.SegmentCount() > 2 )
57  {
58  SEG::ecoord limit = ( static_cast<SEG::ecoord>( m_tolerance ) * m_tolerance );
59 
60  for( int i = 0; i < m_trail.SegmentCount() - 2; i++ )
61  {
62  const SEG& s_trail = m_trail.CSegment( i );
63 
64  if( s_trail.SquaredDistance( s_new ) <= limit )
65  {
66  m_trail = m_trail.Slice( 0, i );
67  break;
68  }
69  }
70  }
71 
72  m_trail.Append( aP );
73  }
74 
75  m_trail.Simplify();
76 
77  DEBUG_DECORATOR *dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
78 
79  PNS_DBG( dbg, AddLine, m_trail, CYAN, 50000, "mt-trail" );
80 }
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex=-1) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
VECTOR2I::extended_type ecoord
Definition: seg.h:43
ecoord SquaredDistance(const SEG &aSeg) const
Definition: seg.cpp:39
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
#define PNS_DBG(dbg, method,...)
Definition: color4d.h:58
int SegmentCount() const
Return the number of segments in this line chain.
Definition: seg.h:40
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:207
static ROUTER * GetInstance()
Definition: pns_router.cpp:78

References SHAPE_LINE_CHAIN::Append(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), CYAN, PNS::ROUTER_IFACE::GetDebugDecorator(), PNS::ROUTER::GetInstance(), PNS::ROUTER::GetInterface(), m_tolerance, m_trail, PNS_DBG, SHAPE_LINE_CHAIN::SegmentCount(), SHAPE_LINE_CHAIN::Simplify(), SHAPE_LINE_CHAIN::Slice(), and SEG::SquaredDistance().

Referenced by PNS::DRAGGER::Drag(), PNS::LINE_PLACER::FixRoute(), PNS::LINE_PLACER::Move(), PNS::DRAGGER::Start(), PNS::LINE_PLACER::Start(), and PNS::LINE_PLACER::UnfixRoute().

◆ Clear()

void PNS::MOUSE_TRAIL_TRACER::Clear ( )

◆ FlipPosture()

void PNS::MOUSE_TRAIL_TRACER::FlipPosture ( )

Definition at line 268 of file pns_mouse_trail_tracer.cpp.

269 {
271  m_forced = true;
272  m_manuallyForced = true;
273 }
const DIRECTION_45 Right() const
Return the direction on the right side of this (i.e.
Definition: direction45.h:238

References m_direction, m_forced, m_manuallyForced, and DIRECTION_45::Right().

Referenced by PNS::LINE_PLACER::FlipPosture().

◆ GetPosture()

DIRECTION_45 PNS::MOUSE_TRAIL_TRACER::GetPosture ( const VECTOR2I aP)

Definition at line 83 of file pns_mouse_trail_tracer.cpp.

84 {
85  // Tuning factor for how good the "fit" of the trail must be to the posture
86  const double areaRatioThreshold = 1.3;
87 
88  // Tuning factor to minimize flutter
89  const double areaRatioEpsilon = 0.25;
90 
91  // Minimum distance factor of the trail before the min area test is used to lock the solver
92  const double minAreaCutoffDistanceFactor = 6;
93 
94  // Adjusts how far away from p0 we get before whatever posture we solved is locked in
95  const int lockDistanceFactor = 25;
96 
97  // Adjusts how close to p0 we unlock the posture again if one was locked already
98  const int unlockDistanceFactor = 4;
99 
100  if( m_trail.PointCount() < 2 || m_manuallyForced )
101  {
102  // If mouse trail detection is enabled; using the last seg direction as a starting point
103  // will give the best results. Otherwise, just assume that we switch postures every
104  // segment.
107 
108  return m_direction;
109  }
110 
111  DEBUG_DECORATOR* dbg = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
112  VECTOR2I p0 = m_trail.CPoint( 0 );
113  double refLength = SEG( p0, aP ).Length();
114  SHAPE_LINE_CHAIN straight( DIRECTION_45().BuildInitialTrace( p0, aP, false, false ) );
115 
116  straight.SetClosed( true );
117  straight.Append( m_trail.Reverse() );
118  straight.Simplify();
119 
120  PNS_DBG( dbg, AddLine, straight, m_forced ? BLUE : GREEN, 100000, "mt-straight" );
121 
122  double areaS = straight.Area();
123 
124  SHAPE_LINE_CHAIN diag( DIRECTION_45().BuildInitialTrace( p0, aP, true, false ) );
125  diag.Append( m_trail.Reverse() );
126  diag.SetClosed( true );
127  diag.Simplify();
128 
129  PNS_DBG( dbg, AddLine, diag, YELLOW, 100000, "mt-diag" );
130 
131  double areaDiag = diag.Area();
132  double ratio = areaS / ( areaDiag + 1.0 );
133 
134  // heuristic to detect that the user dragged back the cursor to the beginning of the trace
135  // in this case, we cancel any forced posture and restart the trail
136  if( m_forced && refLength < unlockDistanceFactor * m_tolerance )
137  {
138  PNS_DBG( dbg, Message, "Posture: Unlocked and reset" );
139  m_forced = false;
140  VECTOR2I start = p0;
141  m_trail.Clear();
142  m_trail.Append( start );
143  }
144 
145  bool areaOk = false;
146 
147  // Check the actual trail area against the cutoff. This prevents flutter when the trail is
148  // very close to a straight line.
149  if( !m_forced && refLength > minAreaCutoffDistanceFactor * m_tolerance )
150  {
151  double areaCutoff = m_tolerance * refLength;
152  SHAPE_LINE_CHAIN trail( m_trail );
153  trail.SetClosed( true );
154 
155  if( trail.Area() > areaCutoff )
156  areaOk = true;
157 }
158 
159  DIRECTION_45 straightDirection;
160  DIRECTION_45 diagDirection;
161  DIRECTION_45 newDirection = m_direction;
162 
163  straightDirection = DIRECTION_45( straight.CSegment( 0 ) );
164  diagDirection = DIRECTION_45( diag.CSegment( 0 ) );
165 
166  if( !m_forced && areaOk && ratio > areaRatioThreshold + areaRatioEpsilon )
167  newDirection = diagDirection;
168  else if( !m_forced && areaOk && ratio < ( 1.0 / areaRatioThreshold ) - areaRatioEpsilon )
169  newDirection = straightDirection;
170  else
171  newDirection = m_direction.IsDiagonal() ? diagDirection : straightDirection;
172 
173  if( !m_disableMouse && newDirection != m_direction )
174  {
175  PNS_DBG( dbg, Message, wxString::Format( "Posture: direction update %s => %s",
176  m_direction.Format(), newDirection.Format() ) );
177  m_direction = newDirection;
178  }
179 
180  // If we have a last segment, correct the direction relative to it. For segment exit, we want
181  // to correct to the least obtuse
183  {
184  PNS_DBG( dbg, Message,
185  wxString::Format( "Posture: checking direction %s against last seg %s",
187 
188  if( straightDirection == m_lastSegDirection )
189  {
190  if( m_direction != straightDirection )
191  {
192  PNS_DBG( dbg, Message, wxString::Format( "Posture: forcing straight => %s",
193  straightDirection.Format() ) );
194  }
195 
196  m_direction = straightDirection;
197  }
198  else if( diagDirection == m_lastSegDirection )
199  {
200  if( m_direction != straightDirection )
201  {
202  PNS_DBG( dbg, Message, wxString::Format( "Posture: forcing diagonal => %s",
203  diagDirection.Format() ) );
204  }
205 
206  m_direction = diagDirection;
207  }
208  else
209  {
211  {
213  // Force a better (acute) connection
214  m_direction = m_direction.IsDiagonal() ? straightDirection : diagDirection;
215  PNS_DBG( dbg, Message, wxString::Format( "Posture: correcting half full => %s",
216  m_direction.Format() ) );
217  break;
218 
220  {
221  // Force a better connection by flipping if possible
222  DIRECTION_45 candidate = m_direction.IsDiagonal() ? straightDirection
223  : diagDirection;
224 
225  if( candidate.Angle( m_lastSegDirection ) == DIRECTION_45::ANG_RIGHT )
226  {
227  PNS_DBG( dbg, Message, wxString::Format( "Posture: correcting right => %s",
228  candidate.Format() ) );
229  m_direction = candidate;
230  }
231 
232  break;
233  }
234 
236  {
237  // Force a better connection by flipping if possible
238  DIRECTION_45 candidate = m_direction.IsDiagonal() ? straightDirection
239  : diagDirection;
240 
242  {
243  PNS_DBG( dbg, Message, wxString::Format( "Posture: correcting obtuse => %s",
244  candidate.Format() ) );
245  m_direction = candidate;
246  }
247 
248  break;
249  }
250 
251  default:
252  break;
253  }
254  }
255  }
256 
257  // If we get far away from the initial point, lock in the current solution to prevent flutter
258  if( !m_forced && refLength > lockDistanceFactor * m_tolerance )
259  {
260  PNS_DBG( dbg, Message, "Posture: solution locked" );
261  m_forced = true;
262  }
263 
264  return m_direction;
265 }
int Length() const
Return the length (this).
Definition: seg.h:350
const std::string Format() const
Format the direction in a human readable word.
Definition: direction45.h:117
const DIRECTION_45 Right() const
Return the direction on the right side of this (i.e.
Definition: direction45.h:238
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
Definition: direction45.h:169
Definition: color4d.h:67
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:36
Definition: color4d.h:57
#define PNS_DBG(dbg, method,...)
bool IsDiagonal() const
Returns true if the direction is diagonal (e.g.
Definition: direction45.h:201
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Definition: seg.h:40
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
Definition: color4d.h:56
Represent a polyline (an zero-thickness chain of connected line segments).
void Clear()
Remove all points from the line chain.
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:207
static ROUTER * GetInstance()
Definition: pns_router.cpp:78

References DIRECTION_45::ANG_ACUTE, DIRECTION_45::ANG_HALF_FULL, DIRECTION_45::ANG_OBTUSE, DIRECTION_45::ANG_RIGHT, DIRECTION_45::Angle(), SHAPE_LINE_CHAIN::Append(), SHAPE_LINE_CHAIN::Area(), BLUE, SHAPE_LINE_CHAIN::Clear(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), DIRECTION_45::Format(), Format(), PNS::ROUTER_IFACE::GetDebugDecorator(), PNS::ROUTER::GetInstance(), PNS::ROUTER::GetInterface(), GREEN, DIRECTION_45::IsDiagonal(), SEG::Length(), m_direction, m_disableMouse, m_forced, m_lastSegDirection, m_manuallyForced, m_tolerance, m_trail, PNS_DBG, SHAPE_LINE_CHAIN::PointCount(), SHAPE_LINE_CHAIN::Reverse(), DIRECTION_45::Right(), SHAPE_LINE_CHAIN::SetClosed(), SHAPE_LINE_CHAIN::Simplify(), DIRECTION_45::UNDEFINED, and YELLOW.

Referenced by PNS::LINE_PLACER::buildInitialLine().

◆ GetTrailLeadVector()

VECTOR2I PNS::MOUSE_TRAIL_TRACER::GetTrailLeadVector ( ) const

Definition at line 276 of file pns_mouse_trail_tracer.cpp.

277 {
278  if( m_trail.PointCount() < 2 )
279  {
280  return VECTOR2I(0, 0);
281  }
282  else
283  {
284  return m_trail.CPoint( -1 ) - m_trail.CPoint( 0 );
285  }
286 }
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.

References SHAPE_LINE_CHAIN::CPoint(), m_trail, and SHAPE_LINE_CHAIN::PointCount().

Referenced by PNS::DRAGGER::propagateViaForces().

◆ IsManuallyForced()

bool PNS::MOUSE_TRAIL_TRACER::IsManuallyForced ( ) const
inline

◆ SetDefaultDirections()

void PNS::MOUSE_TRAIL_TRACER::SetDefaultDirections ( DIRECTION_45  aInitDirection,
DIRECTION_45  aLastSegDir 
)
inline

Definition at line 43 of file pns_mouse_trail_tracer.h.

44  {
45  m_direction = aInitDirection;
46  m_lastSegDirection = aLastSegDir;
47  }

References m_direction, and m_lastSegDirection.

Referenced by PNS::LINE_PLACER::FixRoute(), PNS::LINE_PLACER::Start(), and PNS::LINE_PLACER::UnfixRoute().

◆ SetMouseDisabled()

void PNS::MOUSE_TRAIL_TRACER::SetMouseDisabled ( bool  aDisabled = true)
inline

Disables the mouse-trail portion of the posture solver; leaving only the manual posture switch and the previous-segment posture algorithm.

Definition at line 57 of file pns_mouse_trail_tracer.h.

57 { m_disableMouse = aDisabled; }

References m_disableMouse.

Referenced by PNS::LINE_PLACER::Start().

◆ SetTolerance()

void PNS::MOUSE_TRAIL_TRACER::SetTolerance ( int  toll)
inline

Definition at line 41 of file pns_mouse_trail_tracer.h.

References m_tolerance.

Referenced by PNS::LINE_PLACER::FixRoute(), and PNS::LINE_PLACER::Start().

Member Data Documentation

◆ m_direction

DIRECTION_45 PNS::MOUSE_TRAIL_TRACER::m_direction
private

Definition at line 65 of file pns_mouse_trail_tracer.h.

Referenced by FlipPosture(), GetPosture(), and SetDefaultDirections().

◆ m_disableMouse

bool PNS::MOUSE_TRAIL_TRACER::m_disableMouse
private

Definition at line 68 of file pns_mouse_trail_tracer.h.

Referenced by GetPosture(), MOUSE_TRAIL_TRACER(), and SetMouseDisabled().

◆ m_forced

bool PNS::MOUSE_TRAIL_TRACER::m_forced
private

Definition at line 67 of file pns_mouse_trail_tracer.h.

Referenced by Clear(), FlipPosture(), and GetPosture().

◆ m_lastSegDirection

DIRECTION_45 PNS::MOUSE_TRAIL_TRACER::m_lastSegDirection
private

Definition at line 66 of file pns_mouse_trail_tracer.h.

Referenced by GetPosture(), and SetDefaultDirections().

◆ m_manuallyForced

bool PNS::MOUSE_TRAIL_TRACER::m_manuallyForced
private

Definition at line 69 of file pns_mouse_trail_tracer.h.

Referenced by Clear(), FlipPosture(), GetPosture(), and IsManuallyForced().

◆ m_tolerance

int PNS::MOUSE_TRAIL_TRACER::m_tolerance
private

◆ m_trail

SHAPE_LINE_CHAIN PNS::MOUSE_TRAIL_TRACER::m_trail
private

Definition at line 63 of file pns_mouse_trail_tracer.h.

Referenced by AddTrailPoint(), Clear(), GetPosture(), and GetTrailLeadVector().


The documentation for this class was generated from the following files: