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
123
124 auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
125 auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
126
127 if( distA < w2 || distB < w2 )
128 {
130
131 if( distB <= distA )
133 }
134 else if( m_freeAngleMode )
135 {
136 if( distB < distA &&
138 ( !m_draggedLine.CLine().IsPtOnArc( static_cast<size_t>(m_draggedSegmentIndex) + 1 ) ) )
139 {
141 }
142
144 }
145 else
146 {
148 }
149
150 return true;
151}
152
153
154bool DRAGGER::startDragArc( const VECTOR2D& aP, ARC* aArc )
155{
157 m_mode = DM_ARC;
158
160 {
161 // If we're already in a state that violates DRC then there's not much we can do but
162 // switch to mark obstacles mode.
164 }
165
166 return true;
167}
168
169
171{
172 m_initialVia = aVia->MakeHandle();
174
175 m_mode = DM_VIA;
176
177 if ( m_world->CheckColliding( aVia ) )
178 {
179 // If we're already in a state that violates DRC then there's not much we can do but
180 // switch to mark obstacles mode.
182 }
183
184 return true;
185}
186
188{
189 ITEM_SET rv;
190
191 const JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
192
193 if( !jt )
194 return rv;
195
196 bool foundVia = false;
197
198 for( ITEM* item : jt->LinkList() )
199 {
200 if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
201 {
202 int segIndex;
203 LINKED_ITEM* seg = ( LINKED_ITEM*) item;
204 LINE l = aNode->AssembleLine( seg, &segIndex );
205
206 if( segIndex != 0 )
207 l.Reverse();
208
209 rv.Add( l );
210 }
211 else if( item->OfKind( ITEM::VIA_T ) )
212 {
213 if( !foundVia )
214 {
215 rv.Add( item );
216 foundVia = true;
217 }
218 }
219 }
220
221 return rv;
222}
223
224bool DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
225{
226 if( aPrimitives.Empty() )
227 return false;
228
229 ITEM* startItem = aPrimitives[0];
230
231 m_lastNode = nullptr;
236 m_lastValidPoint = aP;
237
240
242
244 {
245 m_shove = std::make_unique<SHOVE>( m_preDragNode, Router() );
246 m_shove->SetLogger( Logger() );
247 m_shove->SetDebugDecorator( Dbg() );
248 m_shove->SetDefaultShovePolicy( SHOVE::SHP_SHOVE );
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 LINE draggedPostOpt, origLine( aOrig );
473
474 aDragged.ClearLinks();
475 aDragged.Unmark();
476
477 if( Settings().GetOptimizeEntireDraggedTrack() )
478 {
479 OPTIMIZER optimizer( m_lastNode );
480
481 int effort =
483
484 if( Settings().SmoothDraggedSegments() )
486
487 optimizer.SetEffortLevel( effort );
488
489 OPT_BOX2I affectedArea = aDragged.ChangedArea( &aOrig );
490 VECTOR2I anchor( aP );
491
492 if( aDragged.CLine().Find( aP ) < 0 )
493 anchor = aDragged.CLine().NearestPoint( aP );
494
495 optimizer.SetPreserveVertex( anchor );
496
497 if( !affectedArea )
498 affectedArea = BOX2I( aP ); // No valid area yet? set to minimum to disable optimization
499
500 PNS_DBG( Dbg(), AddPoint, anchor, YELLOW, 100000, wxT( "drag-anchor" ) );
501 PNS_DBG( Dbg(), AddShape, *affectedArea, RED, 0, wxT( "drag-affected-area" ) );
502
503 optimizer.SetRestrictArea( *affectedArea );
504
505 PNS_DBG( Dbg(), AddItem, aDragged.Clone(), RED, 0, wxT( "drag-preopt" ) );
506 aDragged.Line().Split( anchor );
507
508 optimizer.Optimize( &aDragged, &draggedPostOpt, &origLine );
509 PNS_DBG( Dbg(), AddItem, aDragged.Clone(), GREEN, 0, wxT( "drag-postopt" ) );
510 }
511 else
512 {
513 draggedPostOpt = aDragged;
514 }
515
516 m_lastNode->Add( draggedPostOpt );
518 m_draggedItems.Add( draggedPostOpt );
519}
520
521
522bool DRAGGER::tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk )
523{
524 WALKAROUND walkaround( aNode, Router() );
525 bool ok = false;
526 walkaround.SetSolidsOnly( false );
527 walkaround.SetDebugDecorator( Dbg() );
528 walkaround.SetLogger( Logger() );
529 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
530 walkaround.SetLengthLimit( true, 30.0 );
532
533 aWalk = aOrig;
534
535 WALKAROUND::RESULT wr = walkaround.Route( aWalk );
536
538 {
539 aWalk = wr.lines[ WALKAROUND::WP_SHORTEST ];
540 return true;
541 }
542
543 return false;
544}
545
546
548{
549 bool ok = false;
550
551 // fixme: rewrite using shared_ptr...
552 if( m_lastNode )
553 {
554 delete m_lastNode;
555 m_lastNode = nullptr;
556 }
557
559
560 switch( m_mode )
561 {
562 case DM_SEGMENT:
563 case DM_CORNER:
564 {
565 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
566 LINE dragged( m_draggedLine );
567 LINE draggedWalk( m_draggedLine );
568 LINE origLine( m_draggedLine );
569
570 dragged.SetSnapThreshhold( thresh );
571
572 if( m_mode == DM_SEGMENT )
573 dragged.DragSegment( aP, m_draggedSegmentIndex );
574 else
575 dragged.DragCorner( aP, m_draggedSegmentIndex );
576
577 if ( m_world->CheckColliding( &dragged ) )
578 {
579 ok = tryWalkaround( m_lastNode, dragged, draggedWalk );
580 }
581 else
582 {
583 draggedWalk = dragged;
584 ok = true;
585 }
586
587 if( draggedWalk.CLine().PointCount() < 2 )
588 ok = false;
589
590 if( ok )
591 {
592 PNS_DBG( Dbg(), AddShape, &origLine.CLine(), BLUE, 50000, wxT( "drag-orig-line" ) );
593 PNS_DBG( Dbg(), AddShape, &draggedWalk.CLine(), CYAN, 75000, wxT( "drag-walk" ) );
594 m_lastNode->Remove( origLine );
595 optimizeAndUpdateDraggedLine( draggedWalk, origLine, aP );
596 }
597
598 break;
599 }
600 case DM_VIA: // fixme...
602 break;
603 }
604
605 m_dragStatus = ok;
606
607 return ok;
608}
609
610
612{
613
614 if( m_lastNode )
615 {
616 delete m_lastNode;
617 m_lastNode = nullptr;
618 }
619
620 switch( m_mode )
621 {
622 case DM_SEGMENT:
623 case DM_CORNER:
624 {
625 bool ok = false;
626 //TODO: Make threshold configurable
627 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 2 : 0;
628 LINE draggedPreShove( m_draggedLine );
629 draggedPreShove.SetSnapThreshhold( thresh );
630
631 if( m_mode == DM_SEGMENT )
632 draggedPreShove.DragSegment( aP, m_draggedSegmentIndex );
633 else
634 draggedPreShove.DragCorner( aP, m_draggedSegmentIndex );
635
636 auto preShoveNode = m_shove->CurrentNode();
637
638 if( preShoveNode )
639 {
640 preShoveNode->Remove( draggedPreShove );
641 }
642
643 m_shove->ClearHeads();
644 m_shove->AddHeads( draggedPreShove, SHOVE::SHP_SHOVE );
645 ok = m_shove->Run() == SHOVE::SH_OK;
646
647 LINE draggedPostShove( draggedPreShove );
648
649 if( ok )
650 {
651 if( m_shove->HeadsModified() )
652 {
653 draggedPostShove = m_shove->GetModifiedHead( 0 );
654 }
655 }
656
657 m_lastNode = m_shove->CurrentNode()->Branch();
658
659 if( ok )
660 {
661 VECTOR2D lockV;
662 draggedPostShove.ClearLinks();
663 draggedPostShove.Unmark();
664 optimizeAndUpdateDraggedLine( draggedPostShove, m_draggedLine, aP );
665 m_lastDragSolution = draggedPostShove;
666 }
667
668 m_dragStatus = ok;
669 break;
670 }
671
672 case DM_VIA:
673 {
674 VIA_HANDLE newVia;
675
676 // corner count limiter intended to avoid excessive optimization produces mediocre results for via shoving.
677 // this is a hack that disables it, before I figure out a more reliable solution
678 m_shove->DisablePostShoveOptimizations( OPTIMIZER::LIMIT_CORNER_COUNT );
679
680 m_shove->ClearHeads();
681 m_shove->AddHeads( m_draggedVia, aP, SHOVE::SHP_SHOVE );
682
683 SHOVE::SHOVE_STATUS st = m_shove->Run(); //ShoveDraggingVia( m_draggedVia, aP, newVia );
684
685 PNS_DBG( Dbg(), Message, wxString::Format("head-mod %d",
686 m_shove->HeadsModified() ? 1: 0 ) );
687
688 if( m_shove->HeadsModified() )
689 {
690 newVia = m_shove->GetModifiedHeadVia( 0 );
691
692 PNS_DBG( Dbg(), Message, wxString::Format("newvia %d %d %d %d",
693 newVia.pos.x,
694 newVia.pos.y,
695 newVia.layers.Start(),
696 newVia.layers.End()
697 ) );
698
699 m_draggedVia = newVia;
700 }
701
702
703 m_lastNode = m_shove->CurrentNode()->Branch();
704
706
707 // If drag didn't work (i.e. dragged onto a collision) try walkaround instead
708 if( st != SHOVE::SH_OK )
710 else
711 m_dragStatus = true;
712
713 break;
714 }
715 }
716
717 return m_dragStatus;
718}
719
720
721bool DRAGGER::FixRoute( bool aForceCommit )
722{
723 NODE* node = CurrentNode();
724
725 if( node )
726 {
727 if( m_dragStatus )
728 {
729 Router()->CommitRouting( node );
730 return true;
731 }
732 else if( m_forceMarkObstaclesMode )
733 {
734 if( aForceCommit )
735 {
736 Router()->CommitRouting( node );
737 return true;
738 }
739
740 return false;
741 }
742 else
743 {
744 // If collisions exist, we can fix in shove/smart mode because all tracks to be
745 // committed will be in valid positions (even if the current routing solution to
746 // the mouse cursor is invalid).
748 node = CurrentNode();
749
750 if( node && m_dragStatus )
751 {
752 Router()->CommitRouting( node );
753 return true;
754 }
755 }
756 }
757
758 return false;
759}
760
761
762bool DRAGGER::Drag( const VECTOR2I& aP )
763{
765
766 bool ret = false;
767
769 {
770 ret = dragMarkObstacles( aP );
771 }
772 else
773 {
774 switch( m_currentMode )
775 {
776 case RM_MarkObstacles: ret = dragMarkObstacles( aP ); break;
777 case RM_Shove: ret = dragShove( aP ); break;
778 case RM_Walkaround: ret = dragWalkaround( aP ); break;
779 default: break;
780 }
781 }
782
783 if( ret )
784 {
785 m_lastValidPoint = aP;
786 }
787 else
788 {
789 if( m_lastNode )
790 {
791 NODE* parent = m_lastNode->GetParent()->Branch();
792 delete m_lastNode;
793 m_lastNode = parent;
797 }
798 }
799
800 return ret;
801}
802
803
805{
806 return m_lastNode ? m_lastNode : m_world;
807}
808
809
811{
812 return m_draggedItems;
813}
814
815}
BOX2< VECTOR2I > BOX2I
Definition: box2.h:922
std::optional< BOX2I > OPT_BOX2I
Definition: box2.h:926
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:163
PNS::DRAG_MODE Mode() const override
bool m_dragStatus
Definition: pns_dragger.h:157
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:160
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:154
int m_draggedSegmentIndex
Definition: pns_dragger.h:156
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:155
NODE * m_lastNode
Definition: pns_dragger.h:150
LINE m_draggedLine
Definition: pns_dragger.h:153
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:166
bool m_forceMarkObstaclesMode
Definition: pns_dragger.h:167
NODE * m_preDragNode
Definition: pns_dragger.h:151
PNS_MODE m_currentMode
Definition: pns_dragger.h:158
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:168
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:33
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:249
virtual NET_HANDLE Net() const
Definition: pns_item.h:197
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:170
@ 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:303
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:62
OPT_BOX2I ChangedArea(const LINE *aOther) const
Definition: pns_line.cpp:1215
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:138
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:137
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false, DIRECTION_45 aPreferredEndingDirection=DIRECTION_45())
Definition: pns_line.cpp:785
void SetSnapThreshhold(int aThreshhold)
Definition: pns_line.h:232
virtual void Unmark(int aMarker=-1) const override
Definition: pns_line.cpp:133
int PointCount() const
Definition: pns_line.h:141
void DragSegment(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition: pns_line.cpp:799
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
Definition: pns_line.cpp:1074
virtual LINE * Clone() const override
Return a deep copy of the item.
Definition: pns_line.cpp:115
int Width() const
Return true if the line is geometrically identical as line aOther.
Definition: pns_line.h:157
void AddTrailPoint(const VECTOR2I &aP)
Keep the router "world" - i.e.
Definition: pns_node.h:231
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:143
NODE * GetParent() const
Check if this branch contains an updated version of the m_item from the root branch.
Definition: pns_node.h:483
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:1242
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:665
void Remove(ARC *aArc)
Remove an item from this branch.
Definition: pns_node.cpp:906
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:1044
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)
static bool Optimize(const LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
void SetRestrictArea(const BOX2I &aArea, bool aStrict=true)
void SetEffortLevel(int aEffort)
@ 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:921
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:90
int Width() const override
Definition: pns_segment.h:85
const VIA_HANDLE MakeHandle() const
Definition: pns_via.cpp:281
void SetIterationLimit(const int aIterLimit)
void SetLengthLimit(bool aEnable, double aLengthExpansionFactor)
void SetSolidsOnly(bool aSolidsOnly)
STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
void SetAllowedPolicies(std::vector< WALK_POLICY > aPolicies)
int Start() const
Definition: pns_layerset.h:86
int End() const
Definition: pns_layerset.h:91
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
bool IsPtOnArc(size_t aPtIndex) const
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
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.
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
@ BLUE
Definition: color4d.h:56
@ GREEN
Definition: color4d.h:57
@ 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:327
#define PNS_DBG(dbg, method,...)
VECTOR2I pos
Definition: pns_via.h:53
NET_HANDLE net
Definition: pns_via.h:55
PNS_LAYER_RANGE layers
Definition: pns_via.h:54
LINE lines[MaxWalkPolicies]
STATUS status[MaxWalkPolicies]