KiCad PCB EDA Suite
pns_dragger.cpp
Go to the documentation of this file.
1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2014 CERN
5  * Copyright (C) 2016-2019 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "pns_arc.h"
23 
24 #include "pns_dragger.h"
25 #include "pns_shove.h"
26 #include "pns_router.h"
27 #include "pns_debug_decorator.h"
28 #include "pns_walkaround.h"
29 
30 namespace PNS {
31 
32 DRAGGER::DRAGGER( ROUTER* aRouter ) :
33  DRAG_ALGO( aRouter ),
34  m_initialVia( {} ),
35  m_draggedVia( {} )
36 {
37  m_world = NULL;
38  m_lastNode = NULL;
39  m_mode = DM_SEGMENT;
40  m_draggedSegmentIndex = 0;
41  m_dragStatus = false;
42  m_currentMode = RM_MarkObstacles;
43  m_freeAngleMode = false;
44 }
45 
46 
48 {
49 }
50 
51 
52 bool DRAGGER::propagateViaForces( NODE* node, std::set<VIA*>& vias )
53 {
54  VIA* via = *vias.begin();
55 
56  VECTOR2I force;
58 
59  bool solidsOnly = false;// ( m_currentMode != RM_Walkaround );
60 
61  if( via->PushoutForce( node, lead, force, solidsOnly, 40 ) )
62  {
63  via->SetPos( via->Pos() + force );
64  return true;
65  }
66 
67  return false;
68 }
69 
70 
72 {
73  int w2 = aSeg->Width() / 2;
74 
75  auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
76  auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
77 
78  VECTOR2I psnap;
79 
80  if( distA <= w2 )
81  {
82  psnap = aSeg->Seg().A;
83  }
84  else if( distB <= w2 )
85  {
86  psnap = aSeg->Seg().B;
87  }
88  else
89  {
90  return nullptr;
91  }
92 
93  JOINT *jt = m_world->FindJoint( psnap, aSeg );
94 
95  if ( !jt )
96  {
97  return nullptr;
98  }
99 
100  for( auto lnk : jt->LinkList() )
101  {
102  if( lnk.item->IsVirtual() && lnk.item->OfKind( ITEM::VIA_T ))
103  {
104  return static_cast<VVIA*>( lnk.item );
105  }
106  }
107 
108  return nullptr;
109 }
110 
111 
113 {
114  int w2 = aSeg->Width() / 2;
115 
118 
119  if( m_shove )
120  {
121  m_shove->SetInitialLine( m_draggedLine );
122  }
123 
124  auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
125  auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
126 
127  if( distA <= w2 )
128  {
129  m_mode = DM_CORNER;
130  }
131  else if( distB <= w2 )
132  {
134  m_mode = DM_CORNER;
135  }
136  else if( m_freeAngleMode )
137  {
138  if( distB < distA &&
140  ( m_draggedLine.CLine().CShapes()[ m_draggedSegmentIndex + 1 ] < 0 ) )
141  {
143  }
144 
145  m_mode = DM_CORNER;
146  }
147  else
148  {
149  m_mode = DM_SEGMENT;
150  }
151 
152  return true;
153 }
154 
155 
156 bool DRAGGER::startDragArc( const VECTOR2D& aP, ARC* aArc )
157 {
159  m_shove->SetInitialLine( m_draggedLine );
160  m_mode = DM_ARC;
161 
162  return true;
163 }
164 
165 
167 {
168  m_initialVia = aVia->MakeHandle();
170 
171  m_mode = DM_VIA;
172 
173  return true;
174 }
175 
177 {
178  ITEM_SET rv;
179 
180  JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
181 
182  if( !jt )
183  return rv;
184 
185  for( ITEM* item : jt->LinkList() )
186  {
187  if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
188  {
189  int segIndex;
190  LINKED_ITEM* seg = ( LINKED_ITEM*) item;
191  LINE l = aNode->AssembleLine( seg, &segIndex );
192 
193  if( segIndex != 0 )
194  l.Reverse();
195 
196  rv.Add( l );
197  }
198  else if( item->OfKind( ITEM::VIA_T ) )
199  {
200  rv.Add( item );
201  }
202  }
203 
204  return rv;
205 }
206 
207 bool DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
208 {
209  if( aPrimitives.Empty() )
210  return false;
211 
212  ITEM* startItem = aPrimitives[0];
213 
214  m_lastNode = NULL;
218  m_lastValidPoint = aP;
219 
222 
224  {
225  m_shove = std::make_unique<SHOVE>( m_world, Router() );
226  m_shove->SetLogger( Logger() );
227  m_shove->SetDebugDecorator( Dbg() );
228  }
229 
230  startItem->Unmark( MK_LOCKED );
231 
232  PNS_DBG( Dbg(), Message, wxString::Format( "StartDragging: item %p [kind %d]", startItem, (int) startItem->Kind() ) );
233 
234  switch( startItem->Kind() )
235  {
236  case ITEM::SEGMENT_T:
237  {
238  SEGMENT* seg = static_cast<SEGMENT*>( startItem );
239  VVIA* vvia = checkVirtualVia( aP, seg );
240 
241  if( vvia )
242  {
243  return startDragVia( vvia );
244  }
245  else
246  {
247  return startDragSegment( aP, seg );
248  }
249  }
250  case ITEM::VIA_T:
251  return startDragVia( static_cast<VIA*>( startItem ) );
252 
253  case ITEM::ARC_T:
254  return startDragArc( aP, static_cast<ARC*>( startItem ) );
255 
256  default:
257  return false;
258  }
259 }
260 
261 
262 void DRAGGER::SetMode( int aMode )
263 {
264  m_mode = aMode;
265 }
266 
267 
269 {
270  // fixme: rewrite using shared_ptr...
271  if( m_lastNode )
272  {
273  delete m_lastNode;
274  m_lastNode = nullptr;
275  }
276 
278 
279  switch( m_mode )
280  {
281  case DM_SEGMENT:
282  case DM_CORNER:
283  {
284  //TODO: Make threshold configurable
285  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
286  LINE origLine( m_draggedLine );
287  LINE dragged( m_draggedLine );
288  dragged.SetSnapThreshhold( thresh );
289  dragged.ClearLinks();
290 
291  if( m_mode == DM_SEGMENT )
292  dragged.DragSegment( aP, m_draggedSegmentIndex );
293  else
295 
296  m_lastNode->Remove( origLine );
297  m_lastNode->Add( dragged );
298 
300  m_draggedItems.Add( dragged );
301 
302  break;
303  }
304 
305  case DM_VIA: // fixme...
306  {
308 
309  break;
310  }
311  }
312 
313  if( Settings().AllowDRCViolations() )
314  m_dragStatus = true;
315  else
317 
318  return true;
319 }
320 
321 
322 bool DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
323 {
325 
326  ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
327 
328  if( fanout.Empty() )
329  {
330  return true;
331  }
332 
333  for( ITEM* item : fanout.Items() )
334  {
335  if( const LINE* l = dyn_cast<const LINE*>( item ) )
336  {
337  LINE origLine( *l );
338  LINE draggedLine( *l );
339 
340  draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
341  draggedLine.ClearLinks();
342 
343  m_draggedItems.Add( draggedLine );
344 
345  m_lastNode->Remove( origLine );
346  m_lastNode->Add( draggedLine );
347  }
348  else if ( VIA *via = dyn_cast<VIA*>( item ) )
349  {
350  auto nvia = Clone( *via );
351 
352  nvia->SetPos( aP );
353  m_draggedItems.Add( nvia.get() );
354 
355  m_lastNode->Remove( via );
356  m_lastNode->Add( std::move( nvia ) );
357  }
358  }
359 
360  return true;
361 }
362 
363 
364 bool DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
365 {
367 
368  ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
369 
370  if( fanout.Empty() )
371  {
372  return true;
373  }
374 
375  bool viaPropOk = false;
376  VECTOR2I viaTargetPos;
377 
378  for( ITEM* item : fanout.Items() )
379  {
380  if ( VIA *via = dyn_cast<VIA*>( item ) )
381  {
382  auto draggedVia = Clone( *via );
383 
384  draggedVia->SetPos( aP );
385  m_draggedItems.Add( draggedVia.get() );
386 
387  std::set<VIA*> vias;
388 
389  vias.insert( draggedVia.get() );
390 
391  bool ok = propagateViaForces( m_lastNode, vias );
392 
393  if( ok )
394  {
395  viaTargetPos = draggedVia->Pos();
396  viaPropOk = true;
397  m_lastNode->Remove( via );
398  m_lastNode->Add( std::move(draggedVia) );
399  }
400  }
401  }
402 
403  if( !viaPropOk ) // can't force-propagate the via? bummer...
404  return false;
405 
406  for( ITEM* item : fanout.Items() )
407  {
408  if( const LINE* l = dyn_cast<const LINE*>( item ) )
409  {
410  LINE origLine( *l );
411  LINE draggedLine( *l );
412  LINE walkLine( *l );
413 
414  draggedLine.DragCorner( viaTargetPos, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
415  draggedLine.ClearLinks();
416 
417  if ( m_world->CheckColliding( &draggedLine ) )
418  {
419  bool ok = tryWalkaround( m_lastNode, draggedLine, walkLine );
420 
421  if( !ok )
422  return false;
423 
424  m_lastNode->Remove( origLine );
425  optimizeAndUpdateDraggedLine( walkLine, origLine, aP );
426  }
427  else
428  {
429  m_draggedItems.Add( draggedLine );
430 
431  m_lastNode->Remove( origLine );
432  m_lastNode->Add( draggedLine );
433  }
434  }
435  }
436 
437  return true;
438 }
439 
440 
441 void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, const VECTOR2I& aP )
442 {
443  VECTOR2D lockV;
444  aDragged.ClearLinks();
445  aDragged.Unmark();
446 
447  lockV = aDragged.CLine().NearestPoint( aP );
448 
449  OPTIMIZER optimizer( m_lastNode );
450 
452 
453  if( Settings().SmoothDraggedSegments() )
454  effort |= OPTIMIZER::MERGE_COLINEAR;
455 
456  optimizer.SetEffortLevel( effort );
457 
458  OPT_BOX2I affectedArea = aDragged.ChangedArea( &aOrig );
459  VECTOR2I anchor( aP );
460 
461  if( aDragged.CLine().Find( aP ) < 0 )
462  {
463  anchor = aDragged.CLine().NearestPoint( aP );
464  }
465 
466  optimizer.SetPreserveVertex( anchor );
467 
468  // People almost never want KiCad to reroute tracks in areas they can't even see, so restrict
469  // the area to what is visible even if we are optimizing the "entire" track.
470  if( Settings().GetOptimizeEntireDraggedTrack() )
471  affectedArea = VisibleViewArea();
472  else if( !affectedArea )
473  affectedArea = BOX2I( aP ); // No valid area yet? set to minimum to disable optimization
474 
475  PNS_DBG( Dbg(), AddPoint, anchor, YELLOW, 100000, "drag-anchor" );
476  PNS_DBG( Dbg(), AddBox, *affectedArea, RED, "drag-affected-area" );
477 
478  optimizer.SetRestrictArea( *affectedArea );
479  optimizer.Optimize( &aDragged );
480 
481  OPT_BOX2I optArea = aDragged.ChangedArea( &aOrig );
482 
483  if( optArea )
484  PNS_DBG( Dbg(), AddBox, *optArea, BLUE, "drag-opt-area" );
485 
486  m_lastNode->Add( aDragged );
488  m_draggedItems.Add( aDragged );
489 }
490 
491 
492 bool DRAGGER::tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk )
493 {
494  WALKAROUND walkaround( aNode, Router() );
495  bool ok = false;
496  walkaround.SetSolidsOnly( false );
497  walkaround.SetDebugDecorator( Dbg() );
498  walkaround.SetLogger( Logger() );
499  walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
500 
501  aWalk = aOrig;
502 
503  WALKAROUND::RESULT wr = walkaround.Route( aWalk );
504 
505 
507  {
508  aWalk = ( wr.lineCw.CLine().Length() < wr.lineCcw.CLine().Length() ? wr.lineCw :
509  wr.lineCcw );
510  ok = true;
511  }
512  else if( wr.statusCw == WALKAROUND::DONE )
513  {
514  aWalk = wr.lineCw;
515  ok = true;
516  }
517  else if( wr.statusCcw == WALKAROUND::DONE )
518  {
519  aWalk = wr.lineCcw;
520  ok = true;
521  }
522  return ok;
523 }
524 
525 
527 {
528  bool ok = false;
529 // fixme: rewrite using shared_ptr...
530  if( m_lastNode )
531  {
532  delete m_lastNode;
533  m_lastNode = nullptr;
534  }
535 
537 
538  switch( m_mode )
539  {
540  case DM_SEGMENT:
541  case DM_CORNER:
542  {
543  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
544  LINE dragged( m_draggedLine );
545  LINE draggedWalk( m_draggedLine );
546  LINE origLine( m_draggedLine );
547 
548  dragged.SetSnapThreshhold( thresh );
549 
550  if( m_mode == DM_SEGMENT )
551  dragged.DragSegment( aP, m_draggedSegmentIndex );
552  else
553  dragged.DragCorner( aP, m_draggedSegmentIndex );
554 
555  if ( m_world->CheckColliding( &dragged ) )
556  {
557  ok = tryWalkaround( m_lastNode, dragged, draggedWalk );
558  }
559  else
560  {
561  draggedWalk = dragged;
562  ok = true;
563  }
564 
565  if( ok )
566  {
567  PNS_DBG( Dbg(), AddLine, origLine.CLine(), BLUE, 50000, "drag-orig-line" );
568  PNS_DBG( Dbg(), AddLine, draggedWalk.CLine(), CYAN, 75000, "drag-walk" );
569  m_lastNode->Remove( origLine );
570  optimizeAndUpdateDraggedLine( draggedWalk, origLine, aP );
571  }
572  break;
573  }
574  case DM_VIA: // fixme...
575  {
577  break;
578  }
579  }
580 
581  m_dragStatus = ok;
582 
583  return true;
584 }
585 
586 
587 bool DRAGGER::dragShove( const VECTOR2I& aP )
588 {
589  bool ok = false;
590 
591  if( m_lastNode )
592  {
593  delete m_lastNode;
594  m_lastNode = NULL;
595  }
596 
597  switch( m_mode )
598  {
599  case DM_SEGMENT:
600  case DM_CORNER:
601  {
602  //TODO: Make threshold configurable
603  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 2 : 0;
604  LINE dragged( m_draggedLine );
605  dragged.SetSnapThreshhold( thresh );
606 
607  if( m_mode == DM_SEGMENT )
608  dragged.DragSegment( aP, m_draggedSegmentIndex );
609  else
610  dragged.DragCorner( aP, m_draggedSegmentIndex );
611 
612  PNS_DBG( Dbg(), AddLine, dragged.CLine(), BLUE, 5000, "drag-shove-line" );
613 
614  SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( dragged );
615 
616  if( st == SHOVE::SH_OK )
617  ok = true;
618  else if( st == SHOVE::SH_HEAD_MODIFIED )
619  {
620  dragged = m_shove->NewHead();
621  ok = true;
622  }
623 
624  m_lastNode = m_shove->CurrentNode()->Branch();
625 
626  if( ok )
627  {
628  VECTOR2D lockV;
629  dragged.ClearLinks();
630  dragged.Unmark();
632  m_lastDragSolution = dragged;
633  }
634  else
635  {
638  }
639 
640  break;
641  }
642 
643  case DM_VIA:
644  {
645  VIA_HANDLE newVia;
646 
647  SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, newVia );
648 
649  if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED )
650  ok = true;
651 
652  m_lastNode = m_shove->CurrentNode()->Branch();
653 
654  if( newVia.valid )
655  m_draggedVia = newVia;
656 
658  break;
659  }
660  }
661 
662  m_dragStatus = ok;
663 
664  return ok;
665 }
666 
667 
669 {
670  NODE* node = CurrentNode();
671 
672  if( node )
673  {
674  // If collisions exist, we can fix in shove/smart mode because all tracks to be committed
675  // will be in valid positions (even if the current routing solution to the mouse cursor is
676  // invalid). In other modes, we can only commit if "Allow DRC violations" is enabled.
677  if( !m_dragStatus )
678  {
680  node = CurrentNode();
681 
682  if( !node )
683  return false;
684  }
685 
686  if( !m_dragStatus && !Settings().AllowDRCViolations() )
687  return false;
688 
689  Router()->CommitRouting( node );
690  return true;
691  }
692 
693  return false;
694 }
695 
696 
697 bool DRAGGER::Drag( const VECTOR2I& aP )
698 {
700 
701  bool ret = false;
702 
703  if( m_freeAngleMode )
704  {
705  ret = dragMarkObstacles( aP );
706  }
707  else
708  {
709  switch( m_currentMode )
710  {
711  case RM_MarkObstacles:
712  ret = dragMarkObstacles( aP );
713  break;
714 
715  case RM_Shove:
716  case RM_Smart:
717  ret = dragShove( aP );
718  break;
719 
720  case RM_Walkaround:
721  ret = dragWalkaround( aP );
722  break;
723 
724  default:
725  break;
726  }
727  }
728 
729  if( ret )
730  m_lastValidPoint = aP;
731 
732  return ret;
733 }
734 
735 
737 {
738  return m_lastNode ? m_lastNode : m_world;
739 }
740 
741 
743 {
744  return m_draggedItems;
745 }
746 
747 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:148
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:137
Base class for PNS router board items.
Definition: pns_item.h:55
ITEM_SET m_draggedItems
If true, moves the connection lines without maintaining 45 degrees corners.
Definition: pns_dragger.h:147
const VIA_HANDLE MakeHandle() const
Definition: pns_via.cpp:122
ROUTER * Router() const
Return current router settings.
Definition: pns_algo_base.h:54
long long int Length() const
Function Length()
bool Drag(const VECTOR2I &aP) override
Function Drag()
BOX2< VECTOR2I > BOX2I
Definition: box2.h:512
bool tryWalkaround(NODE *aNode, LINE &aOrig, LINE &aWalk)
bool Empty() const
Definition: pns_itemset.h:133
Keep the router "world" - i.e.
Definition: pns_node.h:144
bool propagateViaForces(NODE *node, std::set< VIA * > &vias)
Definition: pns_dragger.cpp:52
OPT_BOX2I ChangedArea(const LINE *aOther) const
Definition: pns_line.cpp:1165
void DragSegment(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition: pns_line.cpp:742
DRAGGER(ROUTER *aRouter)
Definition: pns_dragger.cpp:32
void CommitRouting()
Definition: pns_router.cpp:694
std::unique_ptr< SHOVE > m_shove
Definition: pns_dragger.h:139
DRAG_ALGO.
Definition: pns_drag_algo.h:42
int Width() const override
Definition: pns_segment.h:79
WALKAROUND_STATUS statusCw
ENTRIES & Items()
Definition: pns_itemset.h:138
bool m_dragStatus
Definition: pns_dragger.h:141
void SetRestrictArea(const BOX2I &aArea, bool aStrict=true)
virtual LOGGER * Logger()
void optimizeAndUpdateDraggedLine(LINE &aDragged, const LINE &aOrig, const VECTOR2I &aP)
bool startDragSegment(const VECTOR2D &aP, SEGMENT *aSeg)
VIA_HANDLE m_draggedVia
Definition: pns_dragger.h:133
virtual bool Start(const VECTOR2I &aP, ITEM_SET &aPrimitives) override
Function Start()
LINE m_draggedLine
Definition: pns_dragger.h:137
const ITEM_SET Traces() override
Function Traces()
WALKAROUND_STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
NODE * CurrentNode() const override
Function CurrentNode()
bool startDragArc(const VECTOR2D &aP, ARC *aArc)
const SEG & Seg() const
Definition: pns_segment.h:84
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:60
virtual void Unmark(int aMarker=-1) const
Definition: pns_item.h:209
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:127
bool startDragVia(VIA *aVia)
int PointCount() const
Definition: pns_line.h:140
LINE m_lastDragSolution
Definition: pns_dragger.h:138
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Finds a point on the line chain that is closest to point aP.
void Remove(ARC *aArc)
Remove an item from this branch.
Definition: pns_node.cpp:810
int Start() const
Definition: pns_layerset.h:82
const std::vector< ssize_t > & CShapes() const
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
Definition: color4d.h:67
bool dragViaMarkObstacles(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
Represents a 2D point on a given set of layers and belonging to a certain net, that links together a ...
Definition: pns_joint.h:42
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
Definition: pns_line.cpp:1019
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=NULL, bool aStopAtLockedJoints=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Definition: pns_node.cpp:920
#define NULL
int Find(const VECTOR2I &aP, int aThreshold=0) const
Function Find()
int m_draggedSegmentIndex
Definition: pns_dragger.h:140
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I aV=VECTOR2I(0, 0))
#define PNS_DBG(dbg, method,...)
void SetPreserveVertex(const VECTOR2I &aV)
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:78
void AddTrailPoint(const VECTOR2I &aP)
bool SmoothDraggedSegments() const
Enable/disable smoothing segments during dragging.
PNS_MODE Mode() const
Set the routing mode.
Definition: color4d.h:58
void SetSolidsOnly(bool aSolidsOnly)
bool dragViaWalkaround(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
const LINKED_ITEMS & LinkList() const
Definition: pns_joint.h:195
Reduce corner cost iteratively.
Definition: pns_optimizer.h:99
Definition: color4d.h:59
MOUSE_TRAIL_TRACER m_mouseTrailTracer
Definition: pns_dragger.h:151
JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, int aNet)
Search for a joint at a given position, layer and belonging to given net.
Definition: pns_node.cpp:1104
NODE * m_lastNode
Definition: pns_dragger.h:135
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition: pns_line.cpp:728
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
bool FixRoute() override
Function FixRoute()
const BOX2I & VisibleViewArea() const
Guess what's better, try to make least mess on the PCB.
const ITEM_SET findViaFanoutByHandle(NODE *aNode, const VIA_HANDLE &handle)
Definition: color4d.h:56
bool dragWalkaround(const VECTOR2I &aP)
Ignore collisions, mark obstacles.
bool dragShove(const VECTOR2I &aP)
PNS_MODE m_currentMode
Definition: pns_dragger.h:142
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:265
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Check if the item collides with anything else in the world, and if found, returns the obstacle.
Definition: pns_node.cpp:433
WALKAROUND_STATUS statusCcw
LAYER_RANGE layers
Definition: pns_via.h:44
VECTOR2I A
Definition: seg.h:48
VIA_HANDLE m_initialVia
Definition: pns_dragger.h:132
int Width() const
Return true if the line is geometrically identical as line aOther.
Definition: pns_line.h:156
bool dragMarkObstacles(const VECTOR2I &aP)
Only walk around.
OPT< BOX2I > OPT_BOX2I
Definition: box2.h:515
void SetDebugDecorator(DEBUG_DECORATOR *aDecorator)
Assign a debug decorator allowing this algo to draw extra graphics for visual debugging.
Definition: pns_algo_base.h:73
VECTOR2I pos
Definition: pns_via.h:43
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:128
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
Definition: pns_optimizer.h:94
bool m_freeAngleMode
Definition: pns_dragger.h:150
Merge co-linear segments.
void SetEffortLevel(int aEffort)
Push and Shove diff pair dimensions (gap) settings dialog.
VECTOR2D m_lastValidPoint
Contains the list of items that are currently modified by the dragger.
Definition: pns_dragger.h:144
VVIA * checkVirtualVia(const VECTOR2D &aP, SEGMENT *aSeg)
Definition: pns_dragger.cpp:71
void SetLogger(LOGGER *aLogger)
Definition: pns_algo_base.h:65
void SetMode(int aDragMode) override
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:621
void SetIterationLimit(const int aIterLimit)
virtual void Unmark(int aMarker=-1) const override
Definition: pns_line.cpp:99
void SetSnapThreshhold(int aThreshhold)
Definition: pns_line.h:221
VECTOR2I B
Definition: seg.h:49