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_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
51
52
53bool DRAGGER::propagateViaForces( NODE* node, std::set<VIA*>& vias )
54{
55 VIA* via = *vias.begin();
56
57 VECTOR2I force;
58 VECTOR2I lead = -m_mouseTrailTracer.GetTrailLeadVector();
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
113 m_draggedLine = m_world->AssembleLine( aSeg, &m_draggedSegmentIndex );
115
116 auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
117 auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
118
119 if( distA < w2 || distB < w2 )
120 {
122
123 if( distB <= distA )
125 }
126 else if( m_freeAngleMode )
127 {
128 if( distB < distA &&
129 ( m_draggedSegmentIndex < m_draggedLine.PointCount() - 2 ) &&
130 ( !m_draggedLine.CLine().IsPtOnArc( static_cast<size_t>(m_draggedSegmentIndex) + 1 ) ) )
131 {
133 }
134
136 }
137 else
138 {
140 }
141
142 return true;
143}
144
145
146bool DRAGGER::startDragArc( const VECTOR2D& aP, ARC* aArc )
147{
148 m_draggedLine = m_world->AssembleLine( aArc, &m_draggedSegmentIndex );
149 m_mode = DM_ARC;
150
151 return true;
152}
153
154
156{
157 m_initialVia = aVia->MakeHandle();
159
160 m_mode = DM_VIA;
161
162 return true;
163}
164
166{
167 ITEM_SET rv;
168
169 const JOINT* jt = aNode->FindJoint( handle.pos, handle.layers.Start(), handle.net );
170
171 if( !jt )
172 return rv;
173
174 bool foundVia = false;
175
176 for( ITEM* item : jt->LinkList() )
177 {
178 if( item->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
179 {
180 int segIndex;
181 LINKED_ITEM* seg = ( LINKED_ITEM*) item;
182 LINE l = aNode->AssembleLine( seg, &segIndex );
183
184 if( segIndex != 0 )
185 l.Reverse();
186
187 rv.Add( l );
188 }
189 else if( item->OfKind( ITEM::VIA_T ) )
190 {
191 if( !foundVia )
192 {
193 rv.Add( item );
194 foundVia = true;
195 }
196 }
197 }
198
199 return rv;
200}
201
202bool DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
203{
204 if( aPrimitives.Empty() )
205 return false;
206
207 ITEM* startItem = aPrimitives[0];
208
209 m_lastNode = nullptr;
210 m_draggedItems.Clear();
214 m_lastValidPoint = aP;
215
216 m_mouseTrailTracer.Clear();
217 m_mouseTrailTracer.AddTrailPoint( aP );
218
219 m_preDragNode = m_world->Branch();
220
222 {
223 m_shove = std::make_unique<SHOVE>( m_preDragNode, Router() );
224 m_shove->SetLogger( Logger() );
225 m_shove->SetDebugDecorator( Dbg() );
226 m_shove->SetDefaultShovePolicy( SHOVE::SHP_SHOVE );
227 }
228
229 startItem->Unmark( MK_LOCKED );
230
231 PNS_DBG( Dbg(), Message, wxString::Format( "StartDragging: item %p [kind %d]",
232 startItem, (int) startItem->Kind() ) );
233
234 switch( startItem->Kind() )
235 {
236 case ITEM::SEGMENT_T:
237 {
238 SEGMENT* seg = static_cast<SEGMENT*>( startItem );
239 VVIA* vvia = checkVirtualVia( aP, seg );
240
241 if( vvia )
242 return startDragVia( vvia );
243 else
244 return startDragSegment( aP, seg );
245 }
246 case ITEM::VIA_T:
247 return startDragVia( static_cast<VIA*>( startItem ) );
248
249 case ITEM::ARC_T:
250 return startDragArc( aP, static_cast<ARC*>( startItem ) );
251
252 default:
253 return false;
254 }
255}
256
257
259{
260 m_mode = static_cast<int>( aMode );
261}
262
263
265{
266 return static_cast<PNS::DRAG_MODE>( m_mode );
267}
268
269
270const std::vector<NET_HANDLE> DRAGGER::CurrentNets() const
271{
272 if( m_mode == PNS::DM_VIA )
273 return std::vector<NET_HANDLE>( 1, m_draggedVia.net );
274 else
275 return std::vector<NET_HANDLE>( 1, m_draggedLine.Net() );
276}
277
278
280{
281 // fixme: rewrite using shared_ptr...
282 if( m_lastNode )
283 {
284 delete m_lastNode;
285 m_lastNode = nullptr;
286 }
287
288 m_lastNode = m_world->Branch();
289
290 switch( m_mode )
291 {
292 case DM_SEGMENT:
293 case DM_CORNER:
294 {
295 //TODO: Make threshold configurable
296 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
297 LINE origLine( m_draggedLine );
298 LINE dragged( m_draggedLine );
299 dragged.SetSnapThreshhold( thresh );
300 dragged.ClearLinks();
301
302 if( m_mode == DM_SEGMENT )
303 dragged.DragSegment( aP, m_draggedSegmentIndex );
304 else
306
307 m_lastNode->Remove( origLine );
308 m_lastNode->Add( dragged );
309
310 m_draggedItems.Clear();
311 m_draggedItems.Add( dragged );
312
313 break;
314 }
315
316 case DM_VIA: // fixme...
318
319 break;
320 }
321
322 if( Settings().AllowDRCViolations() )
323 m_dragStatus = true;
324 else
325 m_dragStatus = !m_lastNode->CheckColliding( m_draggedItems );
326
327 return true;
328}
329
330
331bool DRAGGER::dragViaMarkObstacles( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
332{
333 m_draggedItems.Clear();
334
335 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
336
337 if( fanout.Empty() )
338 return true;
339
340 for( ITEM* item : fanout.Items() )
341 {
342 if( const LINE* l = dyn_cast<const LINE*>( item ) )
343 {
344 LINE origLine( *l );
345 LINE draggedLine( *l );
346
347 draggedLine.DragCorner( aP, origLine.CLine().Find( aHandle.pos ), m_freeAngleMode );
348 draggedLine.ClearLinks();
349
350 m_draggedItems.Add( draggedLine );
351
352 m_lastNode->Remove( origLine );
353 m_lastNode->Add( draggedLine );
354 }
355 else if ( VIA *via = dyn_cast<VIA*>( item ) )
356 {
357 auto nvia = Clone( *via );
358
359 nvia->SetPos( aP );
360 m_draggedItems.Add( nvia.get() );
361
362 m_lastNode->Remove( via );
363 m_lastNode->Add( std::move( nvia ) );
364 }
365 }
366
367 return true;
368}
369
370
371bool DRAGGER::dragViaWalkaround( const VIA_HANDLE& aHandle, NODE* aNode, const VECTOR2I& aP )
372{
373 m_draggedItems.Clear();
374
375 ITEM_SET fanout = findViaFanoutByHandle( aNode, aHandle );
376
377 if( fanout.Empty() )
378 return true;
379
380 bool viaPropOk = false;
381 VECTOR2I viaTargetPos;
382
383 for( ITEM* item : fanout.Items() )
384 {
385 if( VIA *via = dyn_cast<VIA*>( item ) )
386 {
387 std::unique_ptr<VIA> draggedVia = Clone( *via );
388
389 draggedVia->SetPos( aP );
390 m_draggedItems.Add( draggedVia.get() );
391
392 std::set<VIA*> vias;
393
394 vias.insert( draggedVia.get() );
395
396 m_lastNode->Remove( via );
397
398 bool ok = propagateViaForces( m_lastNode, vias );
399
400 if( ok )
401 {
402 viaTargetPos = draggedVia->Pos();
403 viaPropOk = true;
404 m_lastNode->Add( std::move(draggedVia) );
405 }
406 }
407 }
408
409 if( !viaPropOk ) // can't force-propagate the via? bummer...
410 return false;
411
412 for( ITEM* item : fanout.Items() )
413 {
414 if( const LINE* l = dyn_cast<const LINE*>( item ) )
415 {
416 LINE origLine( *l );
417 LINE draggedLine( *l );
418 LINE walkLine( *l );
419
420 draggedLine.DragCorner( viaTargetPos, origLine.CLine().Find( aHandle.pos ),
422 draggedLine.ClearLinks();
423
424 if ( m_world->CheckColliding( &draggedLine ) )
425 {
426 bool ok = tryWalkaround( m_lastNode, draggedLine, walkLine );
427
428 if( !ok )
429 return false;
430
431 m_lastNode->Remove( origLine );
432 optimizeAndUpdateDraggedLine( walkLine, origLine, aP );
433 }
434 else
435 {
436 m_draggedItems.Add( draggedLine );
437
438 m_lastNode->Remove( origLine );
439 m_lastNode->Add( draggedLine );
440 }
441 }
442 }
443
444 return true;
445}
446
447
448void DRAGGER::optimizeAndUpdateDraggedLine( LINE& aDragged, const LINE& aOrig, const VECTOR2I& aP )
449{
450 LINE draggedPostOpt, origLine( aOrig );
451
452 aDragged.ClearLinks();
453 aDragged.Unmark();
454
455 if( Settings().GetOptimizeEntireDraggedTrack() )
456 {
457 OPTIMIZER optimizer( m_lastNode );
458
459 int effort =
461
462 if( Settings().SmoothDraggedSegments() )
464
465 optimizer.SetEffortLevel( effort );
466
467 OPT_BOX2I affectedArea = aDragged.ChangedArea( &aOrig );
468 VECTOR2I anchor( aP );
469
470 if( aDragged.CLine().Find( aP ) < 0 )
471 anchor = aDragged.CLine().NearestPoint( aP );
472
473 optimizer.SetPreserveVertex( anchor );
474
475 if( !affectedArea )
476 affectedArea = BOX2I( aP ); // No valid area yet? set to minimum to disable optimization
477
478 PNS_DBG( Dbg(), AddPoint, anchor, YELLOW, 100000, wxT( "drag-anchor" ) );
479 PNS_DBG( Dbg(), AddShape, *affectedArea, RED, 0, wxT( "drag-affected-area" ) );
480
481 optimizer.SetRestrictArea( *affectedArea );
482
483 PNS_DBG( Dbg(), AddItem, aDragged.Clone(), RED, 0, wxT( "drag-preopt" ) );
484 aDragged.Line().Split( anchor );
485
486 optimizer.Optimize( &aDragged, &draggedPostOpt, &origLine );
487 PNS_DBG( Dbg(), AddItem, aDragged.Clone(), GREEN, 0, wxT( "drag-postopt" ) );
488 }
489 else
490 {
491 draggedPostOpt = aDragged;
492 }
493
494 m_lastNode->Add( draggedPostOpt );
495 m_draggedItems.Clear();
496 m_draggedItems.Add( draggedPostOpt );
497}
498
499
500bool DRAGGER::tryWalkaround( NODE* aNode, LINE& aOrig, LINE& aWalk )
501{
502 WALKAROUND walkaround( aNode, Router() );
503 bool ok = false;
504 walkaround.SetSolidsOnly( false );
505 walkaround.SetDebugDecorator( Dbg() );
506 walkaround.SetLogger( Logger() );
507 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
508 walkaround.SetLengthLimit( true, 30.0 );
510
511 aWalk = aOrig;
512
513 WALKAROUND::RESULT wr = walkaround.Route( aWalk );
514
516 {
517 aWalk = wr.lines[ WALKAROUND::WP_SHORTEST ];
518 return true;
519 }
520
521 return false;
522}
523
524
526{
527 bool ok = false;
528
529 // fixme: rewrite using shared_ptr...
530 if( m_lastNode )
531 {
532 delete m_lastNode;
533 m_lastNode = nullptr;
534 }
535
536 m_lastNode = m_world->Branch();
537
538 switch( m_mode )
539 {
540 case DM_SEGMENT:
541 case DM_CORNER:
542 {
543 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
544 LINE dragged( m_draggedLine );
545 LINE draggedWalk( m_draggedLine );
546 LINE origLine( m_draggedLine );
547
548 dragged.SetSnapThreshhold( thresh );
549
550 if( m_mode == DM_SEGMENT )
551 dragged.DragSegment( aP, m_draggedSegmentIndex );
552 else
553 dragged.DragCorner( aP, m_draggedSegmentIndex );
554
555 if ( m_world->CheckColliding( &dragged ) )
556 {
557 ok = tryWalkaround( m_lastNode, dragged, draggedWalk );
558 }
559 else
560 {
561 draggedWalk = dragged;
562 ok = true;
563 }
564
565 if( draggedWalk.CLine().PointCount() < 2 )
566 ok = false;
567
568 if( ok )
569 {
570 PNS_DBG( Dbg(), AddShape, &origLine.CLine(), BLUE, 50000, wxT( "drag-orig-line" ) );
571 PNS_DBG( Dbg(), AddShape, &draggedWalk.CLine(), CYAN, 75000, wxT( "drag-walk" ) );
572 m_lastNode->Remove( origLine );
573 optimizeAndUpdateDraggedLine( draggedWalk, origLine, aP );
574 }
575
576 break;
577 }
578 case DM_VIA: // fixme...
580 break;
581 }
582
583 m_dragStatus = ok;
584
585 return ok;
586}
587
588
590{
591
592 if( m_lastNode )
593 {
594 delete m_lastNode;
595 m_lastNode = nullptr;
596 }
597
598 switch( m_mode )
599 {
600 case DM_SEGMENT:
601 case DM_CORNER:
602 {
603 bool ok = false;
604 //TODO: Make threshold configurable
605 int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 2 : 0;
606 LINE draggedPreShove( m_draggedLine );
607 draggedPreShove.SetSnapThreshhold( thresh );
608
609 if( m_mode == DM_SEGMENT )
610 draggedPreShove.DragSegment( aP, m_draggedSegmentIndex );
611 else
612 draggedPreShove.DragCorner( aP, m_draggedSegmentIndex );
613
614 auto preShoveNode = m_shove->CurrentNode();
615
616 if( preShoveNode )
617 preShoveNode->Remove( draggedPreShove );
618
619 m_shove->ClearHeads();
620 m_shove->AddHeads( draggedPreShove, SHOVE::SHP_SHOVE | SHOVE::SHP_DONT_LOCK_ENDPOINTS );
621 ok = m_shove->Run() == SHOVE::SH_OK;
622
623 LINE draggedPostShove( draggedPreShove );
624
625 if( ok )
626 {
627 if( m_shove->HeadsModified() )
628 draggedPostShove = m_shove->GetModifiedHead( 0 );
629 }
630
631 m_lastNode = m_shove->CurrentNode()->Branch();
632
633 if( ok )
634 {
635 draggedPostShove.ClearLinks();
636 draggedPostShove.Unmark();
637 optimizeAndUpdateDraggedLine( draggedPostShove, m_draggedLine, aP );
638 m_lastDragSolution = std::move( draggedPostShove );
639 }
640
641 m_dragStatus = ok;
642 break;
643 }
644
645 case DM_VIA:
646 {
647 VIA_HANDLE newVia;
648
649 // corner count limiter intended to avoid excessive optimization produces mediocre results for via shoving.
650 // this is a hack that disables it, before I figure out a more reliable solution
651 m_shove->DisablePostShoveOptimizations( OPTIMIZER::LIMIT_CORNER_COUNT );
652
653 m_shove->ClearHeads();
654 m_shove->AddHeads( m_draggedVia, aP, SHOVE::SHP_SHOVE );
655
656 SHOVE::SHOVE_STATUS st = m_shove->Run(); //ShoveDraggingVia( m_draggedVia, aP, newVia );
657
658 PNS_DBG( Dbg(), Message, wxString::Format("head-mod %d",
659 m_shove->HeadsModified() ? 1: 0 ) );
660
661 if( m_shove->HeadsModified() )
662 {
663 newVia = m_shove->GetModifiedHeadVia( 0 );
664
665 PNS_DBG( Dbg(), Message, wxString::Format("newvia %d %d %d %d",
666 newVia.pos.x,
667 newVia.pos.y,
668 newVia.layers.Start(),
669 newVia.layers.End()
670 ) );
671
672 m_draggedVia = newVia;
673 }
674
675
676 m_lastNode = m_shove->CurrentNode()->Branch();
677
678 m_draggedItems.Clear();
679
680 // If drag didn't work (i.e. dragged onto a collision) try walkaround instead
681 if( st != SHOVE::SH_OK )
683 else
684 m_dragStatus = true;
685
686 break;
687 }
688 }
689
690 return m_dragStatus;
691}
692
693
694bool DRAGGER::FixRoute( bool aForceCommit )
695{
696 NODE* node = CurrentNode();
697
698 if( node )
699 {
700 if( m_dragStatus )
701 {
702 Router()->CommitRouting( node );
703 return true;
704 }
705 else if( m_forceMarkObstaclesMode )
706 {
707 if( aForceCommit )
708 {
709 Router()->CommitRouting( node );
710 return true;
711 }
712
713 return false;
714 }
715 else
716 {
717 // If collisions exist, we can fix in shove/smart mode because all tracks to be
718 // committed will be in valid positions (even if the current routing solution to
719 // the mouse cursor is invalid).
721 node = CurrentNode();
722
723 if( node && m_dragStatus )
724 {
725 Router()->CommitRouting( node );
726 return true;
727 }
728 }
729 }
730
731 return false;
732}
733
734
735bool DRAGGER::Drag( const VECTOR2I& aP )
736{
737 m_mouseTrailTracer.AddTrailPoint( aP );
738
739 bool ret = false;
740
742 {
743 ret = dragMarkObstacles( aP );
744 }
745 else
746 {
747 switch( m_currentMode )
748 {
749 case RM_MarkObstacles: ret = dragMarkObstacles( aP ); break;
750 case RM_Shove: ret = dragShove( aP ); break;
751 case RM_Walkaround: ret = dragWalkaround( aP ); break;
752 default: break;
753 }
754 }
755
756 if( ret )
757 {
758 m_lastValidPoint = aP;
759 }
760 else
761 {
762 if( m_lastNode )
763 {
764 NODE* parent = m_lastNode->GetParent()->Branch();
765 delete m_lastNode;
766 m_lastNode = parent;
767 m_draggedItems.Clear();
768 m_lastDragSolution.ClearLinks();
770 }
771 }
772
773 return ret;
774}
775
776
778{
779 return m_lastNode ? m_lastNode : m_world;
780}
781
782
784{
785 return m_draggedItems;
786}
787
788}
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:831
void SetSnapThreshhold(int aThreshhold)
Definition pns_line.h:237
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:845
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
virtual LINE * Clone() const override
Return a deep copy of the item.
Definition pns_line.cpp:162
Keep the router "world" - i.e.
Definition pns_node.h:232
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:295
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: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: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:53
NET_HANDLE net
Definition pns_via.h:55
PNS_LAYER_RANGE layers
Definition pns_via.h:54
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