KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2024 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 m_forceMarkObstaclesMode = false;
45}
46
47
49{
50}
51
52
53bool DRAGGER::propagateViaForces( NODE* node, std::set<VIA*>& vias )
54{
55 VIA* via = *vias.begin();
56
57 VECTOR2I force;
59
60 const int iterLimit = Settings().ViaForcePropIterationLimit();
61
62 if( via->PushoutForce( node, lead, force, ITEM::ANY_T, iterLimit ) )
63 {
64 via->SetPos( via->Pos() + force );
65 return true;
66 }
67
68 return false;
69}
70
71
73{
74 int w2 = aSeg->Width() / 2;
75
76 auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
77 auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
78
79 VECTOR2I psnap;
80
81 if( distA <= w2 )
82 {
83 psnap = aSeg->Seg().A;
84 }
85 else if( distB <= w2 )
86 {
87 psnap = aSeg->Seg().B;
88 }
89 else
90 {
91 return nullptr;
92 }
93
94 const JOINT *jt = m_world->FindJoint( psnap, aSeg );
95
96 if ( !jt )
97 return nullptr;
98
99 for( ITEM* item : jt->LinkList() )
100 {
101 if( item->IsVirtual() && item->OfKind( ITEM::VIA_T ))
102 return static_cast<VVIA*>( item );
103 }
104
105 return nullptr;
106}
107
108
110{
111 int w2 = aSeg->Width() / 2;
112
115
117 {
118 // If we're already in a state that violates DRC then there's not much we can do but
119 // switch to mark obstacles mode.
121 }
122
124 m_shove->SetInitialLine( m_draggedLine );
125
126 auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
127 auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
128
129 if( distA < w2 || distB < w2 )
130 {
132
133 if( distB <= distA )
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
163 {
164 // If we're already in a state that violates DRC then there's not much we can do but
165 // switch to mark obstacles mode.
167 }
168
169 return true;
170}
171
172
174{
175 m_initialVia = aVia->MakeHandle();
177
178 m_mode = DM_VIA;
179
180 if ( m_world->CheckColliding( aVia ) )
181 {
182 // If we're already in a state that violates DRC then there's not much we can do but
183 // switch to mark obstacles mode.
185 }
186
187 return true;
188}
189
191{
192 ITEM_SET rv;
193
194 const JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
195
196 if( !jt )
197 return rv;
198
199 bool foundVia = false;
200
201 for( ITEM* item : jt->LinkList() )
202 {
203 if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
204 {
205 int segIndex;
206 LINKED_ITEM* seg = ( LINKED_ITEM*) item;
207 LINE l = aNode->AssembleLine( seg, &segIndex );
208
209 if( segIndex != 0 )
210 l.Reverse();
211
212 rv.Add( l );
213 }
214 else if( item->OfKind( ITEM::VIA_T ) )
215 {
216 if( !foundVia )
217 {
218 rv.Add( item );
219 foundVia = true;
220 }
221 }
222 }
223
224 return rv;
225}
226
227bool DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
228{
229 if( aPrimitives.Empty() )
230 return false;
231
232 ITEM* startItem = aPrimitives[0];
233
234 m_lastNode = nullptr;
239 m_lastValidPoint = aP;
240
243
245 {
246 m_shove = std::make_unique<SHOVE>( m_world, Router() );
247 m_shove->SetLogger( Logger() );
248 m_shove->SetDebugDecorator( Dbg() );
249 }
250
251 startItem->Unmark( MK_LOCKED );
252
253 PNS_DBG( Dbg(), Message, wxString::Format( "StartDragging: item %p [kind %d]",
254 startItem, (int) startItem->Kind() ) );
255
256 switch( startItem->Kind() )
257 {
258 case ITEM::SEGMENT_T:
259 {
260 SEGMENT* seg = static_cast<SEGMENT*>( startItem );
261 VVIA* vvia = checkVirtualVia( aP, seg );
262
263 if( vvia )
264 return startDragVia( vvia );
265 else
266 return startDragSegment( aP, seg );
267 }
268 case ITEM::VIA_T:
269 return startDragVia( static_cast<VIA*>( startItem ) );
270
271 case ITEM::ARC_T:
272 return startDragArc( aP, static_cast<ARC*>( startItem ) );
273
274 default:
275 return false;
276 }
277}
278
279
281{
282 m_mode = static_cast<int>( aMode );
283}
284
285
287{
288 return static_cast<PNS::DRAG_MODE>( m_mode );
289}
290
291
292const std::vector<NET_HANDLE> DRAGGER::CurrentNets() const
293{
294 if( m_mode == PNS::DM_VIA )
295 return std::vector<NET_HANDLE>( 1, m_draggedVia.net );
296 else
297 return std::vector<NET_HANDLE>( 1, m_draggedLine.Net() );
298}
299
300
302{
303 // fixme: rewrite using shared_ptr...
304 if( m_lastNode )
305 {
306 delete m_lastNode;
307 m_lastNode = nullptr;
308 }
309
311
312 switch( m_mode )
313 {
314 case DM_SEGMENT:
315 case DM_CORNER:
316 {
317 //TODO: Make threshold configurable
318 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
319 LINE origLine( m_draggedLine );
320 LINE dragged( m_draggedLine );
321 dragged.SetSnapThreshhold( thresh );
322 dragged.ClearLinks();
323
324 if( m_mode == DM_SEGMENT )
325 dragged.DragSegment( aP, m_draggedSegmentIndex );
326 else
328
329 m_lastNode->Remove( origLine );
330 m_lastNode->Add( dragged );
331
333 m_draggedItems.Add( dragged );
334
335 break;
336 }
337
338 case DM_VIA: // fixme...
340
341 break;
342 }
343
344 if( Settings().AllowDRCViolations() )
345 m_dragStatus = true;
346 else
348
349 return true;
350}
351
352
353bool DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
354{
356
357 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
358
359 if( fanout.Empty() )
360 return true;
361
362 for( ITEM* item : fanout.Items() )
363 {
364 if( const LINE* l = dyn_cast<const LINE*>( item ) )
365 {
366 LINE origLine( *l );
367 LINE draggedLine( *l );
368
369 draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
370 draggedLine.ClearLinks();
371
372 m_draggedItems.Add( draggedLine );
373
374 m_lastNode->Remove( origLine );
375 m_lastNode->Add( draggedLine );
376 }
377 else if ( VIA *via = dyn_cast<VIA*>( item ) )
378 {
379 auto nvia = Clone( *via );
380
381 nvia->SetPos( aP );
382 m_draggedItems.Add( nvia.get() );
383
385 m_lastNode->Add( std::move( nvia ) );
386 }
387 }
388
389 return true;
390}
391
392
393bool DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
394{
396
397 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
398
399 if( fanout.Empty() )
400 return true;
401
402 bool viaPropOk = false;
403 VECTOR2I viaTargetPos;
404
405 for( ITEM* item : fanout.Items() )
406 {
407 if( VIA *via = dyn_cast<VIA*>( item ) )
408 {
409 std::unique_ptr<VIA> draggedVia = Clone( *via );
410
411 draggedVia->SetPos( aP );
412 m_draggedItems.Add( draggedVia.get() );
413
414 std::set<VIA*> vias;
415
416 vias.insert( draggedVia.get() );
417
419
420 bool ok = propagateViaForces( m_lastNode, vias );
421
422 if( ok )
423 {
424 viaTargetPos = draggedVia->Pos();
425 viaPropOk = true;
426 m_lastNode->Add( std::move(draggedVia) );
427 }
428 }
429 }
430
431 if( !viaPropOk ) // can't force-propagate the via? bummer...
432 return false;
433
434 for( ITEM* item : fanout.Items() )
435 {
436 if( const LINE* l = dyn_cast<const LINE*>( item ) )
437 {
438 LINE origLine( *l );
439 LINE draggedLine( *l );
440 LINE walkLine( *l );
441
442 draggedLine.DragCorner( viaTargetPos, origLine.CLine().Find( aHandle.pos ),
444 draggedLine.ClearLinks();
445
446 if ( m_world->CheckColliding( &draggedLine ) )
447 {
448 bool ok = tryWalkaround( m_lastNode, draggedLine, walkLine );
449
450 if( !ok )
451 return false;
452
453 m_lastNode->Remove( origLine );
454 optimizeAndUpdateDraggedLine( walkLine, origLine, aP );
455 }
456 else
457 {
458 m_draggedItems.Add( draggedLine );
459
460 m_lastNode->Remove( origLine );
461 m_lastNode->Add( draggedLine );
462 }
463 }
464 }
465
466 return true;
467}
468
469
470void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, const VECTOR2I& aP )
471{
472 aDragged.ClearLinks();
473 aDragged.Unmark();
474
475 OPTIMIZER optimizer( m_lastNode );
476
478
479 if( Settings().SmoothDraggedSegments() )
481
482 optimizer.SetEffortLevel( effort );
483
484 OPT_BOX2I affectedArea = aDragged.ChangedArea( &aOrig );
485 VECTOR2I anchor( aP );
486
487 if( aDragged.CLine().Find( aP ) < 0 )
488 anchor = aDragged.CLine().NearestPoint( aP );
489
490 optimizer.SetPreserveVertex( anchor );
491
492 // People almost never want KiCad to reroute tracks in areas they can't even see, so restrict
493 // the area to what is visible even if we are optimizing the "entire" track.
494 if( Settings().GetOptimizeEntireDraggedTrack() )
495 affectedArea = VisibleViewArea();
496 else if( !affectedArea )
497 affectedArea = BOX2I( aP ); // No valid area yet? set to minimum to disable optimization
498
499 PNS_DBG( Dbg(), AddPoint, anchor, YELLOW, 100000, wxT( "drag-anchor" ) );
500 PNS_DBG( Dbg(), AddShape, *affectedArea, RED, 0, wxT( "drag-affected-area" ) );
501
502 optimizer.SetRestrictArea( *affectedArea );
503 optimizer.Optimize( &aDragged );
504
505 OPT_BOX2I optArea = aDragged.ChangedArea( &aOrig );
506
507 if( optArea )
508 PNS_DBG( Dbg(), AddShape, *optArea, BLUE, 0, wxT( "drag-opt-area" ) );
509
510 m_lastNode->Add( aDragged );
512 m_draggedItems.Add( aDragged );
513}
514
515
516bool DRAGGER::tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk )
517{
518 WALKAROUND walkaround( aNode, Router() );
519 bool ok = false;
520 walkaround.SetSolidsOnly( false );
521 walkaround.SetDebugDecorator( Dbg() );
522 walkaround.SetLogger( Logger() );
523 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
524
525 aWalk = aOrig;
526
527 WALKAROUND::RESULT wr = walkaround.Route( aWalk );
528
530 {
531 if( wr.lineCw.CLine().PointCount() > 1
532 && wr.lineCw.CLine().Length() < wr.lineCcw.CLine().Length() )
533 {
534 aWalk = wr.lineCw;
535 ok = true;
536 }
537 else if( wr.lineCcw.CLine().PointCount() > 1 )
538 {
539 aWalk = wr.lineCcw;
540 ok = true;
541 }
542 }
543 else if( wr.statusCw == WALKAROUND::DONE && wr.lineCw.CLine().PointCount() > 1 )
544 {
545 aWalk = wr.lineCw;
546 ok = true;
547 }
548 else if( wr.statusCcw == WALKAROUND::DONE && wr.lineCcw.CLine().PointCount() > 1 )
549 {
550 aWalk = wr.lineCcw;
551 ok = true;
552 }
553
554 return ok;
555}
556
557
559{
560 bool ok = false;
561
562 // fixme: rewrite using shared_ptr...
563 if( m_lastNode )
564 {
565 delete m_lastNode;
566 m_lastNode = nullptr;
567 }
568
570
571 switch( m_mode )
572 {
573 case DM_SEGMENT:
574 case DM_CORNER:
575 {
576 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
577 LINE dragged( m_draggedLine );
578 LINE draggedWalk( m_draggedLine );
579 LINE origLine( m_draggedLine );
580
581 dragged.SetSnapThreshhold( thresh );
582
583 if( m_mode == DM_SEGMENT )
584 dragged.DragSegment( aP, m_draggedSegmentIndex );
585 else
586 dragged.DragCorner( aP, m_draggedSegmentIndex );
587
588 if ( m_world->CheckColliding( &dragged ) )
589 {
590 ok = tryWalkaround( m_lastNode, dragged, draggedWalk );
591 }
592 else
593 {
594 draggedWalk = dragged;
595 ok = true;
596 }
597
598 if( draggedWalk.CLine().PointCount() < 2 )
599 ok = false;
600
601 if( ok )
602 {
603 PNS_DBG( Dbg(), AddShape, &origLine.CLine(), BLUE, 50000, wxT( "drag-orig-line" ) );
604 PNS_DBG( Dbg(), AddShape, &draggedWalk.CLine(), CYAN, 75000, wxT( "drag-walk" ) );
605 m_lastNode->Remove( origLine );
606 optimizeAndUpdateDraggedLine( draggedWalk, origLine, aP );
607 }
608
609 break;
610 }
611 case DM_VIA: // fixme...
613 break;
614 }
615
616 m_dragStatus = ok;
617
618 return ok;
619}
620
621
623{
624 bool ok = false;
625
626 if( m_lastNode )
627 {
628 delete m_lastNode;
629 m_lastNode = nullptr;
630 }
631
632 switch( m_mode )
633 {
634 case DM_SEGMENT:
635 case DM_CORNER:
636 {
637 //TODO: Make threshold configurable
638 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 2 : 0;
639 LINE dragged( m_draggedLine );
640 dragged.SetSnapThreshhold( thresh );
641
642 if( m_mode == DM_SEGMENT )
643 dragged.DragSegment( aP, m_draggedSegmentIndex );
644 else
645 dragged.DragCorner( aP, m_draggedSegmentIndex );
646
647 PNS_DBG( Dbg(), AddShape, &dragged.CLine(), BLUE, 5000, wxT( "drag-shove-line" ) );
648
649 SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( dragged );
650
651 if( st == SHOVE::SH_OK )
652 {
653 ok = true;
654 }
655 else if( st == SHOVE::SH_HEAD_MODIFIED )
656 {
657 dragged = m_shove->NewHead();
658 ok = true;
659 }
660
661 m_lastNode = m_shove->CurrentNode()->Branch();
662
663 if( ok )
664 {
665 VECTOR2D lockV;
666 dragged.ClearLinks();
667 dragged.Unmark();
669 m_lastDragSolution = dragged;
670 }
671 else
672 {
675 }
676
677 break;
678 }
679
680 case DM_VIA:
681 {
682 VIA_HANDLE newVia;
683
684 // corner count limiter intended to avoid excessive optimization produces mediocre results for via shoving.
685 // this is a hack that disables it, before I figure out a more reliable solution
686 m_shove->DisablePostShoveOptimizations( OPTIMIZER::LIMIT_CORNER_COUNT );
687 SHOVE::SHOVE_STATUS st = m_shove->ShoveDraggingVia( m_draggedVia, aP, newVia );
688
689 if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED )
690 ok = true;
691
692 m_lastNode = m_shove->CurrentNode()->Branch();
693
694 if( newVia.valid )
695 m_draggedVia = newVia;
696
698
699 // If drag didn't work (i.e. dragged onto a collision) try walkaround instead
700 if( !ok )
702
703 break;
704 }
705 }
706
707 m_dragStatus = ok;
708
709 return ok;
710}
711
712
713bool DRAGGER::FixRoute( bool aForceCommit )
714{
715 NODE* node = CurrentNode();
716
717 if( node )
718 {
719 if( m_dragStatus )
720 {
721 Router()->CommitRouting( node );
722 return true;
723 }
724 else if( m_forceMarkObstaclesMode )
725 {
726 if( aForceCommit )
727 {
728 Router()->CommitRouting( node );
729 return true;
730 }
731
732 return false;
733 }
734 else
735 {
736 // If collisions exist, we can fix in shove/smart mode because all tracks to be
737 // committed will be in valid positions (even if the current routing solution to
738 // the mouse cursor is invalid).
740 node = CurrentNode();
741
742 if( node && m_dragStatus )
743 {
744 Router()->CommitRouting( node );
745 return true;
746 }
747 }
748 }
749
750 return false;
751}
752
753
754bool DRAGGER::Drag( const VECTOR2I& aP )
755{
757
758 bool ret = false;
759
761 {
762 ret = dragMarkObstacles( aP );
763 }
764 else
765 {
766 switch( m_currentMode )
767 {
768 case RM_MarkObstacles: ret = dragMarkObstacles( aP ); break;
769 case RM_Shove: ret = dragShove( aP ); break;
770 case RM_Walkaround: ret = dragWalkaround( aP ); break;
771 default: break;
772 }
773 }
774
775 if( ret )
776 {
777 m_lastValidPoint = aP;
778 }
779 else
780 {
781 if( m_lastNode )
782 {
783 delete m_lastNode;
785 m_lastNode = nullptr;
786 }
787 }
788
789 return ret;
790}
791
792
794{
795 return m_lastNode ? m_lastNode : m_world;
796}
797
798
800{
801 return m_draggedItems;
802}
803
804}
BOX2< VECTOR2I > BOX2I
Definition: box2.h:922
std::optional< BOX2I > OPT_BOX2I
Definition: box2.h:926
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:162
PNS::DRAG_MODE Mode() const override
bool m_dragStatus
Definition: pns_dragger.h:156
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:159
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:153
int m_draggedSegmentIndex
Definition: pns_dragger.h:155
const std::vector< NET_HANDLE > CurrentNets() const override
Function CurrentNets()
bool dragShove(const VECTOR2I &aP)
void SetMode(PNS::DRAG_MODE aDragMode) override
bool dragMarkObstacles(const VECTOR2I &aP)
bool FixRoute(bool aForceCommit) override
Function FixRoute()
std::unique_ptr< SHOVE > m_shove
Definition: pns_dragger.h:154
NODE * m_lastNode
Definition: pns_dragger.h:150
LINE m_draggedLine
Definition: pns_dragger.h:152
bool dragWalkaround(const VECTOR2I &aP)
VVIA * checkVirtualVia(const VECTOR2D &aP, SEGMENT *aSeg)
Definition: pns_dragger.cpp:72
VIA_HANDLE m_draggedVia
Definition: pns_dragger.h:148
bool dragViaWalkaround(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
bool m_freeAngleMode
Definition: pns_dragger.h:165
bool m_forceMarkObstaclesMode
Definition: pns_dragger.h:166
PNS_MODE m_currentMode
Definition: pns_dragger.h:157
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:167
VIA_HANDLE m_initialVia
Definition: pns_dragger.h:147
bool propagateViaForces(NODE *node, std::set< VIA * > &vias)
Definition: pns_dragger.cpp:53
DRAG_ALGO.
Definition: pns_drag_algo.h:44
bool Empty() const
Definition: pns_itemset.h:82
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
std::vector< ITEM * > & Items()
Definition: pns_itemset.h:87
Base class for PNS router board items.
Definition: pns_item.h:97
virtual void Unmark(int aMarker=-1) const
Definition: pns_item.h:231
virtual NET_HANDLE Net() const
Definition: pns_item.h:194
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:167
@ SEGMENT_T
Definition: pns_item.h:106
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 std::vector< ITEM * > & LinkList() const
Definition: pns_joint.h:273
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
OPT_BOX2I ChangedArea(const LINE *aOther) const
Definition: pns_line.cpp:1172
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:136
void SetSnapThreshhold(int aThreshhold)
Definition: pns_line.h:219
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition: pns_line.cpp:754
virtual void Unmark(int aMarker=-1) const override
Definition: pns_line.cpp:119
int PointCount() const
Definition: pns_line.h:139
void DragSegment(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition: pns_line.cpp:768
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
Definition: pns_line.cpp:1043
int Width() const
Return true if the line is geometrically identical as line aOther.
Definition: pns_line.h:155
void AddTrailPoint(const VECTOR2I &aP)
Keep the router "world" - i.e.
Definition: pns_node.h:207
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:143
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:410
const JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, NET_HANDLE aNet) const
Search for a joint at a given position, layer and belonging to given net.
Definition: pns_node.cpp:1215
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:663
void Remove(ARC *aArc)
Remove an item from this branch.
Definition: pns_node.cpp:884
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:1017
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:899
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:193
void SetIterationLimit(const int aIterLimit)
void SetSolidsOnly(bool aSolidsOnly)
WALKAROUND_STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
int Start() const
Definition: pns_layerset.h:82
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.
DRAG_MODE
Definition: pns_router.h:71
@ 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:44
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:309
#define PNS_DBG(dbg, method,...)
VECTOR2I pos
Definition: pns_via.h:45
NET_HANDLE net
Definition: pns_via.h:47
PNS_LAYER_RANGE layers
Definition: pns_via.h:46
WALKAROUND_STATUS statusCcw
WALKAROUND_STATUS statusCw