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 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_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#include "pns_utils.h"
31
32namespace PNS {
33
35 PLACEMENT_ALGO( aRouter )
36{
38 m_chainedPlacement = false;
39 m_initialDiagonal = false;
40 m_startDiagonal = false;
41 m_fitOk = false;
42 m_netP = nullptr;
43 m_netN = nullptr;
44 m_iteration = 0;
45 m_world = nullptr;
46 m_shove = nullptr;
47 m_currentNode = nullptr;
48 m_lastNode = nullptr;
49 m_lastFixNode = nullptr;
50 m_placingVia = false;
51 m_viaDiameter = 0;
52 m_viaDrill = 0;
55 m_startsOnVia = false;
56 m_orthoMode = false;
57 m_snapOnTarget = false;
58 m_currentEndItem = nullptr;
59 m_currentTraceOk = false;
60 m_idle = true;
61}
62
64{}
65
66
68{
69 m_world = aWorld;
70}
71
72
74{
76
77 VIA v( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), aNet, m_sizes.ViaType() );
78
79 return v;
80}
81
82
83void DIFF_PAIR_PLACER::SetOrthoMode ( bool aOrthoMode )
84{
85 m_orthoMode = aOrthoMode;
86
87 if( !m_idle )
88 Move( m_currentEnd, nullptr );
89}
90
91
92bool DIFF_PAIR_PLACER::ToggleVia( bool aEnabled )
93{
94 m_placingVia = aEnabled;
95
96 if( !m_idle )
97 Move( m_currentEnd, nullptr );
98
99 return true;
100}
101
102
104{
105 if( !routeHead( aP ) )
106 return false;
107
108 bool collP = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.PLine() ) );
109 bool collN = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.NLine() ) );
110
111 m_fitOk = !( collP || collN ) ;
112
113 return m_fitOk;
114}
115
116
118{
119 VIA virtHead = makeVia( aP, nullptr );
120
121 if( m_placingVia )
122 {
123 virtHead.SetDiameter( 0, viaGap() + 2 * virtHead.Diameter( 0 ) );
124 }
125 else
126 {
127 virtHead.SetLayer( m_currentLayer );
128 virtHead.SetDiameter( 0, m_sizes.DiffPairGap() + 2 * m_sizes.DiffPairWidth() );
129 }
130
131 bool solidsOnly = true;
132
133 if( Settings().Mode() == RM_MarkObstacles )
134 {
135 aNewP = aP;
136 return true;
137 }
138 else if( Settings().Mode() == RM_Walkaround )
139 {
140 solidsOnly = false;
141 }
142
143 // fixme: I'm too lazy to do it well. Circular approximaton will do for the moment.
144
145 // Note: this code is lifted from VIA::PushoutForce and then optimized for this use case and to
146 // check proper clearances to the diff pair line. It can be removed if some specialized
147 // pushout for traces / diff pairs is implemented. Just calling VIA::PushoutForce does not work
148 // as the via may have different resolved clearance to items than the diff pair should.
149 int maxIter = 40;
150 int iter = 0;
151 bool collided = false;
152 VECTOR2I force, totalForce;
153 std::set<const ITEM*> handled;
154
155 while( iter < maxIter )
156 {
157 NODE::OPT_OBSTACLE obs = m_currentNode->CheckColliding( &virtHead, solidsOnly ?
159 ITEM::ANY_T );
160 if( !obs || handled.count( obs->m_item ) )
161 break;
162
163 int clearance = m_currentNode->GetClearance( obs->m_item, &m_currentTrace.PLine(), false );
164 VECTOR2I layerForce;
165 collided = false;
166
167 for( int viaLayer : virtHead.RelevantShapeLayers( obs->m_item ) )
168 {
169 collided |= obs->m_item->Shape( viaLayer )->Collide( virtHead.Shape( viaLayer ),
170 clearance, &layerForce );
171
172 if( layerForce.SquaredEuclideanNorm() > force.SquaredEuclideanNorm() )
173 force = layerForce;
174 }
175
176 if( collided )
177 {
178 totalForce += force;
179 virtHead.SetPos( virtHead.Pos() + force );
180 }
181
182 handled.insert( obs->m_item );
183
184 iter++;
185 }
186
187 bool succeeded = ( !collided || iter != maxIter );
188
189 if( succeeded )
190 {
191 aNewP = aP + force;
192 return true;
193 }
194
195 return false;
196}
197
198
200 bool aPFirst, bool aWindCw, bool aSolidsOnly )
201{
202 WALKAROUND walkaround( aNode, Router() );
204
205 walkaround.SetSolidsOnly( aSolidsOnly );
206 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
208
209 SHOVE shove( aNode, Router() );
210 LINE walkP, walkN;
211
212 aWalk = *aCurrent;
213
214 int iter = 0;
215
216 DIFF_PAIR cur( *aCurrent );
217
218 bool currentIsP = aPFirst;
219
220 int mask = aSolidsOnly ? ITEM::SOLID_T : ITEM::ANY_T;
221
222 do
223 {
224 LINE preWalk = ( currentIsP ? cur.PLine() : cur.NLine() );
225 LINE preShove = ( currentIsP ? cur.NLine() : cur.PLine() );
226 LINE postWalk;
227
228 if( !aNode->CheckColliding ( &preWalk, mask ) )
229 {
230 currentIsP = !currentIsP;
231
232 if( !aNode->CheckColliding( &preShove, mask ) )
233 break;
234 else
235 continue;
236 }
237
238 auto wf1 = walkaround.Route( preWalk );
239
240 if( wf1.status[ WALKAROUND::WP_SHORTEST ] != WALKAROUND::ST_DONE )
241 return false;
242
243 postWalk = wf1.lines[ WALKAROUND::WP_SHORTEST ];
244
245 LINE postShove( preShove );
246
247 shove.ForceClearance( true, cur.Gap() - 2 * PNS_HULL_MARGIN );
248
249 bool sh1;
250
251 sh1 = shove.ShoveObstacleLine( postWalk, preShove, postShove );
252
253 if( !sh1 )
254 return false;
255
256 postWalk.Line().Simplify();
257 postShove.Line().Simplify();
258
259 cur.SetShape( postWalk.CLine(), postShove.CLine(), !currentIsP );
260
261 currentIsP = !currentIsP;
262
263 if( !aNode->CheckColliding( &postShove, mask ) )
264 break;
265
266 iter++;
267 }
268 while( iter < 3 );
269
270 if( iter == 3 )
271 return false;
272
273 aWalk.SetShape( cur.CP(), cur.CN() );
274
275 return true;
276}
277
278
279bool DIFF_PAIR_PLACER::tryWalkDp( NODE* aNode, DIFF_PAIR &aPair, bool aSolidsOnly )
280{
281 DIFF_PAIR best;
282 double bestScore = 100000000000000.0;
283
284 for( int attempt = 0; attempt <= 3; attempt++ )
285 {
286 DIFF_PAIR p;
287 NODE *tmp = m_currentNode->Branch();
288
289 bool pfirst = ( attempt & 1 ) ? true : false;
290 bool wind_cw = ( attempt & 2 ) ? true : false;
291
292 if( attemptWalk( tmp, &aPair, p, pfirst, wind_cw, aSolidsOnly ) )
293 {
294 // double len = p.TotalLength();
295 double cl = 1 + p.CoupledLength();
296 double skew = p.Skew();
297
298 double score = cl + fabs( skew ) * 3.0;
299
300 if( score < bestScore )
301 {
302 bestScore = score;
303 best = p;
304 }
305 }
306
307 delete tmp;
308 }
309
310 if( bestScore > 0.0 )
311 {
312 OPTIMIZER optimizer( m_currentNode );
313
314 aPair.SetShape( best );
315 optimizer.Optimize( &aPair );
316
317 return true;
318 }
319
320 return false;
321}
322
323
325{
326 if( !routeHead ( aP ) )
327 return false;
328
330
331 return m_fitOk;
332}
333
334
336{
337 switch( Settings().Mode() )
338 {
339 case RM_MarkObstacles:
340 return rhMarkObstacles( aP );
341 case RM_Walkaround:
342 return rhWalkOnly( aP );
343 case RM_Shove:
344 return rhShoveOnly( aP );
345 default:
346 break;
347 }
348
349 return false;
350}
351
352
354{
355 m_currentNode = m_shove->CurrentNode();
356
357 bool ok = routeHead( aP );
358
359 m_fitOk = false;
360
361 if( !ok )
362 return false;
363
364 if( !tryWalkDp( m_currentNode, m_currentTrace, true ) )
365 return false;
366
367 LINE pLine( m_currentTrace.PLine() );
368 LINE nLine( m_currentTrace.NLine() );
369 ITEM_SET head;
370
371 m_shove->ClearHeads();
372 m_shove->AddHeads( pLine );
373 m_shove->AddHeads( nLine );
374
375 SHOVE::SHOVE_STATUS status = m_shove->Run();
376
377 m_currentNode = m_shove->CurrentNode();
378
379 if( status == SHOVE::SH_OK )
380 {
381 m_currentNode = m_shove->CurrentNode();
382
383 if( m_shove->HeadsModified( 0 ))
384 pLine = m_shove->GetModifiedHead(0);
385
386 if( m_shove->HeadsModified( 1 ))
387 nLine = m_shove->GetModifiedHead(1);
388
391 {
392 m_fitOk = true;
393 }
394 }
395 else
396 {
397 // bring back previous state
398 m_currentTrace.SetShape( pLine.CLine(), nLine.CLine() );
399 }
400
401
402 return m_fitOk;
403}
404
405
407{
408 ITEM_SET t;
409
410 t.Add( &m_currentTrace.PLine() );
411 t.Add( &m_currentTrace.NLine() );
412
413 return t;
414}
415
416
418{
420
421 if( !m_idle )
422 Move( m_currentEnd, nullptr );
423}
424
425
426NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
427{
428 if( m_lastNode )
429 return m_lastNode;
430
431 return m_currentNode;
432}
433
434
436{
437 if( m_idle )
438 {
439 m_currentLayer = aLayer;
440 return true;
441 }
442 else if( m_chainedPlacement || !m_prevPair )
443 {
444 return false;
445 }
446 else if( !m_prevPair->PrimP() || ( m_prevPair->PrimP()->OfKind( ITEM::VIA_T ) &&
447 m_prevPair->PrimP()->Layers().Overlaps( aLayer ) ) )
448 {
449 m_currentLayer = aLayer;
452 Move( m_currentEnd, nullptr );
453 return true;
454 }
455
456 return false;
457}
458
459
461{
462 switch( aItem->Kind() )
463 {
464 case ITEM::LINE_T:
465 {
466 LINE* l = static_cast<LINE*>( aItem );
467
468 if( !l->PointCount() )
469 return OPT_VECTOR2I();
470 else
471 return l->CPoint( 0 );
472 }
473 case ITEM::VIA_T:
474 case ITEM::SOLID_T:
475 return aItem->Anchor( 0 );
476
477 case ITEM::ARC_T:
478 {
479 ARC* a = static_cast<ARC*>( aItem );
480
481 const JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
482 const JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
483
484 if( jA && jA->LinkCount() == 1 )
485 return a->Arc().GetP0();
486 else if( jB && jB->LinkCount() == 1 )
487 return a->Arc().GetP1();
488 else
489 return OPT_VECTOR2I();
490 }
491 case ITEM::SEGMENT_T:
492 {
493 SEGMENT* s = static_cast<SEGMENT*>( aItem );
494
495 const JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
496 const JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
497
498 if( jA && jA->LinkCount() == 1 )
499 return s->Seg().A;
500 else if( jB && jB->LinkCount() == 1 )
501 return s->Seg().B;
502 else
503 return OPT_VECTOR2I();
504 }
505
506 default:
507 return OPT_VECTOR2I();
508 }
509}
510
511
512
514 DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
515{
516 NET_HANDLE netP, netN;
517
518 bool result = aWorld->GetRuleResolver()->DpNetPair( aItem, netP, netN );
519
520 if( !result )
521 {
522 if( aErrorMsg )
523 {
524 *aErrorMsg = _( "Unable to find complementary differential pair "
525 "nets. Make sure the names of the nets belonging "
526 "to a differential pair end with either N/P or +/-." );
527 }
528 return false;
529 }
530
531 NET_HANDLE refNet = aItem->Net();
532 NET_HANDLE coupledNet = ( refNet == netP ) ? netN : netP;
533
534 OPT_VECTOR2I refAnchor = getDanglingAnchor( aWorld, aItem );
535 ITEM* primRef = aItem;
536
537 if( !refAnchor )
538 {
539 if( aErrorMsg )
540 {
541 *aErrorMsg = _( "Can't find a suitable starting point. If starting "
542 "from an existing differential pair make sure you are "
543 "at the end." );
544 }
545
546 return false;
547 }
548
549 std::set<ITEM*> coupledItems;
550
551 aWorld->AllItemsInNet( coupledNet, coupledItems );
552 double bestDist = std::numeric_limits<double>::max();
553 bool found = false;
554
555 for( ITEM* item : coupledItems )
556 {
557 if( item->Kind() == aItem->Kind() )
558 {
559 OPT_VECTOR2I anchor = getDanglingAnchor( aWorld, item );
560
561 if( !anchor )
562 continue;
563
564 double dist = ( *anchor - *refAnchor ).EuclideanNorm();
565
566 bool shapeMatches = true;
567
568 if( item->OfKind( ITEM::SOLID_T | ITEM::VIA_T ) && item->Layers() != aItem->Layers() )
569 {
570 shapeMatches = false;
571 }
572
573 if( dist < bestDist && shapeMatches )
574 {
575 found = true;
576 bestDist = dist;
577
578 if( refNet != netP )
579 {
580 aPair = DP_PRIMITIVE_PAIR ( item, primRef );
581 aPair.SetAnchors( *anchor, *refAnchor );
582 }
583 else
584 {
585 aPair = DP_PRIMITIVE_PAIR( primRef, item );
586 aPair.SetAnchors( *refAnchor, *anchor );
587 }
588 }
589 }
590 }
591
592 if( !found )
593 {
594 if( aErrorMsg )
595 {
596 *aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
597 "for coupled net \"%s\"." ),
598 aWorld->GetRuleResolver()->NetName( coupledNet ) );
599 }
600
601 return false;
602 }
603
604 return true;
605}
606
607
609{
610 return std::max( m_sizes.DiffPairViaGap(),
612}
613
614
616{
618}
619
620
621bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
622{
623 VECTOR2I p( aP );
624
625 setWorld( Router()->GetWorld() );
627
628 wxString err_msg;
629
630 if( !FindDpPrimitivePair( m_currentNode, aP, aStartItem, m_start, &err_msg ) )
631 {
632 Router()->SetFailureReason( err_msg );
633 return false;
634 }
635
636 m_netP = m_start.PrimP()->Net();
637 m_netN = m_start.PrimN()->Net();
638
639 m_currentStart = p;
640 m_currentEnd = p;
641 m_placingVia = false;
642 m_chainedPlacement = false;
643 m_currentTraceOk = false;
646 m_lastFixNode = nullptr;
647
649
650 return true;
651}
652
653
655{
656 m_idle = false;
657 m_orthoMode = false;
658 m_currentEndItem = nullptr;
660
661 NODE* world = Router()->GetWorld();
662
663 world->KillChildren();
664 NODE* rootNode = world->Branch();
665
666 setWorld( rootNode );
667
668 m_lastNode = nullptr;
669 m_currentNode = rootNode;
670
671 m_shove = std::make_unique<SHOVE>( m_currentNode, Router() );
672}
673
674
676{
677 m_fitOk = false;
678
679 DP_GATEWAYS gwsEntry( gap() );
680 DP_GATEWAYS gwsTarget( gap() );
681
682 if( !m_prevPair )
684
686
687 DP_PRIMITIVE_PAIR target;
688
690 {
691 gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
692 m_snapOnTarget = true;
693 }
694 else
695 {
696 VECTOR2I fp;
697
698 if( !propagateDpHeadForces( aP, fp ) )
699 return false;
700
701 VECTOR2I midp, dirV;
702 m_prevPair->CursorOrientation( fp, midp, dirV );
703
704 VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp );
705
706 // compute 'leader point' distance from the cursor (project cursor position
707 // on the extension of the starting segment pair of the DP)
708 int lead_dist = ( fpProj - fp ).EuclideanNorm();
709
711
712 // far from the initial segment extension line -> allow a 45-degree obtuse turn
713 if( lead_dist > ( m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() ) / 2 )
714 {
715 gwsTarget.BuildForCursor( fp );
716 }
717 else
718 {
719 // close to the initial segment extension line -> keep straight part only, project
720 // as close as possible to the cursor.
721 gwsTarget.BuildForCursor( fpProj );
723 DIRECTION_45( dirV ) );
724 }
725
726 m_snapOnTarget = false;
727 }
728
731
732 bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace );
733
734 if( result )
735 {
736 m_currentTraceOk = true;
740
741 if( m_placingVia )
742 {
744 makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) );
745 }
746 else
747 {
749 }
750
751 return true;
752 }
753
754 return m_currentTraceOk;
755}
756
757
758bool DIFF_PAIR_PLACER::Move( const VECTOR2I& aP , ITEM* aEndItem )
759{
760 m_currentEndItem = aEndItem;
761 m_fitOk = false;
762
763 delete m_lastNode;
764 m_lastNode = nullptr;
765
766 bool retval = route( aP );
767
768 NODE* latestNode = m_currentNode;
769 m_lastNode = latestNode->Branch();
770
771 assert( m_lastNode != nullptr );
772 m_currentEnd = aP;
773
775
776 return retval;
777}
778
779
781{
782 m_sizes = aSizes;
783
784 if( !m_idle )
785 {
788
790 {
793 }
794 }
795}
796
797
798bool DIFF_PAIR_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
799{
800 if( !m_fitOk && !Settings().AllowDRCViolations() )
801 return false;
802
804 return false;
805
806 if( m_currentTrace.CP().SegmentCount() > 1 )
808
809 TOPOLOGY topo( m_lastNode );
810
811 if( !m_snapOnTarget && !m_currentTrace.EndsWithVias() && !aForceFinish &&
812 !Settings().GetFixAllSegments() )
813 {
816
817 if( newP.SegmentCount() > 1 && newN.SegmentCount() > 1 )
818 {
819 newP.Remove( -1, -1 );
820 newN.Remove( -1, -1 );
821 }
822
823 m_currentTrace.SetShape( newP, newN );
824 }
825
827 {
830 m_chainedPlacement = false;
831 }
832 else
833 {
834 m_chainedPlacement = !m_snapOnTarget && !aForceFinish;
835 }
836
837 LINE lineP( m_currentTrace.PLine() );
838 LINE lineN( m_currentTrace.NLine() );
839
840 m_lastNode->Add( lineP );
841 m_lastNode->Add( lineN );
842
843 topo.SimplifyLine( &lineP );
844 topo.SimplifyLine( &lineN );
845
848
849 // avoid an use-after-free error (CommitPlacement calls NODE::Commit which will invalidate the shove heads state. Need to rethink the memory management).
850 if( Settings().Mode() == RM_Shove )
851 m_shove = std::make_unique<SHOVE>( m_world, Router() );
852
854 m_placingVia = false;
855 m_lastFixNode = nullptr;
856
857 if( m_snapOnTarget || aForceFinish )
858 {
859 m_idle = true;
860 return true;
861 }
862 else
863 {
865 return false;
866 }
867}
868
869
871{
873 m_lastNode = nullptr;
874 return true;
875}
876
877
879{
881}
882
883
885{
886 if( m_lastFixNode )
888
889 m_lastFixNode = nullptr;
890 m_lastNode = nullptr;
891 m_currentNode = nullptr;
892 return true;
893}
894
895
896void DIFF_PAIR_PLACER::GetModifiedNets( std::vector<NET_HANDLE> &aNets ) const
897{
898 aNets.push_back( m_netP );
899 aNets.push_back( m_netN );
900}
901
902
904{
905 SHAPE_LINE_CHAIN ratLineN, ratLineP;
906 TOPOLOGY topo( m_lastNode );
907
908 if( topo.LeadingRatLine( &m_currentTrace.PLine(), ratLineP ) )
910
911 if( topo.LeadingRatLine ( &m_currentTrace.NLine(), ratLineN ) )
913}
914
915
916const std::vector<NET_HANDLE> DIFF_PAIR_PLACER::CurrentNets() const
917{
918 std::vector<NET_HANDLE> rv;
919 rv.push_back( m_netP );
920 rv.push_back( m_netN );
921 return rv;
922}
923
924}
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
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:33
Base class for PNS router board items.
Definition: pns_item.h:98
const PNS_LAYER_RANGE & Layers() const
Definition: pns_item.h:212
virtual NET_HANDLE Net() const
Definition: pns_item.h:210
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:173
std::set< int > RelevantShapeLayers(const ITEM *aOther) const
Returns the set of layers on which either this or the other item can have a unique shape.
Definition: pns_item.cpp:94
void SetLayer(int aLayer)
Definition: pns_item.h:215
@ SEGMENT_T
Definition: pns_item.h:107
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:268
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:318
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:62
const VECTOR2I & CPoint(int aIdx) const
Definition: pns_line.h:146
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:138
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:137
VIA & Via()
Definition: pns_line.h:198
int PointCount() const
Definition: pns_line.h:141
Keep the router "world" - i.e.
Definition: pns_node.h:232
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:1268
std::optional< OBSTACLE > OPT_OBSTACLE
Definition: pns_node.h:242
RULE_RESOLVER * GetRuleResolver() const
Return the number of joints.
Definition: pns_node.h:270
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:665
void AllItemsInNet(NET_HANDLE aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1555
void KillChildren()
Definition: pns_node.cpp:1549
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:232
void SetFailureReason(const wxString &aReason)
Definition: pns_router.h:227
void CommitRouting()
Definition: pns_router.cpp:921
NODE * GetWorld() const
Definition: pns_router.h:178
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:93
The actual Push and Shove algorithm.
Definition: pns_shove.h:46
void ForceClearance(bool aEnabled, int aClearance)
Definition: pns_shove.h:89
bool ShoveObstacleLine(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine)
Definition: pns_shove.cpp:501
VIATYPE ViaType() const
int GetDiffPairHoleToHole() const
bool LeadingRatLine(const LINE *aTrack, SHAPE_LINE_CHAIN &aRatLine)
bool SimplifyLine(LINE *aLine)
int Diameter(int aLayer) const
Definition: pns_via.h:196
void SetDiameter(int aLayer, int aDiameter)
Definition: pns_via.h:203
const VECTOR2I & Pos() const
Definition: pns_via.h:180
const SHAPE * Shape(int aLayer) const override
Return the geometrical shape of the item.
Definition: pns_via.h:234
void SetPos(const VECTOR2I &aPos)
Definition: pns_via.h:182
void SetIterationLimit(const int aIterLimit)
void SetSolidsOnly(bool aSolidsOnly)
STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
void SetAllowedPolicies(std::vector< WALK_POLICY > aPolicies)
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
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:422
const VECTOR2I & GetP1() const
Definition: shape_arc.h:117
const VECTOR2I & GetP0() const
Definition: shape_arc.h:116
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Simplify(int aTolerance=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.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition: vector2d.h:307
#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:55
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:344
#define PNS_HULL_MARGIN
Definition: pns_line.h:45
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
int clearance