KiCad PCB EDA Suite
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-2021 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
30namespace PNS {
31
33 PLACEMENT_ALGO( aRouter )
34{
36 m_chainedPlacement = false;
37 m_initialDiagonal = false;
38 m_startDiagonal = false;
39 m_fitOk = false;
40 m_netP = 0;
41 m_netN = 0;
42 m_iteration = 0;
43 m_world = nullptr;
44 m_shove = nullptr;
45 m_currentNode = nullptr;
46 m_lastNode = nullptr;
47 m_placingVia = false;
48 m_viaDiameter = 0;
49 m_viaDrill = 0;
51 m_currentNet = 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
71const VIA DIFF_PAIR_PLACER::makeVia( const VECTOR2I& aP, int aNet )
72{
74
75 VIA v( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), -1, m_sizes.ViaType() );
76 v.SetNet( aNet );
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, -1 );
119
120 if( m_placingVia )
121 {
122 virtHead.SetDiameter( viaGap() + 2 * virtHead.Diameter() );
123 }
124 else
125 {
126 virtHead.SetLayer( m_currentLayer );
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<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() );
163
164 if( obs->m_item->Shape()->Collide( virtHead.Shape(), clearance, &force ) )
165 {
166 collided = true;
167 totalForce += force;
168 virtHead.SetPos( virtHead.Pos() + force );
169 }
170
171 handled.insert( obs->m_item );
172
173 iter++;
174 }
175
176 bool succeeded = ( !collided || iter != maxIter );
177
178 if( succeeded )
179 {
180 aNewP = aP + force;
181 return true;
182 }
183
184 return false;
185}
186
187
189 bool aPFirst, bool aWindCw, bool aSolidsOnly )
190{
191 WALKAROUND walkaround( aNode, Router() );
193
194 walkaround.SetSolidsOnly( aSolidsOnly );
195 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
196
197 SHOVE shove( aNode, Router() );
198 LINE walkP, walkN;
199
200 aWalk = *aCurrent;
201
202 int iter = 0;
203
204 DIFF_PAIR cur( *aCurrent );
205
206 bool currentIsP = aPFirst;
207
208 int mask = aSolidsOnly ? ITEM::SOLID_T : ITEM::ANY_T;
209
210 do
211 {
212 LINE preWalk = ( currentIsP ? cur.PLine() : cur.NLine() );
213 LINE preShove = ( currentIsP ? cur.NLine() : cur.PLine() );
214 LINE postWalk;
215
216 if( !aNode->CheckColliding ( &preWalk, mask ) )
217 {
218 currentIsP = !currentIsP;
219
220 if( !aNode->CheckColliding( &preShove, mask ) )
221 break;
222 else
223 continue;
224 }
225
226 wf1 = walkaround.Route( preWalk, postWalk, false );
227
228 if( wf1 != WALKAROUND::DONE )
229 return false;
230
231 LINE postShove( preShove );
232
233 shove.ForceClearance( true, cur.Gap() - 2 * PNS_HULL_MARGIN );
234
236
237 sh1 = shove.ShoveObstacleLine( postWalk, preShove, postShove );
238
239 if( sh1 != SHOVE::SH_OK )
240 return false;
241
242 postWalk.Line().Simplify();
243 postShove.Line().Simplify();
244
245 cur.SetShape( postWalk.CLine(), postShove.CLine(), !currentIsP );
246
247 currentIsP = !currentIsP;
248
249 if( !aNode->CheckColliding( &postShove, mask ) )
250 break;
251
252 iter++;
253 }
254 while( iter < 3 );
255
256 if( iter == 3 )
257 return false;
258
259 aWalk.SetShape( cur.CP(), cur.CN() );
260
261 return true;
262}
263
264
265bool DIFF_PAIR_PLACER::tryWalkDp( NODE* aNode, DIFF_PAIR &aPair, bool aSolidsOnly )
266{
267 DIFF_PAIR best;
268 double bestScore = 100000000000000.0;
269
270 for( int attempt = 0; attempt <= 3; attempt++ )
271 {
272 DIFF_PAIR p;
273 NODE *tmp = m_currentNode->Branch();
274
275 bool pfirst = ( attempt & 1 ) ? true : false;
276 bool wind_cw = ( attempt & 2 ) ? true : false;
277
278 if( attemptWalk( tmp, &aPair, p, pfirst, wind_cw, aSolidsOnly ) )
279 {
280 // double len = p.TotalLength();
281 double cl = 1 + p.CoupledLength();
282 double skew = p.Skew();
283
284 double score = cl + fabs( skew ) * 3.0;
285
286 if( score < bestScore )
287 {
288 bestScore = score;
289 best = p;
290 }
291 }
292
293 delete tmp;
294 }
295
296 if( bestScore > 0.0 )
297 {
298 OPTIMIZER optimizer( m_currentNode );
299
300 aPair.SetShape( best );
301 optimizer.Optimize( &aPair );
302
303 return true;
304 }
305
306 return false;
307}
308
309
311{
312 if( !routeHead ( aP ) )
313 return false;
314
316
317 return m_fitOk;
318}
319
320
322{
323 switch( Settings().Mode() )
324 {
325 case RM_MarkObstacles:
326 return rhMarkObstacles( aP );
327 case RM_Walkaround:
328 return rhWalkOnly( aP );
329 case RM_Shove:
330 return rhShoveOnly( aP );
331 default:
332 break;
333 }
334
335 return false;
336}
337
338
340{
341 m_currentNode = m_shove->CurrentNode();
342
343 bool ok = routeHead( aP );
344
345 m_fitOk = false;
346
347 if( !ok )
348 return false;
349
350 if( !tryWalkDp( m_currentNode, m_currentTrace, true ) )
351 return false;
352
353 LINE pLine( m_currentTrace.PLine() );
354 LINE nLine( m_currentTrace.NLine() );
355 ITEM_SET head;
356
357 head.Add( &pLine );
358 head.Add( &nLine );
359
360 SHOVE::SHOVE_STATUS status = m_shove->ShoveMultiLines( head );
361
362 m_currentNode = m_shove->CurrentNode();
363
364 if( status == SHOVE::SH_OK )
365 {
366 m_currentNode = m_shove->CurrentNode();
367
370 {
371 m_fitOk = true;
372 }
373 }
374
375 return m_fitOk;
376}
377
378
380{
381 ITEM_SET t;
382
383 t.Add( &m_currentTrace.PLine() );
384 t.Add( &m_currentTrace.NLine() );
385
386 return t;
387}
388
389
391{
393
394 if( !m_idle )
395 Move( m_currentEnd, nullptr );
396}
397
398
399NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
400{
401 if( m_lastNode )
402 return m_lastNode;
403
404 return m_currentNode;
405}
406
407
409{
410 if( m_idle )
411 {
412 m_currentLayer = aLayer;
413 return true;
414 }
415 else if( m_chainedPlacement || !m_prevPair )
416 {
417 return false;
418 }
419 else if( !m_prevPair->PrimP() || ( m_prevPair->PrimP()->OfKind( ITEM::VIA_T ) &&
420 m_prevPair->PrimP()->Layers().Overlaps( aLayer ) ) )
421 {
422 m_currentLayer = aLayer;
425 Move( m_currentEnd, nullptr );
426 return true;
427 }
428
429 return false;
430}
431
432
434{
435 switch( aItem->Kind() )
436 {
437 case ITEM::VIA_T:
438 case ITEM::SOLID_T:
439 return aItem->Anchor( 0 );
440
441 case ITEM::ARC_T:
442 case ITEM::SEGMENT_T:
443 {
444 SEGMENT* s = static_cast<SEGMENT*>( aItem );
445
446 JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
447 JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
448
449 if( jA && jA->LinkCount() == 1 )
450 return s->Seg().A;
451 else if( jB && jB->LinkCount() == 1 )
452 return s->Seg().B;
453 else
454 return OPT_VECTOR2I();
455 }
456
457 default:
458 return OPT_VECTOR2I();
459 }
460}
461
462
463
465 DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
466{
467 int netP, netN;
468
469 bool result = aWorld->GetRuleResolver()->DpNetPair( aItem, netP, netN );
470
471 if( !result )
472 {
473 if( aErrorMsg )
474 {
475 *aErrorMsg = _( "Unable to find complementary differential pair "
476 "nets. Make sure the names of the nets belonging "
477 "to a differential pair end with either N/P or +/-." );
478 }
479 return false;
480 }
481
482 int refNet = aItem->Net();
483 int coupledNet = ( refNet == netP ) ? netN : netP;
484
485 OPT_VECTOR2I refAnchor = getDanglingAnchor( aWorld, aItem );
486 ITEM* primRef = aItem;
487
488 if( !refAnchor )
489 {
490 if( aErrorMsg )
491 {
492 *aErrorMsg = _( "Can't find a suitable starting point. If starting "
493 "from an existing differential pair make sure you are "
494 "at the end." );
495 }
496
497 return false;
498 }
499
500 std::set<ITEM*> coupledItems;
501
502 aWorld->AllItemsInNet( coupledNet, coupledItems );
503 double bestDist = std::numeric_limits<double>::max();
504 bool found = false;
505
506 for( ITEM* item : coupledItems )
507 {
508 if( item->Kind() == aItem->Kind() )
509 {
510 OPT_VECTOR2I anchor = getDanglingAnchor( aWorld, item );
511
512 if( !anchor )
513 continue;
514
515 double dist = ( *anchor - *refAnchor ).EuclideanNorm();
516
517 bool shapeMatches = true;
518
519 if( item->OfKind( ITEM::SOLID_T | ITEM::VIA_T ) && item->Layers() != aItem->Layers() )
520 {
521 shapeMatches = false;
522 }
523
524 if( dist < bestDist && shapeMatches )
525 {
526 found = true;
527 bestDist = dist;
528
529 if( refNet != netP )
530 {
531 aPair = DP_PRIMITIVE_PAIR ( item, primRef );
532 aPair.SetAnchors( *anchor, *refAnchor );
533 }
534 else
535 {
536 aPair = DP_PRIMITIVE_PAIR( primRef, item );
537 aPair.SetAnchors( *refAnchor, *anchor );
538 }
539 }
540 }
541 }
542
543 if( !found )
544 {
545 if( aErrorMsg )
546 {
547 *aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
548 "for coupled net \"%s\"." ),
549 aWorld->GetRuleResolver()->NetName( coupledNet ) );
550 }
551
552 return false;
553 }
554
555 return true;
556}
557
558
560{
561 return std::max( m_sizes.DiffPairViaGap(),
563}
564
565
567{
569}
570
571
572bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
573{
574 VECTOR2I p( aP );
575
576 setWorld( Router()->GetWorld() );
578
579 wxString err_msg;
580
581 if( !FindDpPrimitivePair( m_currentNode, aP, aStartItem, m_start, &err_msg ) )
582 {
583 Router()->SetFailureReason( err_msg );
584 return false;
585 }
586
587 m_netP = m_start.PrimP()->Net();
588 m_netN = m_start.PrimN()->Net();
589
590 m_currentStart = p;
591 m_currentEnd = p;
592 m_placingVia = false;
593 m_chainedPlacement = false;
594 m_currentTraceOk = false;
597
599
600 return true;
601}
602
603
605{
606 m_idle = false;
607 m_orthoMode = false;
608 m_currentEndItem = nullptr;
610
611 NODE* world = Router()->GetWorld();
612
613 world->KillChildren();
614 NODE* rootNode = world->Branch();
615
616 setWorld( rootNode );
617
618 m_lastNode = nullptr;
619 m_currentNode = rootNode;
620
621 m_shove = std::make_unique<SHOVE>( m_currentNode, Router() );
622}
623
624
626{
627 m_fitOk = false;
628
629 DP_GATEWAYS gwsEntry( gap() );
630 DP_GATEWAYS gwsTarget( gap() );
631
632 if( !m_prevPair )
634
636
637 DP_PRIMITIVE_PAIR target;
638
640 {
641 gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
642 m_snapOnTarget = true;
643 }
644 else
645 {
646 VECTOR2I fp;
647
648 if( !propagateDpHeadForces( aP, fp ) )
649 return false;
650
651 VECTOR2I midp, dirV;
652 m_prevPair->CursorOrientation( fp, midp, dirV );
653
654 VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp );
655
656 // compute 'leader point' distance from the cursor (project cursor position
657 // on the extension of the starting segment pair of the DP)
658 int lead_dist = ( fpProj - fp ).EuclideanNorm();
659
661
662 // far from the initial segment extension line -> allow a 45-degree obtuse turn
663 if( lead_dist > ( m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() ) / 2 )
664 {
665 gwsTarget.BuildForCursor( fp );
666 }
667 else
668 {
669 // close to the initial segment extension line -> keep straight part only, project
670 // as close as possible to the cursor.
671 gwsTarget.BuildForCursor( fpProj );
673 DIRECTION_45( dirV ) );
674 }
675
676 m_snapOnTarget = false;
677 }
678
681
682 bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace );
683
684 if( result )
685 {
686 m_currentTraceOk = true;
690
691 if( m_placingVia )
692 {
694 makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) );
695 }
696 else
697 {
699 }
700
701 return true;
702 }
703
704 return m_currentTraceOk;
705}
706
707
708bool DIFF_PAIR_PLACER::Move( const VECTOR2I& aP , ITEM* aEndItem )
709{
710 m_currentEndItem = aEndItem;
711 m_fitOk = false;
712
713 delete m_lastNode;
714 m_lastNode = nullptr;
715
716 bool retval = route( aP );
717
718 NODE* latestNode = m_currentNode;
719 m_lastNode = latestNode->Branch();
720
721 assert( m_lastNode != nullptr );
722 m_currentEnd = aP;
723
725
726 return retval;
727}
728
729
731{
732 m_sizes = aSizes;
733
734 if( !m_idle )
735 {
738
740 {
743 }
744 }
745}
746
747
748bool DIFF_PAIR_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
749{
750 if( !m_fitOk && !Settings().AllowDRCViolations() )
751 return false;
752
754 return false;
755
756 if( m_currentTrace.CP().SegmentCount() > 1 )
758
759 TOPOLOGY topo( m_lastNode );
760
761 if( !m_snapOnTarget && !m_currentTrace.EndsWithVias() && !aForceFinish &&
762 !Settings().GetFixAllSegments() )
763 {
766
767 if( newP.SegmentCount() > 1 && newN.SegmentCount() > 1 )
768 {
769 newP.Remove( -1, -1 );
770 newN.Remove( -1, -1 );
771 }
772
773 m_currentTrace.SetShape( newP, newN );
774 }
775
777 {
780 m_chainedPlacement = false;
781 }
782 else
783 {
784 m_chainedPlacement = !m_snapOnTarget && !aForceFinish;
785 }
786
787 LINE lineP( m_currentTrace.PLine() );
788 LINE lineN( m_currentTrace.NLine() );
789
790 m_lastNode->Add( lineP );
791 m_lastNode->Add( lineN );
792
793 topo.SimplifyLine( &lineP );
794 topo.SimplifyLine( &lineN );
795
797
799 m_placingVia = false;
800
801 if( m_snapOnTarget || aForceFinish )
802 {
803 m_idle = true;
804 return true;
805 }
806 else
807 {
809 return false;
810 }
811}
812
813
815{
817 return true;
818}
819
820
822{
824}
825
826
828{
829 if( m_lastNode )
831
832 m_lastNode = nullptr;
833 m_currentNode = nullptr;
834 return true;
835}
836
837
838void DIFF_PAIR_PLACER::GetModifiedNets( std::vector<int> &aNets ) const
839{
840 aNets.push_back( m_netP );
841 aNets.push_back( m_netN );
842}
843
844
846{
847 SHAPE_LINE_CHAIN ratLineN, ratLineP;
848 TOPOLOGY topo( m_lastNode );
849
850 if( topo.LeadingRatLine( &m_currentTrace.PLine(), ratLineP ) )
852
853 if( topo.LeadingRatLine ( &m_currentTrace.NLine(), ratLineN ) )
855}
856
857
858const std::vector<int> DIFF_PAIR_PLACER::CurrentNets() const
859{
860 std::vector<int> rv;
861 rv.push_back( m_netP );
862 rv.push_back( m_netN );
863 return rv;
864}
865
866}
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.
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)
void GetModifiedNets(std::vector< int > &aNets) const override
Function GetModifiedNets.
bool rhMarkObstacles(const VECTOR2I &aP)
int m_viaDiameter
current via drill
const VIA makeVia(const VECTOR2I &aP, int aNet)
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
const std::vector< int > CurrentNets() const override
Return the net code of currently routed track.
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.
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.
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...
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)
const SHAPE_LINE_CHAIN & CP() const
void SetNets(int aP, int aN)
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:56
void SetNet(int aNet)
Definition: pns_item.h:153
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:132
void SetLayer(int aLayer)
Definition: pns_item.h:159
@ SOLID_T
Definition: pns_item.h:63
@ SEGMENT_T
Definition: pns_item.h:66
const LAYER_RANGE & Layers() const
Definition: pns_item.h:156
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:219
int Net() const
Definition: pns_item.h:154
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:256
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:61
const VIA & Via() const
Definition: pns_line.h:199
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:142
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:141
Keep the router "world" - i.e.
Definition: pns_node.h:156
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:139
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Definition: pns_node.cpp:103
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1476
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:475
std::optional< OBSTACLE > OPT_OBSTACLE
Definition: pns_node.h:166
RULE_RESOLVER * GetRuleResolver() const
Return the number of joints.
Definition: pns_node.h:197
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:667
void KillChildren()
Definition: pns_node.cpp:1470
JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, int aNet)
Search for a joint at a given position, layer and belonging to given net.
Definition: pns_node.cpp:1201
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, int aNetCode)=0
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:215
void SetFailureReason(const wxString &aReason)
Definition: pns_router.h:210
void CommitRouting()
Definition: pns_router.cpp:902
NODE * GetWorld() const
Definition: pns_router.h:161
virtual wxString NetName(int aNet)=0
virtual bool DpNetPair(const ITEM *aItem, int &aNetP, int &aNetN)=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:405
void ForceClearance(bool aEnabled, int aClearance)
Definition: pns_shove.h:74
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:100
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_via.h:136
int Diameter() const
Definition: pns_via.h:112
void SetDiameter(int aDiameter)
Definition: pns_via.h:114
void SetPos(const VECTOR2I &aPos)
Definition: pns_via.h:102
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
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
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.
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:279
#define PNS_HULL_MARGIN
Definition: pns_line.h:44
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129