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 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
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 = NULL;
44  m_shove = NULL;
46  m_lastNode = NULL;
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;
58  m_currentTraceOk = false;
59  m_idle = true;
60 }
61 
63 {
64  if( m_shove )
65  delete m_shove;
66 }
67 
68 
70 {
71  m_world = aWorld;
72 }
73 
74 const VIA DIFF_PAIR_PLACER::makeVia( const VECTOR2I& aP, int aNet )
75 {
77 
78  VIA v( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), -1, m_sizes.ViaType() );
79  v.SetNet( aNet );
80 
81  return v;
82 }
83 
84 
85 void DIFF_PAIR_PLACER::SetOrthoMode ( bool aOrthoMode )
86 {
87  m_orthoMode = aOrthoMode;
88 
89  if( !m_idle )
91 }
92 
93 
94 bool DIFF_PAIR_PLACER::ToggleVia( bool aEnabled )
95 {
96  m_placingVia = aEnabled;
97 
98  if( !m_idle )
100 
101  return true;
102 }
103 
104 
106 {
107  if( !routeHead( aP ) )
108  return false;
109 
110  bool collP = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.PLine() ) );
111  bool collN = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.NLine() ) );
112 
113  m_fitOk = !( collP || collN ) ;
114 
115  return m_fitOk;
116 }
117 
118 
120 {
121  VIA virtHead = makeVia( aP, -1 );
122 
123  if( m_placingVia )
124  virtHead.SetDiameter( viaGap() + 2 * virtHead.Diameter() );
125  else
126  {
127  virtHead.SetLayer( m_currentLayer );
128  virtHead.SetDiameter( m_sizes.DiffPairGap() + 2 * m_sizes.DiffPairWidth() );
129  }
130 
131  bool solidsOnly = true;
132 
134  {
135  aNewP = aP;
136  return true;
137  }
138  else if( m_currentMode == RM_Walkaround )
139  {
140  solidsOnly = false;
141  }
142 
143  // fixme: I'm too lazy to do it well. Circular approximaton will do for the moment.
144 
145  // Note: this code is lifted from VIA::PushoutForce and then optimized for this use case and to
146  // check proper clearances to the diff pair line. It can be removed if some specialized
147  // pushout for traces / diff pairs is implemented. Just calling VIA::PushoutForce does not work
148  // as the via may have different resolved clearance to items than the diff pair should.
149  int maxIter = 40;
150  int iter = 0;
151  bool collided = false;
152  VECTOR2I force, totalForce;
153  std::set<ITEM*> handled;
154 
155  while( iter < maxIter )
156  {
157  NODE::OPT_OBSTACLE obs = m_currentNode->CheckColliding( &virtHead, solidsOnly ?
158  ITEM::SOLID_T :
159  ITEM::ANY_T );
160  if( !obs || handled.count( obs->m_item ) )
161  break;
162 
163  int clearance = m_currentNode->GetClearance( obs->m_item, &m_currentTrace.PLine() );
164 
165  if( obs->m_item->Shape()->Collide( virtHead.Shape(), clearance, &force ) )
166  {
167  collided = true;
168  totalForce += force;
169  virtHead.SetPos( virtHead.Pos() + force );
170  }
171 
172  handled.insert( obs->m_item );
173 
174  iter++;
175  }
176 
177  bool succeeded = ( !collided || iter != maxIter );
178 
179  if( succeeded )
180  {
181  aNewP = aP + force;
182  return true;
183  }
184 
185  return false;
186 }
187 
188 
190  DIFF_PAIR& aWalk, bool aPFirst, bool aWindCw, bool aSolidsOnly )
191 {
192  WALKAROUND walkaround( aNode, Router() );
194 
195  walkaround.SetSolidsOnly( aSolidsOnly );
196  walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
197 
198  SHOVE shove( aNode, Router() );
199  LINE walkP, walkN;
200 
201  aWalk = *aCurrent;
202 
203  int iter = 0;
204 
205  DIFF_PAIR cur( *aCurrent );
206 
207  bool currentIsP = aPFirst;
208 
209  int mask = aSolidsOnly ? ITEM::SOLID_T : ITEM::ANY_T;
210 
211  do
212  {
213  LINE preWalk = ( currentIsP ? cur.PLine() : cur.NLine() );
214  LINE preShove = ( currentIsP ? cur.NLine() : cur.PLine() );
215  LINE postWalk;
216 
217  if( !aNode->CheckColliding ( &preWalk, mask ) )
218  {
219  currentIsP = !currentIsP;
220 
221  if( !aNode->CheckColliding( &preShove, mask ) )
222  break;
223  else
224  continue;
225  }
226 
227  wf1 = walkaround.Route( preWalk, postWalk, false );
228 
229  if( wf1 != WALKAROUND::DONE )
230  return false;
231 
232  LINE postShove( preShove );
233 
234  shove.ForceClearance( true, cur.Gap() - 2 * PNS_HULL_MARGIN );
235 
237 
238  sh1 = shove.ShoveObstacleLine( postWalk, preShove, postShove );
239 
240  if( sh1 != SHOVE::SH_OK )
241  return false;
242 
243  postWalk.Line().Simplify();
244  postShove.Line().Simplify();
245 
246  cur.SetShape( postWalk.CLine(), postShove.CLine(), !currentIsP );
247 
248  currentIsP = !currentIsP;
249 
250  if( !aNode->CheckColliding( &postShove, mask ) )
251  break;
252 
253  iter++;
254  }
255  while( iter < 3 );
256 
257  if( iter == 3 )
258  return false;
259 
260  aWalk.SetShape( cur.CP(), cur.CN() );
261 
262  return true;
263 }
264 
265 
266 bool DIFF_PAIR_PLACER::tryWalkDp( NODE* aNode, DIFF_PAIR &aPair, bool aSolidsOnly )
267 {
268  DIFF_PAIR best;
269  double bestScore = 100000000000000.0;
270 
271  for( int attempt = 0; attempt <= 3; attempt++ )
272  {
273  DIFF_PAIR p;
274  NODE *tmp = m_currentNode->Branch();
275 
276  bool pfirst = ( attempt & 1 ) ? true : false;
277  bool wind_cw = ( attempt & 2 ) ? true : false;
278 
279  if( attemptWalk( tmp, &aPair, p, pfirst, wind_cw, aSolidsOnly ) )
280  {
281  // double len = p.TotalLength();
282  double cl = p.CoupledLength();
283  double skew = p.Skew();
284 
285  double score = cl + fabs( skew ) * 3.0;
286 
287  if( score < bestScore )
288  {
289  bestScore = score;
290  best = p;
291  }
292  }
293 
294  delete tmp;
295  }
296 
297  if( bestScore > 0.0 )
298  {
299  OPTIMIZER optimizer( m_currentNode );
300 
301  aPair.SetShape( best );
302  optimizer.Optimize( &aPair );
303 
304  return true;
305  }
306 
307  return false;
308 }
309 
310 
312 {
313  if( !routeHead ( aP ) )
314  return false;
315 
317 
318  return m_fitOk;
319 }
320 
321 
323 {
324  switch( m_currentMode )
325  {
326  case RM_MarkObstacles:
327  return rhMarkObstacles( aP );
328  case RM_Walkaround:
329  return rhWalkOnly( aP );
330  case RM_Shove:
331  return rhShoveOnly( aP );
332  default:
333  break;
334  }
335 
336  return false;
337 }
338 
339 
341 {
343 
344  bool ok = routeHead( aP );
345 
346  m_fitOk = false;
347 
348  if( !ok )
349  return false;
350 
351  if( !tryWalkDp( m_currentNode, m_currentTrace, true ) )
352  return false;
353 
354  LINE pLine( m_currentTrace.PLine() );
355  LINE nLine( m_currentTrace.NLine() );
356  ITEM_SET head;
357 
358  head.Add( &pLine );
359  head.Add( &nLine );
360 
361  SHOVE::SHOVE_STATUS status = m_shove->ShoveMultiLines( head );
362 
364 
365  if( status == SHOVE::SH_OK )
366  {
368 
371  {
372  m_fitOk = true;
373  }
374  }
375 
376  return m_fitOk;
377 }
378 
379 
381 {
382  ITEM_SET t;
383 
384  t.Add( &m_currentTrace.PLine() );
385  t.Add( &m_currentTrace.NLine() );
386 
387  return t;
388 }
389 
390 
392 {
394 
395  if( !m_idle )
396  Move( m_currentEnd, NULL );
397 }
398 
399 
400 NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
401 {
402  if( m_lastNode )
403  return m_lastNode;
404 
405  return m_currentNode;
406 }
407 
408 
409 bool DIFF_PAIR_PLACER::SetLayer( int aLayer )
410 {
411  if( m_idle )
412  {
413  m_currentLayer = aLayer;
414  return true;
415  }
416  else if( m_chainedPlacement || !m_prevPair )
417  {
418  return false;
419  }
420  else if( !m_prevPair->PrimP() || ( m_prevPair->PrimP()->OfKind( ITEM::VIA_T ) &&
421  m_prevPair->PrimP()->Layers().Overlaps( aLayer ) ) )
422  {
423  m_currentLayer = aLayer;
424  m_start = *m_prevPair;
425  initPlacement();
426  Move( m_currentEnd, NULL );
427  return true;
428  }
429 
430  return false;
431 }
432 
433 
435 {
436  switch( aItem->Kind() )
437  {
438  case ITEM::VIA_T:
439  case ITEM::SOLID_T:
440  return aItem->Anchor( 0 );
441 
442  case ITEM::ARC_T:
443  case ITEM::SEGMENT_T:
444  {
445  SEGMENT* s = static_cast<SEGMENT*>( aItem );
446 
447  JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
448  JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
449 
450  if( jA && jA->LinkCount() == 1 )
451  return s->Seg().A;
452  else if( jB && jB->LinkCount() == 1 )
453  return s->Seg().B;
454  else
455  return OPT_VECTOR2I();
456  }
457 
458  default:
459  return OPT_VECTOR2I();
460  }
461 }
462 
463 
464 
465 bool DIFF_PAIR_PLACER::FindDpPrimitivePair( NODE* aWorld, const VECTOR2I& aP, ITEM* aItem,
466  DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
467 {
468  int netP, netN;
469 
470  wxLogTrace( "PNS", "world %p", aWorld );
471 
472  bool result = aWorld->GetRuleResolver()->DpNetPair( aItem, netP, netN );
473 
474  if( !result )
475  {
476  if( aErrorMsg )
477  {
478  *aErrorMsg = _( "Unable to find complementary differential pair "
479  "nets. Make sure the names of the nets belonging "
480  "to a differential pair end with either N/P or +/-." );
481  }
482  return false;
483  }
484 
485  int refNet = aItem->Net();
486  int coupledNet = ( refNet == netP ) ? netN : netP;
487 
488  wxLogTrace( "PNS", "result %d", !!result );
489 
490  OPT_VECTOR2I refAnchor = getDanglingAnchor( aWorld, aItem );
491  ITEM* primRef = aItem;
492 
493  wxLogTrace( "PNS", "refAnchor %p", aItem );
494 
495  if( !refAnchor )
496  {
497  if( aErrorMsg )
498  {
499  *aErrorMsg = _( "Can't find a suitable starting point. If starting "
500  "from an existing differential pair make sure you are "
501  "at the end." );
502  }
503  return false;
504  }
505 
506  std::set<ITEM*> coupledItems;
507 
508  aWorld->AllItemsInNet( coupledNet, coupledItems );
509  double bestDist = std::numeric_limits<double>::max();
510  bool found = false;
511 
512  for( ITEM* item : coupledItems )
513  {
514  if( item->Kind() == aItem->Kind() )
515  {
516  OPT_VECTOR2I anchor = getDanglingAnchor( aWorld, item );
517  if( !anchor )
518  continue;
519 
520  double dist = ( *anchor - *refAnchor ).EuclideanNorm();
521 
522  bool shapeMatches = true;
523 
524  if( item->OfKind( ITEM::SOLID_T ) && item->Layers() != aItem->Layers() )
525  {
526  shapeMatches = false;
527  }
528 
529  if( dist < bestDist && shapeMatches )
530  {
531  found = true;
532  bestDist = dist;
533 
534  if( refNet != netP )
535  {
536  aPair = DP_PRIMITIVE_PAIR ( item, primRef );
537  aPair.SetAnchors( *anchor, *refAnchor );
538  }
539  else
540  {
541  aPair = DP_PRIMITIVE_PAIR( primRef, item );
542  aPair.SetAnchors( *refAnchor, *anchor );
543  }
544  }
545  }
546  }
547 
548  if( !found )
549  {
550  if( aErrorMsg )
551  {
552  *aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
553  "for coupled net \"%s\"." ),
554  aWorld->GetRuleResolver()->NetName( coupledNet ) );
555  }
556  return false;
557  }
558 
559  return true;
560 }
561 
562 
564 {
565  return std::max( m_sizes.DiffPairViaGap(),
567 }
568 
569 
571 {
573 }
574 
575 
576 bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
577 {
578  VECTOR2I p( aP );
579 
580  setWorld( Router()->GetWorld() );
582 
583  if( !FindDpPrimitivePair( m_currentNode, aP, aStartItem, m_start ) )
584  return false;
585 
586  m_netP = m_start.PrimP()->Net();
587  m_netN = m_start.PrimN()->Net();
588 
589  m_currentStart = p;
590  m_currentEnd = p;
591  m_placingVia = false;
592  m_chainedPlacement = false;
593  m_currentTraceOk = false;
595 
596  initPlacement();
597 
598  return true;
599 }
600 
601 
603 {
604  m_idle = false;
605  m_orthoMode = false;
608 
609  NODE* world = Router()->GetWorld();
610 
611  world->KillChildren();
612  NODE* rootNode = world->Branch();
613 
614  setWorld( rootNode );
615 
616  m_lastNode = NULL;
617  m_currentNode = rootNode;
619 
620  if( m_shove )
621  delete m_shove;
622 
623  m_shove = NULL;
624 
626  {
627  m_shove = new SHOVE( m_currentNode, Router() );
628  }
629 }
630 
631 
633 {
634  m_fitOk = false;
635 
636  DP_GATEWAYS gwsEntry( gap() );
637  DP_GATEWAYS gwsTarget( gap() );
638 
639  if( !m_prevPair )
641 
643 
644  DP_PRIMITIVE_PAIR target;
645 
647  {
648  gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
649  m_snapOnTarget = true;
650  }
651  else
652  {
653  VECTOR2I fp;
654 
655  if( !propagateDpHeadForces( aP, fp ) )
656  return false;
657 
658  VECTOR2I midp, dirV;
659  m_prevPair->CursorOrientation( fp, midp, dirV );
660 
661  VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp );
662 
663  // compute 'leader point' distance from the cursor (project cursor position
664  // on the extension of the starting segment pair of the DP)
665  int lead_dist = ( fpProj - fp ).EuclideanNorm();
666 
667  gwsTarget.SetFitVias( m_placingVia, m_sizes.ViaDiameter(), viaGap() );
668 
669  // far from the initial segment extension line -> allow a 45-degree obtuse turn
670  if( lead_dist > ( m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() ) / 2 )
671  {
672  gwsTarget.BuildForCursor( fp );
673  }
674  // close to the initial segment extension line -> keep straight part only, project as close
675  // as possible to the cursor
676  else
677  {
678  gwsTarget.BuildForCursor( fpProj );
680  DIRECTION_45( dirV ) );
681  }
682 
683  m_snapOnTarget = false;
684  }
685 
688 
689  bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace );
690 
691  if( result )
692  {
693  m_currentTraceOk = true;
697 
698  if( m_placingVia )
699  {
701  makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) );
702  }
703 
704  return true;
705  }
706 
707  return m_currentTraceOk;
708 }
709 
710 
711 bool DIFF_PAIR_PLACER::Move( const VECTOR2I& aP , ITEM* aEndItem )
712 {
713  m_currentEndItem = aEndItem;
714  m_fitOk = false;
715 
716  delete m_lastNode;
717  m_lastNode = NULL;
718 
719  bool retval = route( aP );
720 
721  NODE* latestNode = m_currentNode;
722  m_lastNode = latestNode->Branch();
723 
724  assert( m_lastNode != NULL );
725  m_currentEnd = aP;
726 
728 
729  return retval;
730 }
731 
732 
734 {
735  m_sizes = aSizes;
736 
737  if( !m_idle )
738  {
741 
743  {
746  }
747  }
748 }
749 
750 
751 bool DIFF_PAIR_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
752 {
753  if( !m_fitOk && !Settings().AllowDRCViolations() )
754  return false;
755 
757  return false;
758 
759  if( m_currentTrace.CP().SegmentCount() > 1 )
760  m_initialDiagonal = !DIRECTION_45( m_currentTrace.CP().CSegment( -2 ) ).IsDiagonal();
761 
762  TOPOLOGY topo( m_lastNode );
763 
764  if( !m_snapOnTarget && !m_currentTrace.EndsWithVias() && !aForceFinish &&
766  {
769 
770  if( newP.SegmentCount() > 1 && newN.SegmentCount() > 1 )
771  {
772  newP.Remove( -1, -1 );
773  newN.Remove( -1, -1 );
774  }
775 
776  m_currentTrace.SetShape( newP, newN );
777  }
778 
780  {
783  m_chainedPlacement = false;
784  }
785  else
786  {
787  m_chainedPlacement = !m_snapOnTarget && !aForceFinish;
788  }
789 
790  LINE lineP( m_currentTrace.PLine() );
791  LINE lineN( m_currentTrace.NLine() );
792 
793  m_lastNode->Add( lineP );
794  m_lastNode->Add( lineN );
795 
796  topo.SimplifyLine( &lineP );
797  topo.SimplifyLine( &lineN );
798 
800 
801  CommitPlacement();
802  m_placingVia = false;
803 
804  if( m_snapOnTarget || aForceFinish )
805  {
806  m_idle = true;
807  return true;
808  }
809  else
810  {
811  initPlacement();
812  return false;
813  }
814 }
815 
816 
818 {
820  return true;
821 }
822 
823 
825 {
826  return m_currentTrace.CP().SegmentCount() > 0 ||
828 }
829 
830 
832 {
833  if( m_lastNode )
835 
836  m_lastNode = NULL;
838  return true;
839 }
840 
841 
842 void DIFF_PAIR_PLACER::GetModifiedNets( std::vector<int> &aNets ) const
843 {
844  aNets.push_back( m_netP );
845  aNets.push_back( m_netN );
846 }
847 
848 
850 {
851  SHAPE_LINE_CHAIN ratLineN, ratLineP;
852  TOPOLOGY topo( m_lastNode );
853 
854  if( topo.LeadingRatLine( &m_currentTrace.PLine(), ratLineP ) )
855  m_router->GetInterface()->DisplayRatline( ratLineP, 1 );
856 
857  if( topo.LeadingRatLine ( &m_currentTrace.NLine(), ratLineN ) )
858  m_router->GetInterface()->DisplayRatline( ratLineN, 3 );
859 }
860 
861 
862 const std::vector<int> DIFF_PAIR_PLACER::CurrentNets() const
863 {
864  std::vector<int> rv;
865  rv.push_back( m_netP );
866  rv.push_back( m_netN );
867  return rv;
868 }
869 
870 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:148
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:144
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)
SHOVE.
Definition: pns_shove.h:48
int Gap() const
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Function Simplify()
void GetModifiedNets(std::vector< int > &aNets) const override
Function GetModifiedNets.
void SetLayer(int aLayer)
Definition: pns_item.h:153
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:664
const SHAPE_LINE_CHAIN & CN() const
int m_iteration
pointer to world to search colliding items
void FilterByOrientation(int aAngleMask, DIRECTION_45 aRefOrientation)
SHOVE * m_shove
Current world state.
#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:371
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:125
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:124
const VECTOR2I & Pos() const
Definition: pns_via.h:96
ITEM * PrimP() const
void SetNet(int aNet)
Definition: pns_item.h:147
VIATYPE ViaType() const
int m_viaDrill
current track width
void SetDiameter(int aDiameter)
Definition: pns_via.h:110
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
const VECTOR2I & CPoint(int aIndex) const
Function Point()
bool HasPlacedAnything() const override
Represents a 2D point on a given set of layers and belonging to a certain net, that links together a ...
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:108
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.h:404
ROUTER * m_router
Definition: pns_algo_base.h:87
int GetClearance(const ITEM *aA, const ITEM *aB) const
Definition: pns_node.cpp:97
void KillChildren()
Definition: pns_node.cpp:1306
#define NULL
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:39
bool ToggleVia(bool aEnabled) override
Enable/disable a via at the end of currently routed trace.
int Net() const
Definition: pns_item.h:148
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)
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I aV=VECTOR2I(0, 0))
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.
PNS_MODE Mode() const
Set the routing mode.
bool m_placingVia
current via diameter
DIFF_PAIR_PLACER(ROUTER *aRouter)
void SetViaDiameter(int aDiameter)
void SetSolidsOnly(bool aSolidsOnly)
void SetWidth(int aWidth)
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
double Skew() const
int SegmentCount() const
Function SegmentCount()
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:1041
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:177
void SetPos(const VECTOR2I &aPos)
Definition: pns_via.h:98
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:213
Definition: seg.h:41
DIFF_PAIR.
void FlipPosture() override
Toggle the current posture (straight/diagonal) of the trace head.
Guess what's better, try to make least mess on the PCB.
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:75
ITEM * PrimN() const
DP_PRIMITIVE_PAIR.
const SEG CSegment(int aIndex) const
Function CSegment()
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:257
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1312
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:420
VECTOR2I A
Definition: seg.h:49
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:126
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:147
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
SHOVE_STATUS ShoveMultiLines(const ITEM_SET &aHeadSet)
Definition: pns_shove.cpp:1470
const VIA & Via() const
Definition: pns_line.h:196
DP_GATEWAYS.
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:608
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:210
NODE * CurrentNode()
Definition: pns_shove.cpp:1740
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:150
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:50