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-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 * Author: Tomasz Wlostowski <[email protected]>
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
30namespace PNS {
31
33 DRAG_ALGO( aRouter ),
34 m_initialVia( {} ),
35 m_draggedVia( {} )
36{
37 m_world = nullptr;
38 m_lastNode = nullptr;
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
52bool DRAGGER::propagateViaForces( NODE* node, std::set<VIA*>& vias )
53{
54 VIA* via = *vias.begin();
55
56 VECTOR2I force;
58
59 const int iterLimit = Settings().ViaForcePropIterationLimit();
60
61 if( via->PushoutForce( node, lead, force, ITEM::ANY_T, iterLimit ) )
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 {
130 }
131 else if( distB <= w2 )
132 {
135 }
136 else if( m_freeAngleMode )
137 {
138 if( distB < distA &&
140 ( !m_draggedLine.CLine().IsPtOnArc( static_cast<size_t>(m_draggedSegmentIndex) + 1 ) ) )
141 {
143 }
144
146 }
147 else
148 {
150 }
151
152 return true;
153}
154
155
156bool 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
207bool 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 = nullptr;
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]",
233 startItem, (int) startItem->Kind() ) );
234
235 switch( startItem->Kind() )
236 {
237 case ITEM::SEGMENT_T:
238 {
239 SEGMENT* seg = static_cast<SEGMENT*>( startItem );
240 VVIA* vvia = checkVirtualVia( aP, seg );
241
242 if( vvia )
243 {
244 return startDragVia( vvia );
245 }
246 else
247 {
248 return startDragSegment( aP, seg );
249 }
250 }
251 case ITEM::VIA_T:
252 return startDragVia( static_cast<VIA*>( startItem ) );
253
254 case ITEM::ARC_T:
255 return startDragArc( aP, static_cast<ARC*>( startItem ) );
256
257 default:
258 return false;
259 }
260}
261
262
263void DRAGGER::SetMode( int aMode )
264{
265 m_mode = aMode;
266}
267
268
269const std::vector<int> DRAGGER::CurrentNets() const
270{
271 if( m_mode == PNS::DM_VIA )
272 return std::vector<int>( 1, m_draggedVia.net );
273 else
274 return std::vector<int>( 1, m_draggedLine.Net() );
275}
276
277
279{
280 // fixme: rewrite using shared_ptr...
281 if( m_lastNode )
282 {
283 delete m_lastNode;
284 m_lastNode = nullptr;
285 }
286
288
289 switch( m_mode )
290 {
291 case DM_SEGMENT:
292 case DM_CORNER:
293 {
294 //TODO: Make threshold configurable
295 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
296 LINE origLine( m_draggedLine );
297 LINE dragged( m_draggedLine );
298 dragged.SetSnapThreshhold( thresh );
299 dragged.ClearLinks();
300
301 if( m_mode == DM_SEGMENT )
302 dragged.DragSegment( aP, m_draggedSegmentIndex );
303 else
305
306 m_lastNode->Remove( origLine );
307 m_lastNode->Add( dragged );
308
310 m_draggedItems.Add( dragged );
311
312 break;
313 }
314
315 case DM_VIA: // fixme...
316 {
318
319 break;
320 }
321 }
322
323 if( Settings().AllowDRCViolations() )
324 m_dragStatus = true;
325 else
327
328 return true;
329}
330
331
332bool DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
333{
335
336 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
337
338 if( fanout.Empty() )
339 {
340 return true;
341 }
342
343 for( ITEM* item : fanout.Items() )
344 {
345 if( const LINE* l = dyn_cast<const LINE*>( item ) )
346 {
347 LINE origLine( *l );
348 LINE draggedLine( *l );
349
350 draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
351 draggedLine.ClearLinks();
352
353 m_draggedItems.Add( draggedLine );
354
355 m_lastNode->Remove( origLine );
356 m_lastNode->Add( draggedLine );
357 }
358 else if ( VIA *via = dyn_cast<VIA*>( item ) )
359 {
360 auto nvia = Clone( *via );
361
362 nvia->SetPos( aP );
363 m_draggedItems.Add( nvia.get() );
364
366 m_lastNode->Add( std::move( nvia ) );
367 }
368 }
369
370 return true;
371}
372
373
374bool DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
375{
377
378 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
379
380 if( fanout.Empty() )
381 {
382 return true;
383 }
384
385 bool viaPropOk = false;
386 VECTOR2I viaTargetPos;
387
388 for( ITEM* item : fanout.Items() )
389 {
390 if ( VIA *via = dyn_cast<VIA*>( item ) )
391 {
392 auto draggedVia = Clone( *via );
393
394 draggedVia->SetPos( aP );
395 m_draggedItems.Add( draggedVia.get() );
396
397 std::set<VIA*> vias;
398
399 vias.insert( draggedVia.get() );
400
401 bool ok = propagateViaForces( m_lastNode, vias );
402
403 if( ok )
404 {
405 viaTargetPos = draggedVia->Pos();
406 viaPropOk = true;
408 m_lastNode->Add( std::move(draggedVia) );
409 }
410 }
411 }
412
413 if( !viaPropOk ) // can't force-propagate the via? bummer...
414 return false;
415
416 for( ITEM* item : fanout.Items() )
417 {
418 if( const LINE* l = dyn_cast<const LINE*>( item ) )
419 {
420 LINE origLine( *l );
421 LINE draggedLine( *l );
422 LINE walkLine( *l );
423
424 draggedLine.DragCorner( viaTargetPos, origLine.CLine().Find( aHandle.pos ),
426 draggedLine.ClearLinks();
427
428 if ( m_world->CheckColliding( &draggedLine ) )
429 {
430 bool ok = tryWalkaround( m_lastNode, draggedLine, walkLine );
431
432 if( !ok )
433 return false;
434
435 m_lastNode->Remove( origLine );
436 optimizeAndUpdateDraggedLine( walkLine, origLine, aP );
437 }
438 else
439 {
440 m_draggedItems.Add( draggedLine );
441
442 m_lastNode->Remove( origLine );
443 m_lastNode->Add( draggedLine );
444 }
445 }
446 }
447
448 return true;
449}
450
451
452void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, const VECTOR2I& aP )
453{
454 VECTOR2D lockV;
455 aDragged.ClearLinks();
456 aDragged.Unmark();
457
458 lockV = aDragged.CLine().NearestPoint( aP );
459
460 OPTIMIZER optimizer( m_lastNode );
461
463
464 if( Settings().SmoothDraggedSegments() )
466
467 optimizer.SetEffortLevel( effort );
468
469 OPT_BOX2I affectedArea = aDragged.ChangedArea( &aOrig );
470 VECTOR2I anchor( aP );
471
472 if( aDragged.CLine().Find( aP ) < 0 )
473 {
474 anchor = aDragged.CLine().NearestPoint( aP );
475 }
476
477 optimizer.SetPreserveVertex( anchor );
478
479 // People almost never want KiCad to reroute tracks in areas they can't even see, so restrict
480 // the area to what is visible even if we are optimizing the "entire" track.
481 if( Settings().GetOptimizeEntireDraggedTrack() )
482 affectedArea = VisibleViewArea();
483 else if( !affectedArea )
484 affectedArea = BOX2I( aP ); // No valid area yet? set to minimum to disable optimization
485
486 PNS_DBG( Dbg(), AddPoint, anchor, YELLOW, 100000, wxT( "drag-anchor" ) );
487 PNS_DBG( Dbg(), AddShape, *affectedArea, RED, 0, wxT( "drag-affected-area" ) );
488
489 optimizer.SetRestrictArea( *affectedArea );
490 optimizer.Optimize( &aDragged );
491
492 OPT_BOX2I optArea = aDragged.ChangedArea( &aOrig );
493
494 if( optArea )
495 PNS_DBG( Dbg(), AddShape, *optArea, BLUE, 0, wxT( "drag-opt-area" ) );
496
497 m_lastNode->Add( aDragged );
499 m_draggedItems.Add( aDragged );
500}
501
502
503bool DRAGGER::tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk )
504{
505 WALKAROUND walkaround( aNode, Router() );
506 bool ok = false;
507 walkaround.SetSolidsOnly( false );
508 walkaround.SetDebugDecorator( Dbg() );
509 walkaround.SetLogger( Logger() );
510 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
511
512 aWalk = aOrig;
513
514 WALKAROUND::RESULT wr = walkaround.Route( aWalk );
515
517 {
518 if( wr.lineCw.CLine().PointCount() > 1
519 && wr.lineCw.CLine().Length() < wr.lineCcw.CLine().Length() )
520 {
521 aWalk = wr.lineCw;
522 ok = true;
523 }
524 else if( wr.lineCcw.CLine().PointCount() > 1 )
525 {
526 aWalk = wr.lineCcw;
527 ok = true;
528 }
529 }
530 else if( wr.statusCw == WALKAROUND::DONE && wr.lineCw.CLine().PointCount() > 1 )
531 {
532 aWalk = wr.lineCw;
533 ok = true;
534 }
535 else if( wr.statusCcw == WALKAROUND::DONE && wr.lineCcw.CLine().PointCount() > 1 )
536 {
537 aWalk = wr.lineCcw;
538 ok = true;
539 }
540
541 return ok;
542}
543
544
546{
547 bool ok = false;
548
549 // fixme: rewrite using shared_ptr...
550 if( m_lastNode )
551 {
552 delete m_lastNode;
553 m_lastNode = nullptr;
554 }
555
557
558 switch( m_mode )
559 {
560 case DM_SEGMENT:
561 case DM_CORNER:
562 {
563 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
564 LINE dragged( m_draggedLine );
565 LINE draggedWalk( m_draggedLine );
566 LINE origLine( m_draggedLine );
567
568 dragged.SetSnapThreshhold( thresh );
569
570 if( m_mode == DM_SEGMENT )
571 dragged.DragSegment( aP, m_draggedSegmentIndex );
572 else
573 dragged.DragCorner( aP, m_draggedSegmentIndex );
574
575 if ( m_world->CheckColliding( &dragged ) )
576 {
577 ok = tryWalkaround( m_lastNode, dragged, draggedWalk );
578 }
579 else
580 {
581 draggedWalk = dragged;
582 ok = true;
583 }
584
585 if( draggedWalk.CLine().PointCount() < 2 )
586 ok = false;
587
588 if( ok )
589 {
590 PNS_DBG( Dbg(), AddShape, &origLine.CLine(), BLUE, 50000, wxT( "drag-orig-line" ) );
591 PNS_DBG( Dbg(), AddShape, &draggedWalk.CLine(), CYAN, 75000, wxT( "drag-walk" ) );
592 m_lastNode->Remove( origLine );
593 optimizeAndUpdateDraggedLine( draggedWalk, origLine, aP );
594 }
595
596 break;
597 }
598 case DM_VIA: // fixme...
599 {
601 break;
602 }
603 }
604
605 m_dragStatus = ok;
606
607 return true;
608}
609
610
612{
613 bool ok = false;
614
615 if( m_lastNode )
616 {
617 delete m_lastNode;
618 m_lastNode = nullptr;
619 }
620
621 switch( m_mode )
622 {
623 case DM_SEGMENT:
624 case DM_CORNER:
625 {
626 //TODO: Make threshold configurable
627 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 2 : 0;
628 LINE dragged( m_draggedLine );
629 dragged.SetSnapThreshhold( thresh );
630
631 if( m_mode == DM_SEGMENT )
632 dragged.DragSegment( aP, m_draggedSegmentIndex );
633 else
634 dragged.DragCorner( aP, m_draggedSegmentIndex );
635
636 PNS_DBG( Dbg(), AddShape, &dragged.CLine(), BLUE, 5000, wxT( "drag-shove-line" ) );
637
638 SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( dragged );
639
640 if( st == SHOVE::SH_OK )
641 {
642 ok = true;
643 }
644 else if( st == SHOVE::SH_HEAD_MODIFIED )
645 {
646 dragged = m_shove->NewHead();
647 ok = true;
648 }
649
650 m_lastNode = m_shove->CurrentNode()->Branch();
651
652 if( ok )
653 {
654 VECTOR2D lockV;
655 dragged.ClearLinks();
656 dragged.Unmark();
658 m_lastDragSolution = dragged;
659 }
660 else
661 {
664 }
665
666 break;
667 }
668
669 case DM_VIA:
670 {
671 VIA_HANDLE newVia;
672
673 // corner count limiter intended to avoid excessive optimization produces mediocre results for via shoving.
674 // this is a hack that disables it, before I figure out a more reliable solution
675 m_shove->DisablePostShoveOptimizations( OPTIMIZER::LIMIT_CORNER_COUNT );
676 SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, newVia );
677
678 if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED )
679 ok = true;
680
681 m_lastNode = m_shove->CurrentNode()->Branch();
682
683 if( newVia.valid )
684 m_draggedVia = newVia;
685
687 break;
688 }
689 }
690
691 m_dragStatus = ok;
692
693 return ok;
694}
695
696
698{
699 NODE* node = CurrentNode();
700
701 if( node )
702 {
703 // If collisions exist, we can fix in shove/smart mode because all tracks to be committed
704 // will be in valid positions (even if the current routing solution to the mouse cursor is
705 // invalid). In other modes, we can only commit if "Allow DRC violations" is enabled.
706 if( !m_dragStatus )
707 {
709 node = CurrentNode();
710
711 if( !node )
712 return false;
713 }
714
715 if( !m_dragStatus && !Settings().AllowDRCViolations() )
716 return false;
717
718 Router()->CommitRouting( node );
719 return true;
720 }
721
722 return false;
723}
724
725
726bool DRAGGER::Drag( const VECTOR2I& aP )
727{
729
730 bool ret = false;
731
732 if( m_freeAngleMode )
733 {
734 ret = dragMarkObstacles( aP );
735 }
736 else
737 {
738 switch( m_currentMode )
739 {
740 case RM_MarkObstacles: ret = dragMarkObstacles( aP ); break;
741 case RM_Shove: ret = dragShove( aP ); break;
742 case RM_Walkaround: ret = dragWalkaround( aP ); break;
743 default: break;
744 }
745 }
746
747 if( ret )
748 m_lastValidPoint = aP;
749
750 return ret;
751}
752
753
755{
756 return m_lastNode ? m_lastNode : m_world;
757}
758
759
761{
762 return m_draggedItems;
763}
764
765}
BOX2< VECTOR2I > BOX2I
Definition: box2.h:847
std::optional< BOX2I > OPT_BOX2I
Definition: box2.h:850
int Start() const
Definition: pns_layerset.h:82
const BOX2I & VisibleViewArea() const
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
void SetLogger(LOGGER *aLogger)
Definition: pns_algo_base.h:65
virtual LOGGER * Logger()
ROUTER * Router() const
Return current router settings.
Definition: pns_algo_base.h:54
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:78
ITEM_SET m_draggedItems
If true, moves the connection lines without maintaining 45 degrees corners.
Definition: pns_dragger.h:144
bool m_dragStatus
Definition: pns_dragger.h:138
void optimizeAndUpdateDraggedLine(LINE &aDragged, const LINE &aOrig, const VECTOR2I &aP)
const ITEM_SET findViaFanoutByHandle(NODE *aNode, const VIA_HANDLE &handle)
bool startDragSegment(const VECTOR2D &aP, SEGMENT *aSeg)
VECTOR2D m_lastValidPoint
Contains the list of items that are currently modified by the dragger.
Definition: pns_dragger.h:141
virtual bool Start(const VECTOR2I &aP, ITEM_SET &aPrimitives) override
Function Start()
NODE * CurrentNode() const override
Function CurrentNode()
DRAGGER(ROUTER *aRouter)
Definition: pns_dragger.cpp:32
bool dragViaMarkObstacles(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
bool Drag(const VECTOR2I &aP) override
Function Drag()
bool startDragVia(VIA *aVia)
LINE m_lastDragSolution
Definition: pns_dragger.h:135
int m_draggedSegmentIndex
Definition: pns_dragger.h:137
bool dragShove(const VECTOR2I &aP)
bool dragMarkObstacles(const VECTOR2I &aP)
std::unique_ptr< SHOVE > m_shove
Definition: pns_dragger.h:136
NODE * m_lastNode
Definition: pns_dragger.h:132
LINE m_draggedLine
Definition: pns_dragger.h:134
bool dragWalkaround(const VECTOR2I &aP)
bool FixRoute() override
Function FixRoute()
const std::vector< int > CurrentNets() const override
Function CurrentNets()
VVIA * checkVirtualVia(const VECTOR2D &aP, SEGMENT *aSeg)
Definition: pns_dragger.cpp:71
VIA_HANDLE m_draggedVia
Definition: pns_dragger.h:130
bool dragViaWalkaround(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
bool m_freeAngleMode
Definition: pns_dragger.h:147
PNS_MODE m_currentMode
Definition: pns_dragger.h:139
void SetMode(int aDragMode) override
const ITEM_SET Traces() override
Function Traces()
bool tryWalkaround(NODE *aNode, LINE &aOrig, LINE &aWalk)
bool startDragArc(const VECTOR2D &aP, ARC *aArc)
MOUSE_TRAIL_TRACER m_mouseTrailTracer
Definition: pns_dragger.h:148
VIA_HANDLE m_initialVia
Definition: pns_dragger.h:129
bool propagateViaForces(NODE *node, std::set< VIA * > &vias)
Definition: pns_dragger.cpp:52
DRAG_ALGO.
Definition: pns_drag_algo.h:43
bool Empty() const
Definition: pns_itemset.h:130
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
ENTRIES & Items()
Definition: pns_itemset.h:135
Base class for PNS router board items.
Definition: pns_item.h:56
virtual void Unmark(int aMarker=-1) const
Definition: pns_item.h:213
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:132
@ SEGMENT_T
Definition: pns_item.h:66
int Net() const
Definition: pns_item.h:154
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
Definition: pns_joint.h:43
const LINKED_ITEMS & LinkList() const
Definition: pns_joint.h:241
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
virtual void Unmark(int aMarker=-1) const override
Definition: pns_line.cpp:99
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:142
OPT_BOX2I ChangedArea(const LINE *aOther) const
Definition: pns_line.cpp:1152
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
Definition: pns_line.cpp:1023
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition: pns_line.cpp:734
void SetSnapThreshhold(int aThreshhold)
Definition: pns_line.h:224
void DragSegment(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition: pns_line.cpp:748
int PointCount() const
Definition: pns_line.h:145
int Width() const
Return true if the line is geometrically identical as line aOther.
Definition: pns_line.h:161
void AddTrailPoint(const VECTOR2I &aP)
Keep the router "world" - i.e.
Definition: pns_node.h:156
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:139
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:472
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:664
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:1189
void Remove(ARC *aArc)
Remove an item from this branch.
Definition: pns_node.cpp:881
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Definition: pns_node.cpp:991
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
Definition: pns_optimizer.h:95
void SetPreserveVertex(const VECTOR2I &aV)
void SetRestrictArea(const BOX2I &aArea, bool aStrict=true)
void SetEffortLevel(int aEffort)
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
@ LIMIT_CORNER_COUNT
Do not attempt to optimize if the resulting line's corner count is outside the predefined range.
@ MERGE_SEGMENTS
Reduce corner cost iteratively.
Definition: pns_optimizer.h:99
@ MERGE_COLINEAR
Merge co-linear segments.
void CommitRouting()
Definition: pns_router.cpp:894
int ViaForcePropIterationLimit() const
bool SmoothDraggedSegments() const
Enable/disable smoothing segments during dragging.
PNS_MODE Mode() const
Set the routing mode.
const SEG & Seg() const
Definition: pns_segment.h:84
int Width() const override
Definition: pns_segment.h:79
@ SH_HEAD_MODIFIED
Definition: pns_shove.h:54
const VIA_HANDLE MakeHandle() const
Definition: pns_via.cpp:213
void SetIterationLimit(const int aIterLimit)
void SetSolidsOnly(bool aSolidsOnly)
WALKAROUND_STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
bool IsPtOnArc(size_t aPtIndex) const
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
long long int Length() const
Return length of the line chain in Euclidean metric.
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
@ BLUE
Definition: color4d.h:56
@ CYAN
Definition: color4d.h:58
@ YELLOW
Definition: color4d.h:67
@ RED
Definition: color4d.h:59
Push and Shove diff pair dimensions (gap) settings dialog.
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
@ RM_Walkaround
Only walk around.
@ RM_Shove
Only shove.
@ DM_CORNER
Definition: pns_router.h:72
@ DM_FREE_ANGLE
Definition: pns_router.h:75
@ DM_VIA
Definition: pns_router.h:74
@ DM_SEGMENT
Definition: pns_router.h:73
@ DM_ARC
Definition: pns_router.h:76
@ MK_LOCKED
Definition: pns_item.h:43
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:279
#define PNS_DBG(dbg, method,...)
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
VECTOR2I pos
Definition: pns_via.h:44
LAYER_RANGE layers
Definition: pns_via.h:45
WALKAROUND_STATUS statusCcw
WALKAROUND_STATUS statusCw
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129