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( 0, viaGap() + 2 * virtHead.Diameter( 0 ) );
122 }
123 else
124 {
125 virtHead.SetLayer( m_currentLayer );
126 virtHead.SetDiameter( 0, m_sizes.DiffPairGap() + 2 * m_sizes.DiffPairWidth() );
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 VECTOR2I layerForce;
163 collided = false;
164
165 for( int viaLayer : virtHead.RelevantShapeLayers( obs->m_item ) )
166 {
167 collided |= obs->m_item->Shape( viaLayer )->Collide( virtHead.Shape( viaLayer ),
168 clearance, &layerForce );
169
170 if( layerForce.SquaredEuclideanNorm() > force.SquaredEuclideanNorm() )
171 force = layerForce;
172 }
173
174 if( collided )
175 {
176 totalForce += force;
177 virtHead.SetPos( virtHead.Pos() + force );
178 }
179
180 handled.insert( obs->m_item );
181
182 iter++;
183 }
184
185 bool succeeded = ( !collided || iter != maxIter );
186
187 if( succeeded )
188 {
189 aNewP = aP + force;
190 return true;
191 }
192
193 return false;
194}
195
196
198 bool aPFirst, bool aWindCw, bool aSolidsOnly )
199{
200 WALKAROUND walkaround( aNode, Router() );
202
203 walkaround.SetSolidsOnly( aSolidsOnly );
204 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
206
207 SHOVE shove( aNode, Router() );
208 LINE walkP, walkN;
209
210 aWalk = *aCurrent;
211
212 int iter = 0;
213
214 DIFF_PAIR cur( *aCurrent );
215
216 bool currentIsP = aPFirst;
217
218 int mask = aSolidsOnly ? ITEM::SOLID_T : ITEM::ANY_T;
219
220 do
221 {
222 LINE preWalk = ( currentIsP ? cur.PLine() : cur.NLine() );
223 LINE preShove = ( currentIsP ? cur.NLine() : cur.PLine() );
224 LINE postWalk;
225
226 if( !aNode->CheckColliding ( &preWalk, mask ) )
227 {
228 currentIsP = !currentIsP;
229
230 if( !aNode->CheckColliding( &preShove, mask ) )
231 break;
232 else
233 continue;
234 }
235
236 auto wf1 = walkaround.Route( preWalk );
237
238 if( wf1.status[ WALKAROUND::WP_SHORTEST ] != WALKAROUND::ST_DONE )
239 return false;
240
241 postWalk = wf1.lines[ WALKAROUND::WP_SHORTEST ];
242
243 LINE postShove( preShove );
244
245 shove.ForceClearance( true, cur.Gap() - 2 * PNS_HULL_MARGIN );
246
247 bool sh1;
248
249 sh1 = shove.ShoveObstacleLine( postWalk, preShove, postShove );
250
251 if( !sh1 )
252 return false;
253
254 postWalk.Line().Simplify();
255 postShove.Line().Simplify();
256
257 cur.SetShape( postWalk.CLine(), postShove.CLine(), !currentIsP );
258
259 currentIsP = !currentIsP;
260
261 if( !aNode->CheckColliding( &postShove, mask ) )
262 break;
263
264 iter++;
265 }
266 while( iter < 3 );
267
268 if( iter == 3 )
269 return false;
270
271 aWalk.SetShape( cur.CP(), cur.CN() );
272
273 return true;
274}
275
276
277bool DIFF_PAIR_PLACER::tryWalkDp( NODE* aNode, DIFF_PAIR &aPair, bool aSolidsOnly )
278{
279 DIFF_PAIR best;
280 double bestScore = 100000000000000.0;
281
282 for( int attempt = 0; attempt <= 3; attempt++ )
283 {
284 DIFF_PAIR p;
285 NODE *tmp = m_currentNode->Branch();
286
287 bool pfirst = ( attempt & 1 ) ? true : false;
288 bool wind_cw = ( attempt & 2 ) ? true : false;
289
290 if( attemptWalk( tmp, &aPair, p, pfirst, wind_cw, aSolidsOnly ) )
291 {
292 // double len = p.TotalLength();
293 double cl = 1 + p.CoupledLength();
294 double skew = p.Skew();
295
296 double score = cl + fabs( skew ) * 3.0;
297
298 if( score < bestScore )
299 {
300 bestScore = score;
301 best = p;
302 }
303 }
304
305 delete tmp;
306 }
307
308 if( bestScore > 0.0 )
309 {
310 OPTIMIZER optimizer( m_currentNode );
311
312 aPair.SetShape( best );
313 optimizer.Optimize( &aPair );
314
315 return true;
316 }
317
318 return false;
319}
320
321
323{
324 if( !routeHead ( aP ) )
325 return false;
326
328
329 return m_fitOk;
330}
331
332
334{
335 switch( Settings().Mode() )
336 {
337 case RM_MarkObstacles:
338 return rhMarkObstacles( aP );
339 case RM_Walkaround:
340 return rhWalkOnly( aP );
341 case RM_Shove:
342 return rhShoveOnly( aP );
343 default:
344 break;
345 }
346
347 return false;
348}
349
350
352{
353 m_currentNode = m_shove->CurrentNode();
354
355 bool ok = routeHead( aP );
356
357 m_fitOk = false;
358
359 if( !ok )
360 return false;
361
362 if( !tryWalkDp( m_currentNode, m_currentTrace, true ) )
363 return false;
364
365 LINE pLine( m_currentTrace.PLine() );
366 LINE nLine( m_currentTrace.NLine() );
367 ITEM_SET head;
368
369 head.Add( &pLine );
370 head.Add( &nLine );
371
372 SHOVE::SHOVE_STATUS status = SHOVE::SH_INCOMPLETE; //->ShoveMultiLines( head );
373
374 m_currentNode = m_shove->CurrentNode();
375
376 if( status == SHOVE::SH_OK )
377 {
378 m_currentNode = m_shove->CurrentNode();
379
382 {
383 m_fitOk = true;
384 }
385 }
386
387 return m_fitOk;
388}
389
390
392{
393 ITEM_SET t;
394
395 t.Add( &m_currentTrace.PLine() );
396 t.Add( &m_currentTrace.NLine() );
397
398 return t;
399}
400
401
403{
405
406 if( !m_idle )
407 Move( m_currentEnd, nullptr );
408}
409
410
411NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
412{
413 if( m_lastNode )
414 return m_lastNode;
415
416 return m_currentNode;
417}
418
419
421{
422 if( m_idle )
423 {
424 m_currentLayer = aLayer;
425 return true;
426 }
427 else if( m_chainedPlacement || !m_prevPair )
428 {
429 return false;
430 }
431 else if( !m_prevPair->PrimP() || ( m_prevPair->PrimP()->OfKind( ITEM::VIA_T ) &&
432 m_prevPair->PrimP()->Layers().Overlaps( aLayer ) ) )
433 {
434 m_currentLayer = aLayer;
437 Move( m_currentEnd, nullptr );
438 return true;
439 }
440
441 return false;
442}
443
444
446{
447 switch( aItem->Kind() )
448 {
449 case ITEM::LINE_T:
450 {
451 LINE* l = static_cast<LINE*>( aItem );
452
453 if( !l->PointCount() )
454 return OPT_VECTOR2I();
455 else
456 return l->CPoint( 0 );
457 }
458 case ITEM::VIA_T:
459 case ITEM::SOLID_T:
460 return aItem->Anchor( 0 );
461
462 case ITEM::ARC_T:
463 {
464 ARC* a = static_cast<ARC*>( aItem );
465
466 const JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
467 const JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
468
469 if( jA && jA->LinkCount() == 1 )
470 return a->Arc().GetP0();
471 else if( jB && jB->LinkCount() == 1 )
472 return a->Arc().GetP1();
473 else
474 return OPT_VECTOR2I();
475 }
476 case ITEM::SEGMENT_T:
477 {
478 SEGMENT* s = static_cast<SEGMENT*>( 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 s->Seg().A;
485 else if( jB && jB->LinkCount() == 1 )
486 return s->Seg().B;
487 else
488 return OPT_VECTOR2I();
489 }
490
491 default:
492 return OPT_VECTOR2I();
493 }
494}
495
496
497
499 DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
500{
501 NET_HANDLE netP, netN;
502
503 bool result = aWorld->GetRuleResolver()->DpNetPair( aItem, netP, netN );
504
505 if( !result )
506 {
507 if( aErrorMsg )
508 {
509 *aErrorMsg = _( "Unable to find complementary differential pair "
510 "nets. Make sure the names of the nets belonging "
511 "to a differential pair end with either N/P or +/-." );
512 }
513 return false;
514 }
515
516 NET_HANDLE refNet = aItem->Net();
517 NET_HANDLE coupledNet = ( refNet == netP ) ? netN : netP;
518
519 OPT_VECTOR2I refAnchor = getDanglingAnchor( aWorld, aItem );
520 ITEM* primRef = aItem;
521
522 if( !refAnchor )
523 {
524 if( aErrorMsg )
525 {
526 *aErrorMsg = _( "Can't find a suitable starting point. If starting "
527 "from an existing differential pair make sure you are "
528 "at the end." );
529 }
530
531 return false;
532 }
533
534 std::set<ITEM*> coupledItems;
535
536 aWorld->AllItemsInNet( coupledNet, coupledItems );
537 double bestDist = std::numeric_limits<double>::max();
538 bool found = false;
539
540 for( ITEM* item : coupledItems )
541 {
542 if( item->Kind() == aItem->Kind() )
543 {
544 OPT_VECTOR2I anchor = getDanglingAnchor( aWorld, item );
545
546 if( !anchor )
547 continue;
548
549 double dist = ( *anchor - *refAnchor ).EuclideanNorm();
550
551 bool shapeMatches = true;
552
553 if( item->OfKind( ITEM::SOLID_T | ITEM::VIA_T ) && item->Layers() != aItem->Layers() )
554 {
555 shapeMatches = false;
556 }
557
558 if( dist < bestDist && shapeMatches )
559 {
560 found = true;
561 bestDist = dist;
562
563 if( refNet != netP )
564 {
565 aPair = DP_PRIMITIVE_PAIR ( item, primRef );
566 aPair.SetAnchors( *anchor, *refAnchor );
567 }
568 else
569 {
570 aPair = DP_PRIMITIVE_PAIR( primRef, item );
571 aPair.SetAnchors( *refAnchor, *anchor );
572 }
573 }
574 }
575 }
576
577 if( !found )
578 {
579 if( aErrorMsg )
580 {
581 *aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
582 "for coupled net \"%s\"." ),
583 aWorld->GetRuleResolver()->NetName( coupledNet ) );
584 }
585
586 return false;
587 }
588
589 return true;
590}
591
592
594{
595 return std::max( m_sizes.DiffPairViaGap(),
597}
598
599
601{
603}
604
605
606bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
607{
608 VECTOR2I p( aP );
609
610 setWorld( Router()->GetWorld() );
612
613 wxString err_msg;
614
615 if( !FindDpPrimitivePair( m_currentNode, aP, aStartItem, m_start, &err_msg ) )
616 {
617 Router()->SetFailureReason( err_msg );
618 return false;
619 }
620
621 m_netP = m_start.PrimP()->Net();
622 m_netN = m_start.PrimN()->Net();
623
624 m_currentStart = p;
625 m_currentEnd = p;
626 m_placingVia = false;
627 m_chainedPlacement = false;
628 m_currentTraceOk = false;
631
633
634 return true;
635}
636
637
639{
640 m_idle = false;
641 m_orthoMode = false;
642 m_currentEndItem = nullptr;
644
645 NODE* world = Router()->GetWorld();
646
647 world->KillChildren();
648 NODE* rootNode = world->Branch();
649
650 setWorld( rootNode );
651
652 m_lastNode = nullptr;
653 m_currentNode = rootNode;
654
655 m_shove = std::make_unique<SHOVE>( m_currentNode, Router() );
656}
657
658
660{
661 m_fitOk = false;
662
663 DP_GATEWAYS gwsEntry( gap() );
664 DP_GATEWAYS gwsTarget( gap() );
665
666 if( !m_prevPair )
668
670
671 DP_PRIMITIVE_PAIR target;
672
674 {
675 gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
676 m_snapOnTarget = true;
677 }
678 else
679 {
680 VECTOR2I fp;
681
682 if( !propagateDpHeadForces( aP, fp ) )
683 return false;
684
685 VECTOR2I midp, dirV;
686 m_prevPair->CursorOrientation( fp, midp, dirV );
687
688 VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp );
689
690 // compute 'leader point' distance from the cursor (project cursor position
691 // on the extension of the starting segment pair of the DP)
692 int lead_dist = ( fpProj - fp ).EuclideanNorm();
693
695
696 // far from the initial segment extension line -> allow a 45-degree obtuse turn
697 if( lead_dist > ( m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() ) / 2 )
698 {
699 gwsTarget.BuildForCursor( fp );
700 }
701 else
702 {
703 // close to the initial segment extension line -> keep straight part only, project
704 // as close as possible to the cursor.
705 gwsTarget.BuildForCursor( fpProj );
707 DIRECTION_45( dirV ) );
708 }
709
710 m_snapOnTarget = false;
711 }
712
715
716 bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace );
717
718 if( result )
719 {
720 m_currentTraceOk = true;
724
725 if( m_placingVia )
726 {
728 makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) );
729 }
730 else
731 {
733 }
734
735 return true;
736 }
737
738 return m_currentTraceOk;
739}
740
741
742bool DIFF_PAIR_PLACER::Move( const VECTOR2I& aP , ITEM* aEndItem )
743{
744 m_currentEndItem = aEndItem;
745 m_fitOk = false;
746
747 delete m_lastNode;
748 m_lastNode = nullptr;
749
750 bool retval = route( aP );
751
752 NODE* latestNode = m_currentNode;
753 m_lastNode = latestNode->Branch();
754
755 assert( m_lastNode != nullptr );
756 m_currentEnd = aP;
757
759
760 return retval;
761}
762
763
765{
766 m_sizes = aSizes;
767
768 if( !m_idle )
769 {
772
774 {
777 }
778 }
779}
780
781
782bool DIFF_PAIR_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
783{
784 if( !m_fitOk && !Settings().AllowDRCViolations() )
785 return false;
786
788 return false;
789
790 if( m_currentTrace.CP().SegmentCount() > 1 )
792
793 TOPOLOGY topo( m_lastNode );
794
795 if( !m_snapOnTarget && !m_currentTrace.EndsWithVias() && !aForceFinish &&
796 !Settings().GetFixAllSegments() )
797 {
800
801 if( newP.SegmentCount() > 1 && newN.SegmentCount() > 1 )
802 {
803 newP.Remove( -1, -1 );
804 newN.Remove( -1, -1 );
805 }
806
807 m_currentTrace.SetShape( newP, newN );
808 }
809
811 {
814 m_chainedPlacement = false;
815 }
816 else
817 {
818 m_chainedPlacement = !m_snapOnTarget && !aForceFinish;
819 }
820
821 LINE lineP( m_currentTrace.PLine() );
822 LINE lineN( m_currentTrace.NLine() );
823
824 m_lastNode->Add( lineP );
825 m_lastNode->Add( lineN );
826
827 topo.SimplifyLine( &lineP );
828 topo.SimplifyLine( &lineN );
829
831
833 m_placingVia = false;
834
835 if( m_snapOnTarget || aForceFinish )
836 {
837 m_idle = true;
838 return true;
839 }
840 else
841 {
843 return false;
844 }
845}
846
847
849{
851 return true;
852}
853
854
856{
858}
859
860
862{
863 if( m_lastNode )
865
866 m_lastNode = nullptr;
867 m_currentNode = nullptr;
868 return true;
869}
870
871
872void DIFF_PAIR_PLACER::GetModifiedNets( std::vector<NET_HANDLE> &aNets ) const
873{
874 aNets.push_back( m_netP );
875 aNets.push_back( m_netN );
876}
877
878
880{
881 SHAPE_LINE_CHAIN ratLineN, ratLineP;
882 TOPOLOGY topo( m_lastNode );
883
884 if( topo.LeadingRatLine( &m_currentTrace.PLine(), ratLineP ) )
886
887 if( topo.LeadingRatLine ( &m_currentTrace.NLine(), ratLineN ) )
889}
890
891
892const std::vector<NET_HANDLE> DIFF_PAIR_PLACER::CurrentNets() const
893{
894 std::vector<NET_HANDLE> rv;
895 rv.push_back( m_netP );
896 rv.push_back( m_netN );
897 return rv;
898}
899
900}
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:97
const PNS_LAYER_RANGE & Layers() const
Definition: pns_item.h:199
virtual NET_HANDLE Net() const
Definition: pns_item.h:197
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:170
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:202
@ SEGMENT_T
Definition: pns_item.h:106
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:255
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:1242
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:1529
void KillChildren()
Definition: pns_node.cpp:1523
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
Definition: pns_optimizer.h:95
static bool Optimize(const 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
@ SH_INCOMPLETE
Definition: pns_shove.h:53
bool ShoveObstacleLine(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine)
Definition: pns_shove.cpp:428
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:115
const VECTOR2I & GetP0() const
Definition: shape_arc.h:114
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:54
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:327
#define PNS_HULL_MARGIN
Definition: pns_line.h:45
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39