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 The 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_dragger.h"
23
24#include <core/typeinfo.h>
25
26#include "pns_arc.h"
27#include "pns_shove.h"
28#include "pns_router.h"
29#include "pns_debug_decorator.h"
30#include "pns_walkaround.h"
31
32
33namespace PNS {
34
36 DRAG_ALGO( aRouter ),
37 m_initialVia( {} ),
38 m_draggedVia( {} )
39{
40 m_world = nullptr;
41 m_lastNode = nullptr;
42 m_mode = DM_SEGMENT;
43 m_draggedSegmentIndex = 0;
44 m_dragStatus = false;
45 m_currentMode = RM_MarkObstacles;
46 m_freeAngleMode = false;
47 m_forceMarkObstaclesMode = false;
48}
49
50
54
55
56bool DRAGGER::propagateViaForces( NODE* node, std::set<VIA*>& vias )
57{
58 VIA* via = *vias.begin();
59
60 VECTOR2I force;
61 VECTOR2I lead = -m_mouseTrailTracer.GetTrailLeadVector();
62
63 const int iterLimit = Settings().ViaForcePropIterationLimit();
64
65 if( via->PushoutForce( node, lead, force, ITEM::ANY_T, iterLimit ) )
66 {
67 via->SetPos( via->Pos() + force );
68 return true;
69 }
70
71 return false;
72}
73
74
76{
77 int w2 = aSeg->Width() / 2;
78
79 auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
80 auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
81
82 VECTOR2I psnap;
83
84 if( distA <= w2 )
85 {
86 psnap = aSeg->Seg().A;
87 }
88 else if( distB <= w2 )
89 {
90 psnap = aSeg->Seg().B;
91 }
92 else
93 {
94 return nullptr;
95 }
96
97 const JOINT *jt = m_world->FindJoint( psnap, aSeg );
98
99 if ( !jt )
100 return nullptr;
101
102 for( ITEM* item : jt->LinkList() )
103 {
104 if( item->IsVirtual() && item->OfKind( ITEM::VIA_T ))
105 return static_cast<VVIA*>( item );
106 }
107
108 return nullptr;
109}
110
111
113{
114 int w2 = aSeg->Width() / 2;
115
116 m_draggedLine = m_world->AssembleLine( aSeg, &m_draggedSegmentIndex );
118
119 auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
120 auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
121
122 if( distA < w2 || distB < w2 )
123 {
125
126 if( distB <= distA )
128 }
129 else if( m_freeAngleMode )
130 {
131 if( distB < distA &&
132 ( m_draggedSegmentIndex < m_draggedLine.PointCount() - 2 ) &&
133 ( !m_draggedLine.CLine().IsPtOnArc( static_cast<size_t>(m_draggedSegmentIndex) + 1 ) ) )
134 {
136 }
137
139 }
140 else
141 {
143 }
144
145 return true;
146}
147
148
149bool DRAGGER::startDragArc( const VECTOR2D& aP, ARC* aArc )
150{
151 m_draggedLine = m_world->AssembleLine( aArc, &m_draggedSegmentIndex );
152 m_mode = DM_ARC;
153
154 return true;
155}
156
157
159{
160 m_initialVia = aVia->MakeHandle();
162
163 m_mode = DM_VIA;
164
165 return true;
166}
167
169{
170 ITEM_SET rv;
171
172 const JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
173
174 if( !jt )
175 return rv;
176
177 bool foundVia = false;
178
179 for( ITEM* item : jt->LinkList() )
180 {
181 if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
182 {
183 int segIndex;
184 LINKED_ITEM* seg = ( LINKED_ITEM*) item;
185 LINE l = aNode->AssembleLine( seg, &segIndex );
186
187 if( segIndex != 0 )
188 l.Reverse();
189
190 rv.Add( l );
191 }
192 else if( item->OfKind( ITEM::VIA_T ) )
193 {
194 if( !foundVia )
195 {
196 rv.Add( item );
197 foundVia = true;
198 }
199 }
200 }
201
202 return rv;
203}
204
205bool DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
206{
207 if( aPrimitives.Empty() )
208 return false;
209
210 ITEM* startItem = aPrimitives[0];
211
212 m_lastNode = nullptr;
213 m_draggedItems.Clear();
217 m_lastValidPoint = aP;
218
219 m_mouseTrailTracer.Clear();
220 m_mouseTrailTracer.AddTrailPoint( aP );
221
222 m_preDragNode = m_world->Branch();
223
225 {
226 m_shove = std::make_unique<SHOVE>( m_preDragNode, Router() );
227 m_shove->SetLogger( Logger() );
228 m_shove->SetDebugDecorator( Dbg() );
229 m_shove->SetDefaultShovePolicy( SHOVE::SHP_SHOVE );
230 }
231
232 startItem->Unmark( MK_LOCKED );
233
234 PNS_DBG( Dbg(), Message, wxString::Format( "StartDragging: item %p [kind %d]",
235 startItem, (int) startItem->Kind() ) );
236
237 switch( startItem->Kind() )
238 {
239 case ITEM::SEGMENT_T:
240 {
241 SEGMENT* seg = static_cast<SEGMENT*>( startItem );
242 VVIA* vvia = checkVirtualVia( aP, seg );
243
244 if( vvia )
245 return startDragVia( vvia );
246 else
247 return startDragSegment( aP, seg );
248 }
249 case ITEM::VIA_T:
250 return startDragVia( static_cast<VIA*>( startItem ) );
251
252 case ITEM::ARC_T:
253 return startDragArc( aP, static_cast<ARC*>( startItem ) );
254
255 default:
256 return false;
257 }
258}
259
260
262{
263 m_mode = static_cast<int>( aMode );
264}
265
266
268{
269 return static_cast<PNS::DRAG_MODE>( m_mode );
270}
271
272
273const std::vector<NET_HANDLE> DRAGGER::CurrentNets() const
274{
275 if( m_mode == PNS::DM_VIA )
276 return std::vector<NET_HANDLE>( 1, m_draggedVia.net );
277 else
278 return std::vector<NET_HANDLE>( 1, m_draggedLine.Net() );
279}
280
281
283{
284 // fixme: rewrite using shared_ptr...
285 if( m_lastNode )
286 {
287 delete m_lastNode;
288 m_lastNode = nullptr;
289 }
290
291 m_lastNode = m_world->Branch();
292
293 switch( m_mode )
294 {
295 case DM_SEGMENT:
296 case DM_CORNER:
297 {
298 //TODO: Make threshold configurable
299 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
300 LINE origLine( m_draggedLine );
301 LINE dragged( m_draggedLine );
302 dragged.SetSnapThreshhold( thresh );
303 dragged.ClearLinks();
304
305 if( m_mode == DM_SEGMENT )
306 dragged.DragSegment( aP, m_draggedSegmentIndex );
307 else
309
310 m_lastNode->Remove( origLine );
311 m_lastNode->Add( dragged );
312
313 m_draggedItems.Clear();
314 m_draggedItems.Add( dragged );
315
316 break;
317 }
318
319 case DM_VIA: // fixme...
321
322 break;
323 }
324
325 if( Settings().AllowDRCViolations() )
326 m_dragStatus = true;
327 else
328 m_dragStatus = !m_lastNode->CheckColliding( m_draggedItems );
329
330 return true;
331}
332
333
334bool DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
335{
336 m_draggedItems.Clear();
337
338 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
339
340 if( fanout.Empty() )
341 return true;
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
365 m_lastNode->Remove( via );
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{
376 m_draggedItems.Clear();
377
378 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
379
380 if( fanout.Empty() )
381 return true;
382
383 bool viaPropOk = false;
384 VECTOR2I viaTargetPos;
385
386 for( ITEM* item : fanout.Items() )
387 {
388 if( VIA *via = dyn_cast<VIA*>( item ) )
389 {
390 std::unique_ptr<VIA> draggedVia = Clone( *via );
391
392 draggedVia->SetPos( aP );
393 m_draggedItems.Add( draggedVia.get() );
394
395 std::set<VIA*> vias;
396
397 vias.insert( draggedVia.get() );
398
399 m_lastNode->Remove( via );
400
401 bool ok = propagateViaForces( m_lastNode, vias );
402
403 if( ok )
404 {
405 viaTargetPos = draggedVia->Pos();
406 viaPropOk = true;
407 m_lastNode->Add( std::move(draggedVia) );
408 }
409 }
410 }
411
412 if( !viaPropOk ) // can't force-propagate the via? bummer...
413 return false;
414
415 for( ITEM* item : fanout.Items() )
416 {
417 if( const LINE* l = dyn_cast<const LINE*>( item ) )
418 {
419 LINE origLine( *l );
420 LINE draggedLine( *l );
421 LINE walkLine( *l );
422
423 draggedLine.DragCorner( viaTargetPos, origLine.CLine().Find( aHandle.pos ),
425 draggedLine.ClearLinks();
426
427 if ( m_world->CheckColliding( &draggedLine ) )
428 {
429 bool ok = tryWalkaround( m_lastNode, draggedLine, walkLine );
430
431 if( !ok )
432 return false;
433
434 m_lastNode->Remove( origLine );
435 optimizeAndUpdateDraggedLine( walkLine, origLine, aP );
436 }
437 else
438 {
439 m_draggedItems.Add( draggedLine );
440
441 m_lastNode->Remove( origLine );
442 m_lastNode->Add( draggedLine );
443 }
444 }
445 }
446
447 return true;
448}
449
450
451void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, const VECTOR2I& aP )
452{
453 LINE draggedPostOpt, origLine( aOrig );
454
455 aDragged.ClearLinks();
456 aDragged.Unmark();
457
458 if( Settings().GetOptimizeEntireDraggedTrack() )
459 {
460 OPTIMIZER optimizer( m_lastNode );
461
462 int effort =
464
465 if( Settings().SmoothDraggedSegments() )
467
468 optimizer.SetEffortLevel( effort );
469
470 OPT_BOX2I affectedArea = aDragged.ChangedArea( &aOrig );
471 VECTOR2I anchor( aP );
472
473 if( aDragged.CLine().Find( aP ) < 0 )
474 anchor = aDragged.CLine().NearestPoint( aP );
475
476 optimizer.SetPreserveVertex( anchor );
477
478 if( !affectedArea )
479 affectedArea = BOX2I( aP ); // No valid area yet? set to minimum to disable optimization
480
481 PNS_DBG( Dbg(), AddPoint, anchor, YELLOW, 100000, wxT( "drag-anchor" ) );
482 PNS_DBG( Dbg(), AddShape, *affectedArea, RED, 0, wxT( "drag-affected-area" ) );
483
484 optimizer.SetRestrictArea( *affectedArea );
485
486 PNS_DBG( Dbg(), AddItem, &aDragged, RED, 0, wxT( "drag-preopt" ) );
487 aDragged.Line().Split( anchor );
488
489 optimizer.Optimize( &aDragged, &draggedPostOpt, &origLine );
490 PNS_DBG( Dbg(), AddItem, &aDragged, GREEN, 0, wxT( "drag-postopt" ) );
491 }
492 else
493 {
494 draggedPostOpt = aDragged;
495 }
496
497 m_lastNode->Add( draggedPostOpt );
498 m_draggedItems.Clear();
499 m_draggedItems.Add( draggedPostOpt );
500}
501
502
503bool DRAGGER::tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk )
504{
505 WALKAROUND walkaround( aNode, Router() );
506 walkaround.SetSolidsOnly( false );
507 walkaround.SetDebugDecorator( Dbg() );
508 walkaround.SetLogger( Logger() );
509 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
510 walkaround.SetLengthLimit( true, 30.0 );
512
513 aWalk = aOrig;
514
515 WALKAROUND::RESULT wr = walkaround.Route( aWalk );
516
518 {
519 aWalk = wr.lines[ WALKAROUND::WP_SHORTEST ];
520 return true;
521 }
522
523 return false;
524}
525
526
528{
529 bool ok = false;
530
531 // fixme: rewrite using shared_ptr...
532 if( m_lastNode )
533 {
534 delete m_lastNode;
535 m_lastNode = nullptr;
536 }
537
538 m_lastNode = m_world->Branch();
539
540 switch( m_mode )
541 {
542 case DM_SEGMENT:
543 case DM_CORNER:
544 {
545 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
546 LINE dragged( m_draggedLine );
547 LINE draggedWalk( m_draggedLine );
548 LINE origLine( m_draggedLine );
549
550 dragged.SetSnapThreshhold( thresh );
551
552 if( m_mode == DM_SEGMENT )
553 dragged.DragSegment( aP, m_draggedSegmentIndex );
554 else
555 dragged.DragCorner( aP, m_draggedSegmentIndex );
556
557 if ( m_world->CheckColliding( &dragged ) )
558 {
559 ok = tryWalkaround( m_lastNode, dragged, draggedWalk );
560 }
561 else
562 {
563 draggedWalk = dragged;
564 ok = true;
565 }
566
567 if( draggedWalk.CLine().PointCount() < 2 )
568 ok = false;
569
570 if( ok )
571 {
572 PNS_DBG( Dbg(), AddShape, &origLine.CLine(), BLUE, 50000, wxT( "drag-orig-line" ) );
573 PNS_DBG( Dbg(), AddShape, &draggedWalk.CLine(), CYAN, 75000, wxT( "drag-walk" ) );
574 m_lastNode->Remove( origLine );
575 optimizeAndUpdateDraggedLine( draggedWalk, origLine, aP );
576 }
577
578 break;
579 }
580 case DM_VIA: // fixme...
582 break;
583 }
584
585 m_dragStatus = ok;
586
587 return ok;
588}
589
590
592{
593
594 if( m_lastNode )
595 {
596 delete m_lastNode;
597 m_lastNode = nullptr;
598 }
599
600 switch( m_mode )
601 {
602 case DM_SEGMENT:
603 case DM_CORNER:
604 {
605 bool ok = false;
606 //TODO: Make threshold configurable
607 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 2 : 0;
608 LINE draggedPreShove( m_draggedLine );
609 draggedPreShove.SetSnapThreshhold( thresh );
610
611 if( m_mode == DM_SEGMENT )
612 draggedPreShove.DragSegment( aP, m_draggedSegmentIndex );
613 else
614 draggedPreShove.DragCorner( aP, m_draggedSegmentIndex );
615
616 auto preShoveNode = m_shove->CurrentNode();
617
618 if( preShoveNode )
619 preShoveNode->Remove( draggedPreShove );
620
622
623 PNS_DBG( Dbg(), Message, wxString::Format( "drag seg index %d", m_draggedSegmentIndex ) );
624
625 if( m_mode == DM_CORNER && m_draggedSegmentIndex == 0 )
626 policy |= SHOVE::SHP_REVERSED;
627
628 m_shove->ClearHeads();
629 m_shove->AddHeads( draggedPreShove, policy );
630 ok = m_shove->Run() == SHOVE::SH_OK;
631
632 LINE draggedPostShove( draggedPreShove );
633
634 if( ok )
635 {
636 if( m_shove->HeadsModified() )
637 draggedPostShove = m_shove->GetModifiedHead( 0 );
638 }
639
640 m_lastNode = m_shove->CurrentNode()->Branch();
641
642 if( ok )
643 {
644 draggedPostShove.ClearLinks();
645 draggedPostShove.Unmark();
646 optimizeAndUpdateDraggedLine( draggedPostShove, m_draggedLine, aP );
647 m_lastDragSolution = std::move( draggedPostShove );
648 }
649
650 m_dragStatus = ok;
651 break;
652 }
653
654 case DM_VIA:
655 {
656 VIA_HANDLE newVia;
657
658 // corner count limiter intended to avoid excessive optimization produces mediocre results for via shoving.
659 // this is a hack that disables it, before I figure out a more reliable solution
660 m_shove->DisablePostShoveOptimizations( OPTIMIZER::LIMIT_CORNER_COUNT );
661
662 m_shove->ClearHeads();
663 m_shove->AddHeads( m_draggedVia, aP, SHOVE::SHP_SHOVE );
664
665 SHOVE::SHOVE_STATUS st = m_shove->Run(); //ShoveDraggingVia( m_draggedVia, aP, newVia );
666
667 PNS_DBG( Dbg(), Message, wxString::Format("head-mod %d",
668 m_shove->HeadsModified() ? 1: 0 ) );
669
670 if( m_shove->HeadsModified() )
671 {
672 newVia = m_shove->GetModifiedHeadVia( 0 );
673
674 PNS_DBG( Dbg(), Message, wxString::Format("newvia %d %d %d %d",
675 newVia.pos.x,
676 newVia.pos.y,
677 newVia.layers.Start(),
678 newVia.layers.End()
679 ) );
680
681 m_draggedVia = newVia;
682 }
683
684
685 m_lastNode = m_shove->CurrentNode()->Branch();
686
687 m_draggedItems.Clear();
688
689 // If drag didn't work (i.e. dragged onto a collision) try walkaround instead
690 if( st != SHOVE::SH_OK )
692 else
693 m_dragStatus = true;
694
695 break;
696 }
697 }
698
699 return m_dragStatus;
700}
701
702
703bool DRAGGER::FixRoute( bool aForceCommit )
704{
705 NODE* node = CurrentNode();
706
707 if( node )
708 {
709 if( m_dragStatus )
710 {
711 Router()->CommitRouting( node );
712 return true;
713 }
714 else if( m_forceMarkObstaclesMode )
715 {
716 if( aForceCommit )
717 {
718 Router()->CommitRouting( node );
719 return true;
720 }
721
722 return false;
723 }
724 else
725 {
726 // If collisions exist, we can fix in shove/smart mode because all tracks to be
727 // committed will be in valid positions (even if the current routing solution to
728 // the mouse cursor is invalid).
730 node = CurrentNode();
731
732 if( node && m_dragStatus )
733 {
734 Router()->CommitRouting( node );
735 return true;
736 }
737 }
738 }
739
740 return false;
741}
742
743
744bool DRAGGER::Drag( const VECTOR2I& aP )
745{
746 m_mouseTrailTracer.AddTrailPoint( aP );
747
748 bool firstDrag = m_lastNode == nullptr;
749 bool ret = false;
750
752 {
753 ret = dragMarkObstacles( aP );
754 }
755 else
756 {
757 switch( m_currentMode )
758 {
759 case RM_MarkObstacles: ret = dragMarkObstacles( aP ); break;
760 case RM_Shove: ret = dragShove( aP ); break;
761 case RM_Walkaround: ret = dragWalkaround( aP ); break;
762 default: break;
763 }
764 }
765
766 if( ret )
767 {
768 m_lastValidPoint = aP;
769 }
770 else
771 {
772 if( firstDrag )
773 {
774 // First collision resolution failed, switch to highlight mode
776
777 ret = dragMarkObstacles( aP );
778
779 if( ret )
780 m_lastValidPoint = aP;
781 }
782 else if( m_lastNode )
783 {
784 // Restore last solution
785 NODE* parent = m_lastNode->GetParent()->Branch();
786 delete m_lastNode;
787 m_lastNode = parent;
788 m_draggedItems.Clear();
789 m_lastDragSolution.ClearLinks();
791 }
792 }
793
794 return ret;
795}
796
797
799{
800 return m_lastNode ? m_lastNode : m_world;
801}
802
803
805{
806 return m_draggedItems;
807}
808
809}
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.
void SetLogger(LOGGER *aLogger)
virtual LOGGER * Logger()
ROUTER * Router() const
Return current router settings.
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
DEBUG_DECORATOR * Dbg() const
ITEM_SET m_draggedItems
If true, moves the connection lines without maintaining 45 degrees corners.
PNS::DRAG_MODE Mode() const override
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.
virtual bool Start(const VECTOR2I &aP, ITEM_SET &aPrimitives) override
Function Start()
NODE * CurrentNode() const override
Function CurrentNode()
DRAGGER(ROUTER *aRouter)
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
int m_draggedSegmentIndex
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
NODE * m_lastNode
bool dragWalkaround(const VECTOR2I &aP)
VVIA * checkVirtualVia(const VECTOR2D &aP, SEGMENT *aSeg)
VIA_HANDLE m_draggedVia
bool dragViaWalkaround(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
bool m_freeAngleMode
bool m_forceMarkObstaclesMode
NODE * m_preDragNode
PNS_MODE m_currentMode
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
VIA_HANDLE m_initialVia
bool propagateViaForces(NODE *node, std::set< VIA * > &vias)
DRAG_ALGO(ROUTER *aRouter)
bool Empty() const
Definition pns_itemset.h:82
void Add(const LINE &aLine)
std::vector< ITEM * > & Items()
Definition pns_itemset.h:87
Base class for PNS router board items.
Definition pns_item.h:98
virtual void Unmark(int aMarker=-1) const
Definition pns_item.h:262
PnsKind Kind() const
Return the type (kind) of the item.
Definition pns_item.h:173
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
const SHAPE_LINE_CHAIN & CLine() const
Definition pns_line.h:142
SHAPE_LINE_CHAIN & Line()
Definition pns_line.h:141
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false, DIRECTION_45 aPreferredEndingDirection=DIRECTION_45())
Definition pns_line.cpp:832
void SetSnapThreshhold(int aThreshhold)
Definition pns_line.h:250
virtual void Unmark(int aMarker=-1) const override
Definition pns_line.cpp:180
void DragSegment(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
Definition pns_line.cpp:846
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
Keep the router "world" - i.e.
Definition pns_node.h:240
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.
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false, bool aAllowSegmentSizeMismatch=true)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
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.
@ MERGE_COLINEAR
Merge co-linear segments.
void CommitRouting()
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:93
int Width() const override
Definition pns_segment.h:88
@ SHP_DONT_LOCK_ENDPOINTS
Definition pns_shove.h:66
const VIA_HANDLE MakeHandle() const
Definition pns_via.cpp:310
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
int End() const
VECTOR2I A
Definition seg.h:49
VECTOR2I B
Definition seg.h:50
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:76
@ DM_CORNER
Definition pns_router.h:77
@ DM_FREE_ANGLE
Definition pns_router.h:80
@ DM_VIA
Definition pns_router.h:79
@ DM_SEGMENT
Definition pns_router.h:78
@ DM_ARC
Definition pns_router.h:81
@ MK_LOCKED
Definition pns_item.h:45
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition pns_item.h:344
#define PNS_DBG(dbg, method,...)
VECTOR2I pos
Definition pns_via.h:55
NET_HANDLE net
Definition pns_via.h:57
PNS_LAYER_RANGE layers
Definition pns_via.h:56
LINE lines[MaxWalkPolicies]
STATUS status[MaxWalkPolicies]
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
Definition typeinfo.h:61
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694