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"
25 #include "pns_diff_pair_placer.h"
26 #include "pns_solid.h"
27 #include "pns_topology.h"
28 #include "pns_debug_decorator.h"
29 
30 namespace PNS {
31 
33  PLACEMENT_ALGO( aRouter )
34 {
35  m_state = RT_START;
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;
50  m_currentWidth = 0;
51  m_currentNet = 0;
52  m_currentLayer = 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 
71 const 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 
82 void DIFF_PAIR_PLACER::SetOrthoMode ( bool aOrthoMode )
83 {
84  m_orthoMode = aOrthoMode;
85 
86  if( !m_idle )
87  Move( m_currentEnd, nullptr );
88 }
89 
90 
91 bool 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 );
127  virtHead.SetDiameter( 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<ITEM*> handled;
153 
154  while( iter < maxIter )
155  {
156  NODE::OPT_OBSTACLE obs = m_currentNode->CheckColliding( &virtHead, solidsOnly ?
157  ITEM::SOLID_T :
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 
188 bool DIFF_PAIR_PLACER::attemptWalk( NODE* aNode, DIFF_PAIR* aCurrent, DIFF_PAIR& aWalk,
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 
265 bool 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 = 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 
399 NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
400 {
401  if( m_lastNode )
402  return m_lastNode;
403 
404  return m_currentNode;
405 }
406 
407 
408 bool DIFF_PAIR_PLACER::SetLayer( int aLayer )
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;
423  m_start = *m_prevPair;
424  initPlacement();
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 
464 bool DIFF_PAIR_PLACER::FindDpPrimitivePair( NODE* aWorld, const VECTOR2I& aP, ITEM* aItem,
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 
572 bool 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 
598  initPlacement();
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 
660  gwsTarget.SetFitVias( m_placingVia, m_sizes.ViaDiameter(), viaGap() );
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 
708 bool 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 
748 bool 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 )
757  m_initialDiagonal = !DIRECTION_45( m_currentTrace.CP().CSegment( -2 ) ).IsDiagonal();
758 
759  TOPOLOGY topo( m_lastNode );
760 
761  if( !m_snapOnTarget && !m_currentTrace.EndsWithVias() && !aForceFinish &&
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 
798  CommitPlacement();
799  m_placingVia = false;
800 
801  if( m_snapOnTarget || aForceFinish )
802  {
803  m_idle = true;
804  return true;
805  }
806  else
807  {
808  initPlacement();
809  return false;
810  }
811 }
812 
813 
815 {
817  return true;
818 }
819 
820 
822 {
823  return m_currentTrace.CP().SegmentCount() > 0 || m_currentTrace.CN().SegmentCount() > 0;
824 }
825 
826 
828 {
829  if( m_lastNode )
831 
832  m_lastNode = nullptr;
833  m_currentNode = nullptr;
834  return true;
835 }
836 
837 
838 void 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 ) )
851  m_router->GetInterface()->DisplayRatline( ratLineP, 1 );
852 
853  if( topo.LeadingRatLine ( &m_currentTrace.NLine(), ratLineN ) )
854  m_router->GetInterface()->DisplayRatline( ratLineN, 3 );
855 }
856 
857 
858 const 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 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:146
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:137
bool rhWalkOnly(const VECTOR2I &aP)
route step, shove mode
Base class for PNS router board items.
Definition: pns_item.h:55
SIZES_SETTINGS m_sizes
Are we placing a via?
ROUTER * Router() const
Return current router settings.
Definition: pns_algo_base.h:54
bool FitGateways(DP_GATEWAYS &aEntry, DP_GATEWAYS &aTarget, bool aPrefDiagonal, DIFF_PAIR &aDp)
void BuildForCursor(const VECTOR2I &aCursorPos)
bool attemptWalk(NODE *aNode, DIFF_PAIR *aCurrent, DIFF_PAIR &aWalk, bool aPFirst, bool aWindCw, bool aSolidsOnly)
Keep the router "world" - i.e.
Definition: pns_node.h:146
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...
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
The actual Push and Shove algorithm.
Definition: pns_shove.h:45
int Gap() const
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
void GetModifiedNets(std::vector< int > &aNets) const override
Function GetModifiedNets.
void SetLayer(int aLayer)
Definition: pns_item.h:157
bool route(const VECTOR2I &aP)
Re-route the current track to point aP.
void AppendVias(const VIA &aViaP, const VIA &aViaN)
bool EndsWithVias() const
bool rhShoveOnly(const VECTOR2I &aP)
route step, mark obstacles mode
void CommitRouting()
Definition: pns_router.cpp:707
const SHAPE_LINE_CHAIN & CN() const
int m_iteration
pointer to world to search colliding items
void FilterByOrientation(int aAngleMask, DIRECTION_45 aRefOrientation)
#define PNS_HULL_MARGIN
Definition: pns_line.h:44
int m_viaDiameter
current via drill
WALKAROUND_STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
NODE * CurrentNode(bool aLoopsRemoved=false) const override
Return the most recent world state.
double CoupledLength() const
virtual void DisplayRatline(const SHAPE_LINE_CHAIN &aRatline, int aColor=-1)=0
NODE * m_world
current routing start point (end of tail, beginning of head)
const SEG & Seg() const
Definition: pns_segment.h:84
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:60
SHOVE_STATUS ShoveObstacleLine(const LINE &aCurLine, const LINE &aObstacleLine, LINE &aResultLine)
Definition: pns_shove.cpp:394
const VIA makeVia(const VECTOR2I &aP, int aNet)
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
const SHAPE * Shape() const override
Return the geometrical shape of the item.
Definition: pns_via.h:133
bool routeHead(const VECTOR2I &aP)
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:137
const VECTOR2I & Pos() const
Definition: pns_via.h:99
ITEM * PrimP() const
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
void SetNet(int aNet)
Definition: pns_item.h:151
std::unique_ptr< SHOVE > m_shove
Current world state.
VIATYPE ViaType() const
int m_viaDrill
current track width
void SetDiameter(int aDiameter)
Definition: pns_via.h:113
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
bool HasPlacedAnything() const override
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:42
void BuildFromPrimitivePair(const DP_PRIMITIVE_PAIR &aPair, bool aPreferDiagonal)
void SetGap(int aGap)
bool propagateDpHeadForces(const VECTOR2I &aP, VECTOR2I &aNewP)
int Diameter() const
Definition: pns_via.h:111
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:268
ROUTER * m_router
Definition: pns_algo_base.h:87
int GetClearance(const ITEM *aA, const ITEM *aB) const
Definition: pns_node.cpp:101
void KillChildren()
Definition: pns_node.cpp:1405
void SetFitVias(bool aEnable, int aDiameter=0, int aViaGap=-1)
bool LeadingRatLine(const LINE *aTrack, SHAPE_LINE_CHAIN &aRatLine)
OPT< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:38
bool ToggleVia(bool aEnabled) override
Enable/disable a via at the end of currently routed trace.
int Net() const
Definition: pns_item.h:152
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:36
void UpdateSizes(const SIZES_SETTINGS &aSizes) override
Perform on-the-fly update of the width, via diameter & drill size from a settings class.
OPT_VECTOR2I getDanglingAnchor(NODE *aNode, ITEM *aItem)
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 SetFailureReason(const wxString &aReason)
Definition: pns_router.h:202
PNS_MODE Mode() const
Set the routing mode.
bool m_placingVia
current via diameter
#define _(s)
DIFF_PAIR_PLACER(ROUTER *aRouter)
void SetViaDiameter(int aDiameter)
void SetSolidsOnly(bool aSolidsOnly)
void SetWidth(int aWidth)
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
double Skew() const
int SegmentCount() const
Return the number of segments in this line chain.
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:1140
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:136
bool SimplifyLine(LINE *aLine)
RULE_RESOLVER * GetRuleResolver() const
Return the number of joints.
Definition: pns_node.h:179
void SetPos(const VECTOR2I &aPos)
Definition: pns_via.h:101
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
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:217
Definition: seg.h:40
Basic class for a differential pair.
void FlipPosture() override
Toggle the current posture (straight/diagonal) of the trace head.
const SHAPE_LINE_CHAIN & CP() const
NODE * m_currentNode
Postprocessed world state (including marked collisions & removed loops)
void updateLeadingRatLine()
Draw the "leading" ratsnest line, which connects the end of currently routed track and the nearest ye...
Ignore collisions, mark obstacles.
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).
void ForceClearance(bool aEnabled, int aClearance)
Definition: pns_shove.h:74
ITEM * PrimN() const
Store starting/ending primitives (pads, vias or segments) for a differential pair.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:271
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1411
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:450
VECTOR2I A
Definition: seg.h:48
void initPlacement()
Initialize placement of a new line with given parameters.
static bool FindDpPrimitivePair(NODE *aWorld, const VECTOR2I &aP, ITEM *aItem, DP_PRIMITIVE_PAIR &aPair, wxString *aErrorMsg=nullptr)
Only walk around.
bool SetLayer(int aLayer) override
Set the current routing layer.
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:130
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
Definition: pns_optimizer.h:94
OPT< OBSTACLE > OPT_OBSTACLE
Definition: pns_node.h:149
const std::vector< int > CurrentNets() const override
Return the net code of currently routed track.
virtual wxString NetName(int aNet)=0
OPT< DP_PRIMITIVE_PAIR > m_prevPair
current algorithm iteration
bool tryWalkDp(NODE *aNode, DIFF_PAIR &aPair, bool aSolidsOnly)
route step, walk around mode
void SetOrthoMode(bool aOrthoMode) override
Function SetOrthoMode()
int LinkCount(int aMask=-1) const
Definition: pns_joint.h:210
void setWorld(NODE *aWorld)
Set the board to route.
virtual bool DpNetPair(const ITEM *aItem, int &aNetP, int &aNetN)=0
const VIA & Via() const
Definition: pns_line.h:196
A set of gateways calculated for the cursor or starting/ending primitive pair.
void SetViaDrill(int aDrill)
Push and Shove diff pair dimensions (gap) settings dialog.
NODE * GetWorld() const
Definition: pns_router.h:153
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:638
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:207
void SetIterationLimit(const int aIterLimit)
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:31
const LAYER_RANGE & Layers() const
Definition: pns_item.h:154
DP_PRIMITIVE_PAIR EndingPrimitives()
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
void SetNets(int aP, int aN)
bool rhMarkObstacles(const VECTOR2I &aP)
VECTOR2I B
Definition: seg.h:49