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