KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pns_diff_pair_placer.cpp
Go to the documentation of this file.
1/*
2 * KiRouter - a push-and-(sometimes-)shove PCB router
3 *
4 * Copyright (C) 2013-2015 CERN
5 * Copyright (C) 2016-2023 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_walkaround.h"
23#include "pns_shove.h"
24#include "pns_router.h"
26#include "pns_solid.h"
27#include "pns_topology.h"
28#include "pns_debug_decorator.h"
29#include "pns_arc.h"
30
31namespace PNS {
32
34 PLACEMENT_ALGO( aRouter )
35{
37 m_chainedPlacement = false;
38 m_initialDiagonal = false;
39 m_startDiagonal = false;
40 m_fitOk = false;
41 m_netP = nullptr;
42 m_netN = nullptr;
43 m_iteration = 0;
44 m_world = nullptr;
45 m_shove = nullptr;
46 m_currentNode = nullptr;
47 m_lastNode = nullptr;
48 m_placingVia = false;
49 m_viaDiameter = 0;
50 m_viaDrill = 0;
53 m_startsOnVia = false;
54 m_orthoMode = false;
55 m_snapOnTarget = false;
56 m_currentEndItem = nullptr;
57 m_currentTraceOk = false;
58 m_idle = true;
59}
60
62{}
63
64
66{
67 m_world = aWorld;
68}
69
70
72{
74
75 VIA v( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), aNet, m_sizes.ViaType() );
76
77 return v;
78}
79
80
81void DIFF_PAIR_PLACER::SetOrthoMode ( bool aOrthoMode )
82{
83 m_orthoMode = aOrthoMode;
84
85 if( !m_idle )
86 Move( m_currentEnd, nullptr );
87}
88
89
90bool DIFF_PAIR_PLACER::ToggleVia( bool aEnabled )
91{
92 m_placingVia = aEnabled;
93
94 if( !m_idle )
95 Move( m_currentEnd, nullptr );
96
97 return true;
98}
99
100
102{
103 if( !routeHead( aP ) )
104 return false;
105
106 bool collP = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.PLine() ) );
107 bool collN = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.NLine() ) );
108
109 m_fitOk = !( collP || collN ) ;
110
111 return m_fitOk;
112}
113
114
116{
117 VIA virtHead = makeVia( aP, nullptr );
118
119 if( m_placingVia )
120 {
121 virtHead.SetDiameter( viaGap() + 2 * virtHead.Diameter() );
122 }
123 else
124 {
125 virtHead.SetLayer( m_currentLayer );
127 }
128
129 bool solidsOnly = true;
130
131 if( Settings().Mode() == RM_MarkObstacles )
132 {
133 aNewP = aP;
134 return true;
135 }
136 else if( Settings().Mode() == RM_Walkaround )
137 {
138 solidsOnly = false;
139 }
140
141 // fixme: I'm too lazy to do it well. Circular approximaton will do for the moment.
142
143 // Note: this code is lifted from VIA::PushoutForce and then optimized for this use case and to
144 // check proper clearances to the diff pair line. It can be removed if some specialized
145 // pushout for traces / diff pairs is implemented. Just calling VIA::PushoutForce does not work
146 // as the via may have different resolved clearance to items than the diff pair should.
147 int maxIter = 40;
148 int iter = 0;
149 bool collided = false;
150 VECTOR2I force, totalForce;
151 std::set<const ITEM*> handled;
152
153 while( iter < maxIter )
154 {
155 NODE::OPT_OBSTACLE obs = m_currentNode->CheckColliding( &virtHead, solidsOnly ?
157 ITEM::ANY_T );
158 if( !obs || handled.count( obs->m_item ) )
159 break;
160
161 int clearance = m_currentNode->GetClearance( obs->m_item, &m_currentTrace.PLine(), false );
162
163 if( obs->m_item->Shape()->Collide( virtHead.Shape(), clearance, &force ) )
164 {
165 collided = true;
166 totalForce += force;
167 virtHead.SetPos( virtHead.Pos() + force );
168 }
169
170 handled.insert( obs->m_item );
171
172 iter++;
173 }
174
175 bool succeeded = ( !collided || iter != maxIter );
176
177 if( succeeded )
178 {
179 aNewP = aP + force;
180 return true;
181 }
182
183 return false;
184}
185
186
188 bool aPFirst, bool aWindCw, bool aSolidsOnly )
189{
190 WALKAROUND walkaround( aNode, Router() );
192
193 walkaround.SetSolidsOnly( aSolidsOnly );
194 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
195
196 SHOVE shove( aNode, Router() );
197 LINE walkP, walkN;
198
199 aWalk = *aCurrent;
200
201 int iter = 0;
202
203 DIFF_PAIR cur( *aCurrent );
204
205 bool currentIsP = aPFirst;
206
207 int mask = aSolidsOnly ? ITEM::SOLID_T : ITEM::ANY_T;
208
209 do
210 {
211 LINE preWalk = ( currentIsP ? cur.PLine() : cur.NLine() );
212 LINE preShove = ( currentIsP ? cur.NLine() : cur.PLine() );
213 LINE postWalk;
214
215 if( !aNode->CheckColliding ( &preWalk, mask ) )
216 {
217 currentIsP = !currentIsP;
218
219 if( !aNode->CheckColliding( &preShove, mask ) )
220 break;
221 else
222 continue;
223 }
224
225 wf1 = walkaround.Route( preWalk, postWalk, false );
226
227 if( wf1 != WALKAROUND::DONE )
228 return false;
229
230 LINE postShove( preShove );
231
232 shove.ForceClearance( true, cur.Gap() - 2 * PNS_HULL_MARGIN );
233
235
236 sh1 = shove.ShoveObstacleLine( postWalk, preShove, postShove );
237
238 if( sh1 != SHOVE::SH_OK )
239 return false;
240
241 postWalk.Line().Simplify();
242 postShove.Line().Simplify();
243
244 cur.SetShape( postWalk.CLine(), postShove.CLine(), !currentIsP );
245
246 currentIsP = !currentIsP;
247
248 if( !aNode->CheckColliding( &postShove, mask ) )
249 break;
250
251 iter++;
252 }
253 while( iter < 3 );
254
255 if( iter == 3 )
256 return false;
257
258 aWalk.SetShape( cur.CP(), cur.CN() );
259
260 return true;
261}
262
263
264bool DIFF_PAIR_PLACER::tryWalkDp( NODE* aNode, DIFF_PAIR &aPair, bool aSolidsOnly )
265{
266 DIFF_PAIR best;
267 double bestScore = 100000000000000.0;
268
269 for( int attempt = 0; attempt <= 3; attempt++ )
270 {
271 DIFF_PAIR p;
272 NODE *tmp = m_currentNode->Branch();
273
274 bool pfirst = ( attempt & 1 ) ? true : false;
275 bool wind_cw = ( attempt & 2 ) ? true : false;
276
277 if( attemptWalk( tmp, &aPair, p, pfirst, wind_cw, aSolidsOnly ) )
278 {
279 // double len = p.TotalLength();
280 double cl = 1 + p.CoupledLength();
281 double skew = p.Skew();
282
283 double score = cl + fabs( skew ) * 3.0;
284
285 if( score < bestScore )
286 {
287 bestScore = score;
288 best = p;
289 }
290 }
291
292 delete tmp;
293 }
294
295 if( bestScore > 0.0 )
296 {
297 OPTIMIZER optimizer( m_currentNode );
298
299 aPair.SetShape( best );
300 optimizer.Optimize( &aPair );
301
302 return true;
303 }
304
305 return false;
306}
307
308
310{
311 if( !routeHead ( aP ) )
312 return false;
313
315
316 return m_fitOk;
317}
318
319
321{
322 switch( Settings().Mode() )
323 {
324 case RM_MarkObstacles:
325 return rhMarkObstacles( aP );
326 case RM_Walkaround:
327 return rhWalkOnly( aP );
328 case RM_Shove:
329 return rhShoveOnly( aP );
330 default:
331 break;
332 }
333
334 return false;
335}
336
337
339{
340 m_currentNode = m_shove->CurrentNode();
341
342 bool ok = routeHead( aP );
343
344 m_fitOk = false;
345
346 if( !ok )
347 return false;
348
349 if( !tryWalkDp( m_currentNode, m_currentTrace, true ) )
350 return false;
351
352 LINE pLine( m_currentTrace.PLine() );
353 LINE nLine( m_currentTrace.NLine() );
354 ITEM_SET head;
355
356 head.Add( &pLine );
357 head.Add( &nLine );
358
359 SHOVE::SHOVE_STATUS status = m_shove->ShoveMultiLines( head );
360
361 m_currentNode = m_shove->CurrentNode();
362
363 if( status == SHOVE::SH_OK )
364 {
365 m_currentNode = m_shove->CurrentNode();
366
369 {
370 m_fitOk = true;
371 }
372 }
373
374 return m_fitOk;
375}
376
377
379{
380 ITEM_SET t;
381
382 t.Add( &m_currentTrace.PLine() );
383 t.Add( &m_currentTrace.NLine() );
384
385 return t;
386}
387
388
390{
392
393 if( !m_idle )
394 Move( m_currentEnd, nullptr );
395}
396
397
398NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
399{
400 if( m_lastNode )
401 return m_lastNode;
402
403 return m_currentNode;
404}
405
406
408{
409 if( m_idle )
410 {
411 m_currentLayer = aLayer;
412 return true;
413 }
414 else if( m_chainedPlacement || !m_prevPair )
415 {
416 return false;
417 }
418 else if( !m_prevPair->PrimP() || ( m_prevPair->PrimP()->OfKind( ITEM::VIA_T ) &&
419 m_prevPair->PrimP()->Layers().Overlaps( aLayer ) ) )
420 {
421 m_currentLayer = aLayer;
424 Move( m_currentEnd, nullptr );
425 return true;
426 }
427
428 return false;
429}
430
431
433{
434 switch( aItem->Kind() )
435 {
436 case ITEM::LINE_T:
437 {
438 LINE* l = static_cast<LINE*>( aItem );
439
440 if( !l->PointCount() )
441 return OPT_VECTOR2I();
442 else
443 return l->CPoint( 0 );
444 }
445 case ITEM::VIA_T:
446 case ITEM::SOLID_T:
447 return aItem->Anchor( 0 );
448
449 case ITEM::ARC_T:
450 {
451 ARC* a = static_cast<ARC*>( aItem );
452
453 const JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
454 const JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
455
456 if( jA && jA->LinkCount() == 1 )
457 return a->Arc().GetP0();
458 else if( jB && jB->LinkCount() == 1 )
459 return a->Arc().GetP1();
460 else
461 return OPT_VECTOR2I();
462 }
463 case ITEM::SEGMENT_T:
464 {
465 SEGMENT* s = static_cast<SEGMENT*>( aItem );
466
467 const JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
468 const JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
469
470 if( jA && jA->LinkCount() == 1 )
471 return s->Seg().A;
472 else if( jB && jB->LinkCount() == 1 )
473 return s->Seg().B;
474 else
475 return OPT_VECTOR2I();
476 }
477
478 default:
479 return OPT_VECTOR2I();
480 }
481}
482
483
484
486 DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
487{
488 NET_HANDLE netP, netN;
489
490 bool result = aWorld->GetRuleResolver()->DpNetPair( aItem, netP, netN );
491
492 if( !result )
493 {
494 if( aErrorMsg )
495 {
496 *aErrorMsg = _( "Unable to find complementary differential pair "
497 "nets. Make sure the names of the nets belonging "
498 "to a differential pair end with either N/P or +/-." );
499 }
500 return false;
501 }
502
503 NET_HANDLE refNet = aItem->Net();
504 NET_HANDLE coupledNet = ( refNet == netP ) ? netN : netP;
505
506 OPT_VECTOR2I refAnchor = getDanglingAnchor( aWorld, aItem );
507 ITEM* primRef = aItem;
508
509 if( !refAnchor )
510 {
511 if( aErrorMsg )
512 {
513 *aErrorMsg = _( "Can't find a suitable starting point. If starting "
514 "from an existing differential pair make sure you are "
515 "at the end." );
516 }
517
518 return false;
519 }
520
521 std::set<ITEM*> coupledItems;
522
523 aWorld->AllItemsInNet( coupledNet, coupledItems );
524 double bestDist = std::numeric_limits<double>::max();
525 bool found = false;
526
527 for( ITEM* item : coupledItems )
528 {
529 if( item->Kind() == aItem->Kind() )
530 {
531 OPT_VECTOR2I anchor = getDanglingAnchor( aWorld, item );
532
533 if( !anchor )
534 continue;
535
536 double dist = ( *anchor - *refAnchor ).EuclideanNorm();
537
538 bool shapeMatches = true;
539
540 if( item->OfKind( ITEM::SOLID_T | ITEM::VIA_T ) && item->Layers() != aItem->Layers() )
541 {
542 shapeMatches = false;
543 }
544
545 if( dist < bestDist && shapeMatches )
546 {
547 found = true;
548 bestDist = dist;
549
550 if( refNet != netP )
551 {
552 aPair = DP_PRIMITIVE_PAIR ( item, primRef );
553 aPair.SetAnchors( *anchor, *refAnchor );
554 }
555 else
556 {
557 aPair = DP_PRIMITIVE_PAIR( primRef, item );
558 aPair.SetAnchors( *refAnchor, *anchor );
559 }
560 }
561 }
562 }
563
564 if( !found )
565 {
566 if( aErrorMsg )
567 {
568 *aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
569 "for coupled net \"%s\"." ),
570 aWorld->GetRuleResolver()->NetName( coupledNet ) );
571 }
572
573 return false;
574 }
575
576 return true;
577}
578
579
581{
582 return std::max( m_sizes.DiffPairViaGap(),
584}
585
586
588{
590}
591
592
593bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
594{
595 VECTOR2I p( aP );
596
597 setWorld( Router()->GetWorld() );
599
600 wxString err_msg;
601
602 if( !FindDpPrimitivePair( m_currentNode, aP, aStartItem, m_start, &err_msg ) )
603 {
604 Router()->SetFailureReason( err_msg );
605 return false;
606 }
607
608 m_netP = m_start.PrimP()->Net();
609 m_netN = m_start.PrimN()->Net();
610
611 m_currentStart = p;
612 m_currentEnd = p;
613 m_placingVia = false;
614 m_chainedPlacement = false;
615 m_currentTraceOk = false;
618
620
621 return true;
622}
623
624
626{
627 m_idle = false;
628 m_orthoMode = false;
629 m_currentEndItem = nullptr;
631
632 NODE* world = Router()->GetWorld();
633
634 world->KillChildren();
635 NODE* rootNode = world->Branch();
636
637 setWorld( rootNode );
638
639 m_lastNode = nullptr;
640 m_currentNode = rootNode;
641
642 m_shove = std::make_unique<SHOVE>( m_currentNode, Router() );
643}
644
645
647{
648 m_fitOk = false;
649
650 DP_GATEWAYS gwsEntry( gap() );
651 DP_GATEWAYS gwsTarget( gap() );
652
653 if( !m_prevPair )
655
657
658 DP_PRIMITIVE_PAIR target;
659
661 {
662 gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
663 m_snapOnTarget = true;
664 }
665 else
666 {
667 VECTOR2I fp;
668
669 if( !propagateDpHeadForces( aP, fp ) )
670 return false;
671
672 VECTOR2I midp, dirV;
673 m_prevPair->CursorOrientation( fp, midp, dirV );
674
675 VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp );
676
677 // compute 'leader point' distance from the cursor (project cursor position
678 // on the extension of the starting segment pair of the DP)
679 int lead_dist = ( fpProj - fp ).EuclideanNorm();
680
682
683 // far from the initial segment extension line -> allow a 45-degree obtuse turn
684 if( lead_dist > ( m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() ) / 2 )
685 {
686 gwsTarget.BuildForCursor( fp );
687 }
688 else
689 {
690 // close to the initial segment extension line -> keep straight part only, project
691 // as close as possible to the cursor.
692 gwsTarget.BuildForCursor( fpProj );
694 DIRECTION_45( dirV ) );
695 }
696
697 m_snapOnTarget = false;
698 }
699
702
703 bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace );
704
705 if( result )
706 {
707 m_currentTraceOk = true;
711
712 if( m_placingVia )
713 {
715 makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) );
716 }
717 else
718 {
720 }
721
722 return true;
723 }
724
725 return m_currentTraceOk;
726}
727
728
729bool DIFF_PAIR_PLACER::Move( const VECTOR2I& aP , ITEM* aEndItem )
730{
731 m_currentEndItem = aEndItem;
732 m_fitOk = false;
733
734 delete m_lastNode;
735 m_lastNode = nullptr;
736
737 bool retval = route( aP );
738
739 NODE* latestNode = m_currentNode;
740 m_lastNode = latestNode->Branch();
741
742 assert( m_lastNode != nullptr );
743 m_currentEnd = aP;
744
746
747 return retval;
748}
749
750
752{
753 m_sizes = aSizes;
754
755 if( !m_idle )
756 {
759
761 {
764 }
765 }
766}
767
768
769bool DIFF_PAIR_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
770{
771 if( !m_fitOk && !Settings().AllowDRCViolations() )
772 return false;
773
775 return false;
776
777 if( m_currentTrace.CP().SegmentCount() > 1 )
779
780 TOPOLOGY topo( m_lastNode );
781
782 if( !m_snapOnTarget && !m_currentTrace.EndsWithVias() && !aForceFinish &&
783 !Settings().GetFixAllSegments() )
784 {
787
788 if( newP.SegmentCount() > 1 && newN.SegmentCount() > 1 )
789 {
790 newP.Remove( -1, -1 );
791 newN.Remove( -1, -1 );
792 }
793
794 m_currentTrace.SetShape( newP, newN );
795 }
796
798 {
801 m_chainedPlacement = false;
802 }
803 else
804 {
805 m_chainedPlacement = !m_snapOnTarget && !aForceFinish;
806 }
807
808 LINE lineP( m_currentTrace.PLine() );
809 LINE lineN( m_currentTrace.NLine() );
810
811 m_lastNode->Add( lineP );
812 m_lastNode->Add( lineN );
813
814 topo.SimplifyLine( &lineP );
815 topo.SimplifyLine( &lineN );
816
818
820 m_placingVia = false;
821
822 if( m_snapOnTarget || aForceFinish )
823 {
824 m_idle = true;
825 return true;
826 }
827 else
828 {
830 return false;
831 }
832}
833
834
836{
838 return true;
839}
840
841
843{
845}
846
847
849{
850 if( m_lastNode )
852
853 m_lastNode = nullptr;
854 m_currentNode = nullptr;
855 return true;
856}
857
858
859void DIFF_PAIR_PLACER::GetModifiedNets( std::vector<NET_HANDLE> &aNets ) const
860{
861 aNets.push_back( m_netP );
862 aNets.push_back( m_netN );
863}
864
865
867{
868 SHAPE_LINE_CHAIN ratLineN, ratLineP;
869 TOPOLOGY topo( m_lastNode );
870
871 if( topo.LeadingRatLine( &m_currentTrace.PLine(), ratLineP ) )
873
874 if( topo.LeadingRatLine ( &m_currentTrace.NLine(), ratLineN ) )
876}
877
878
879const std::vector<NET_HANDLE> DIFF_PAIR_PLACER::CurrentNets() const
880{
881 std::vector<NET_HANDLE> rv;
882 rv.push_back( m_netP );
883 rv.push_back( m_netN );
884 return rv;
885}
886
887}
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:37
bool IsDiagonal() const
Returns true if the direction is diagonal (e.g.
Definition: direction45.h:213
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
ROUTER * Router() const
Return current router settings.
Definition: pns_algo_base.h:54
ROUTER * m_router
Definition: pns_algo_base.h:87
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
SHAPE_ARC & Arc()
Definition: pns_arc.h:115
NODE * CurrentNode(bool aLoopsRemoved=false) const override
Return the most recent world state.
void SetOrthoMode(bool aOrthoMode) override
Function SetOrthoMode()
bool HasPlacedAnything() const override
NODE * m_world
current routing start point (end of tail, beginning of head)
bool tryWalkDp(NODE *aNode, DIFF_PAIR &aPair, bool aSolidsOnly)
route step, walk around mode
bool propagateDpHeadForces(const VECTOR2I &aP, VECTOR2I &aNewP)
bool rhMarkObstacles(const VECTOR2I &aP)
int m_viaDiameter
current via drill
std::optional< DP_PRIMITIVE_PAIR > m_prevPair
current algorithm iteration
bool ToggleVia(bool aEnabled) override
Enable/disable a via at the end of currently routed trace.
bool route(const VECTOR2I &aP)
Re-route the current track to point aP.
int m_iteration
pointer to world to search colliding items
bool rhShoveOnly(const VECTOR2I &aP)
route step, mark obstacles mode
bool Start(const VECTOR2I &aP, ITEM *aStartItem) override
Start routing a single track at point aP, taking item aStartItem as anchor (unless NULL).
const ITEM_SET Traces() override
Return the complete routed line, as a single-member ITEM_SET.
void GetModifiedNets(std::vector< NET_HANDLE > &aNets) const override
Function GetModifiedNets.
int m_viaDrill
current track width
void FlipPosture() override
Toggle the current posture (straight/diagonal) of the trace head.
DIFF_PAIR_PLACER(ROUTER *aRouter)
bool attemptWalk(NODE *aNode, DIFF_PAIR *aCurrent, DIFF_PAIR &aWalk, bool aPFirst, bool aWindCw, bool aSolidsOnly)
void setWorld(NODE *aWorld)
Set the board to route.
NODE * m_currentNode
Postprocessed world state (including marked collisions & removed loops)
void initPlacement()
Initialize placement of a new line with given parameters.
const std::vector< NET_HANDLE > CurrentNets() const override
Return the net of currently routed track.
bool routeHead(const VECTOR2I &aP)
void UpdateSizes(const SIZES_SETTINGS &aSizes) override
Perform on-the-fly update of the width, via diameter & drill size from a settings class.
static bool FindDpPrimitivePair(NODE *aWorld, const VECTOR2I &aP, ITEM *aItem, DP_PRIMITIVE_PAIR &aPair, wxString *aErrorMsg=nullptr)
bool rhWalkOnly(const VECTOR2I &aP)
route step, shove mode
bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Move the end of the currently routed trace to the point aP, taking aEndItem as anchor (if not NULL).
bool FixRoute(const VECTOR2I &aP, ITEM *aEndItem, bool aForceFinish) override
Commit the currently routed track to the parent node, taking aP as the final end point and aEndItem a...
bool m_placingVia
current via diameter
void updateLeadingRatLine()
Draw the "leading" ratsnest line, which connects the end of currently routed track and the nearest ye...
const VIA makeVia(const VECTOR2I &aP, NET_HANDLE aNet)
SIZES_SETTINGS m_sizes
Are we placing a via?
bool SetLayer(int aLayer) override
Set the current routing layer.
std::unique_ptr< SHOVE > m_shove
Current world state.
Basic class for a differential pair.
void AppendVias(const VIA &aViaP, const VIA &aViaN)
const SHAPE_LINE_CHAIN & CN() const
DP_PRIMITIVE_PAIR EndingPrimitives()
double CoupledLength() const
double Skew() const
void SetViaDiameter(int aDiameter)
void SetViaDrill(int aDrill)
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
int Gap() const
bool EndsWithVias() const
void SetGap(int aGap)
void SetNets(NET_HANDLE aP, NET_HANDLE aN)
const SHAPE_LINE_CHAIN & CP() const
void SetWidth(int aWidth)
A set of gateways calculated for the cursor or starting/ending primitive pair.
void SetFitVias(bool aEnable, int aDiameter=0, int aViaGap=-1)
void BuildFromPrimitivePair(const DP_PRIMITIVE_PAIR &aPair, bool aPreferDiagonal)
bool FitGateways(DP_GATEWAYS &aEntry, DP_GATEWAYS &aTarget, bool aPrefDiagonal, DIFF_PAIR &aDp)
void FilterByOrientation(int aAngleMask, DIRECTION_45 aRefOrientation)
void BuildForCursor(const VECTOR2I &aCursorPos)
Store starting/ending primitives (pads, vias or segments) for a differential pair.
ITEM * PrimN() const
ITEM * PrimP() const
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
Base class for PNS router board items.
Definition: pns_item.h:97
virtual NET_HANDLE Net() const
Definition: pns_item.h:193
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:166
void SetLayer(int aLayer)
Definition: pns_item.h:198
@ SEGMENT_T
Definition: pns_item.h:105
const LAYER_RANGE & Layers() const
Definition: pns_item.h:195
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:236
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
int LinkCount(int aMask=-1) const
Definition: pns_joint.h:289
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
const VECTOR2I & CPoint(int aIdx) const
Definition: pns_line.h:144
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:136
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:135
VIA & Via()
Definition: pns_line.h:193
int PointCount() const
Definition: pns_line.h:139
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
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Return the pre-set worst case clearance between any pair of items.
Definition: pns_node.cpp:129
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:1212
std::optional< OBSTACLE > OPT_OBSTACLE
Definition: pns_node.h:217
RULE_RESOLVER * GetRuleResolver() const
Return the number of joints.
Definition: pns_node.h:245
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:663
void AllItemsInNet(NET_HANDLE aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1502
void KillChildren()
Definition: pns_node.cpp:1496
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
Definition: pns_optimizer.h:95
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
virtual void DisplayRatline(const SHAPE_LINE_CHAIN &aRatline, NET_HANDLE aNetCode)=0
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:218
void SetFailureReason(const wxString &aReason)
Definition: pns_router.h:213
void CommitRouting()
Definition: pns_router.cpp:896
NODE * GetWorld() const
Definition: pns_router.h:164
virtual bool DpNetPair(const ITEM *aItem, NET_HANDLE &aNetP, NET_HANDLE &aNetN)=0
virtual wxString NetName(NET_HANDLE aNet)=0
const SEG & Seg() const
Definition: pns_segment.h:84
The actual Push and Shove algorithm.
Definition: pns_shove.h:46
SHOVE_STATUS ShoveObstacleLine(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine)
Definition: pns_shove.cpp:394
void ForceClearance(bool aEnabled, int aClearance)
Definition: pns_shove.h:69
VIATYPE ViaType() const
int GetDiffPairHoleToHole() const
bool LeadingRatLine(const LINE *aTrack, SHAPE_LINE_CHAIN &aRatLine)
bool SimplifyLine(LINE *aLine)
const VECTOR2I & Pos() const
Definition: pns_via.h:128
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_via.h:168
int Diameter() const
Definition: pns_via.h:142
void SetDiameter(int aDiameter)
Definition: pns_via.h:144
void SetPos(const VECTOR2I &aPos)
Definition: pns_via.h:130
void SetIterationLimit(const int aIterLimit)
void SetSolidsOnly(bool aSolidsOnly)
WALKAROUND_STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.cpp:312
const VECTOR2I & GetP1() const
Definition: shape_arc.h:114
const VECTOR2I & GetP0() const
Definition: shape_arc.h:113
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Simplify(int aMaxError=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
#define _(s)
Push and Shove diff pair dimensions (gap) settings dialog.
OPT_VECTOR2I getDanglingAnchor(NODE *aNode, ITEM *aItem)
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
@ RM_Walkaround
Only walk around.
@ RM_Shove
Only shove.
void * NET_HANDLE
Definition: pns_item.h:54
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:308
#define PNS_HULL_MARGIN
Definition: pns_line.h:44
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:128