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 <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 = 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;
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 
75 const VIA DIFF_PAIR_PLACER::makeVia( const VECTOR2I& aP, int aNet )
76 {
78 
79  VIA v( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), -1, m_sizes.ViaType() );
80  v.SetNet( aNet );
81 
82  return v;
83 }
84 
85 
86 void DIFF_PAIR_PLACER::SetOrthoMode ( bool aOrthoMode )
87 {
88  m_orthoMode = aOrthoMode;
89 
90  if( !m_idle )
91  Move( m_currentEnd, nullptr );
92 }
93 
94 
95 bool DIFF_PAIR_PLACER::ToggleVia( bool aEnabled )
96 {
97  m_placingVia = aEnabled;
98 
99  if( !m_idle )
100  Move( m_currentEnd, nullptr );
101 
102  return true;
103 }
104 
105 
107 {
108  if( !routeHead( aP ) )
109  return false;
110 
111  bool collP = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.PLine() ) );
112  bool collN = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.NLine() ) );
113 
114  m_fitOk = !( collP || collN ) ;
115 
116  return m_fitOk;
117 }
118 
119 
121 {
122  VIA virtHead = makeVia( aP, -1 );
123 
124  if( m_placingVia )
125  {
126  virtHead.SetDiameter( viaGap() + 2 * virtHead.Diameter() );
127  }
128  else
129  {
130  virtHead.SetLayer( m_currentLayer );
131  virtHead.SetDiameter( m_sizes.DiffPairGap() + 2 * m_sizes.DiffPairWidth() );
132  }
133 
134  bool solidsOnly = true;
135 
137  {
138  aNewP = aP;
139  return true;
140  }
141  else if( m_currentMode == RM_Walkaround )
142  {
143  solidsOnly = false;
144  }
145 
146  // fixme: I'm too lazy to do it well. Circular approximaton will do for the moment.
147 
148  // Note: this code is lifted from VIA::PushoutForce and then optimized for this use case and to
149  // check proper clearances to the diff pair line. It can be removed if some specialized
150  // pushout for traces / diff pairs is implemented. Just calling VIA::PushoutForce does not work
151  // as the via may have different resolved clearance to items than the diff pair should.
152  int maxIter = 40;
153  int iter = 0;
154  bool collided = false;
155  VECTOR2I force, totalForce;
156  std::set<ITEM*> handled;
157 
158  while( iter < maxIter )
159  {
160  NODE::OPT_OBSTACLE obs = m_currentNode->CheckColliding( &virtHead, solidsOnly ?
161  ITEM::SOLID_T :
162  ITEM::ANY_T );
163  if( !obs || handled.count( obs->m_item ) )
164  break;
165 
166  int clearance = m_currentNode->GetClearance( obs->m_item, &m_currentTrace.PLine() );
167 
168  if( obs->m_item->Shape()->Collide( virtHead.Shape(), clearance, &force ) )
169  {
170  collided = true;
171  totalForce += force;
172  virtHead.SetPos( virtHead.Pos() + force );
173  }
174 
175  handled.insert( obs->m_item );
176 
177  iter++;
178  }
179 
180  bool succeeded = ( !collided || iter != maxIter );
181 
182  if( succeeded )
183  {
184  aNewP = aP + force;
185  return true;
186  }
187 
188  return false;
189 }
190 
191 
192 bool DIFF_PAIR_PLACER::attemptWalk( NODE* aNode, DIFF_PAIR* aCurrent, DIFF_PAIR& aWalk,
193  bool aPFirst, bool aWindCw, bool aSolidsOnly )
194 {
195  WALKAROUND walkaround( aNode, Router() );
197 
198  walkaround.SetSolidsOnly( aSolidsOnly );
199  walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
200 
201  SHOVE shove( aNode, Router() );
202  LINE walkP, walkN;
203 
204  aWalk = *aCurrent;
205 
206  int iter = 0;
207 
208  DIFF_PAIR cur( *aCurrent );
209 
210  bool currentIsP = aPFirst;
211 
212  int mask = aSolidsOnly ? ITEM::SOLID_T : ITEM::ANY_T;
213 
214  do
215  {
216  LINE preWalk = ( currentIsP ? cur.PLine() : cur.NLine() );
217  LINE preShove = ( currentIsP ? cur.NLine() : cur.PLine() );
218  LINE postWalk;
219 
220  if( !aNode->CheckColliding ( &preWalk, mask ) )
221  {
222  currentIsP = !currentIsP;
223 
224  if( !aNode->CheckColliding( &preShove, mask ) )
225  break;
226  else
227  continue;
228  }
229 
230  wf1 = walkaround.Route( preWalk, postWalk, false );
231 
232  if( wf1 != WALKAROUND::DONE )
233  return false;
234 
235  LINE postShove( preShove );
236 
237  shove.ForceClearance( true, cur.Gap() - 2 * PNS_HULL_MARGIN );
238 
240 
241  sh1 = shove.ShoveObstacleLine( postWalk, preShove, postShove );
242 
243  if( sh1 != SHOVE::SH_OK )
244  return false;
245 
246  postWalk.Line().Simplify();
247  postShove.Line().Simplify();
248 
249  cur.SetShape( postWalk.CLine(), postShove.CLine(), !currentIsP );
250 
251  currentIsP = !currentIsP;
252 
253  if( !aNode->CheckColliding( &postShove, mask ) )
254  break;
255 
256  iter++;
257  }
258  while( iter < 3 );
259 
260  if( iter == 3 )
261  return false;
262 
263  aWalk.SetShape( cur.CP(), cur.CN() );
264 
265  return true;
266 }
267 
268 
269 bool DIFF_PAIR_PLACER::tryWalkDp( NODE* aNode, DIFF_PAIR &aPair, bool aSolidsOnly )
270 {
271  DIFF_PAIR best;
272  double bestScore = 100000000000000.0;
273 
274  for( int attempt = 0; attempt <= 3; attempt++ )
275  {
276  DIFF_PAIR p;
277  NODE *tmp = m_currentNode->Branch();
278 
279  bool pfirst = ( attempt & 1 ) ? true : false;
280  bool wind_cw = ( attempt & 2 ) ? true : false;
281 
282  if( attemptWalk( tmp, &aPair, p, pfirst, wind_cw, aSolidsOnly ) )
283  {
284  // double len = p.TotalLength();
285  double cl = p.CoupledLength();
286  double skew = p.Skew();
287 
288  double score = cl + fabs( skew ) * 3.0;
289 
290  if( score < bestScore )
291  {
292  bestScore = score;
293  best = p;
294  }
295  }
296 
297  delete tmp;
298  }
299 
300  if( bestScore > 0.0 )
301  {
302  OPTIMIZER optimizer( m_currentNode );
303 
304  aPair.SetShape( best );
305  optimizer.Optimize( &aPair );
306 
307  return true;
308  }
309 
310  return false;
311 }
312 
313 
315 {
316  if( !routeHead ( aP ) )
317  return false;
318 
320 
321  return m_fitOk;
322 }
323 
324 
326 {
327  switch( m_currentMode )
328  {
329  case RM_MarkObstacles:
330  return rhMarkObstacles( aP );
331  case RM_Walkaround:
332  return rhWalkOnly( aP );
333  case RM_Shove:
334  return rhShoveOnly( aP );
335  default:
336  break;
337  }
338 
339  return false;
340 }
341 
342 
344 {
346 
347  bool ok = routeHead( aP );
348 
349  m_fitOk = false;
350 
351  if( !ok )
352  return false;
353 
354  if( !tryWalkDp( m_currentNode, m_currentTrace, true ) )
355  return false;
356 
357  LINE pLine( m_currentTrace.PLine() );
358  LINE nLine( m_currentTrace.NLine() );
359  ITEM_SET head;
360 
361  head.Add( &pLine );
362  head.Add( &nLine );
363 
364  SHOVE::SHOVE_STATUS status = m_shove->ShoveMultiLines( head );
365 
367 
368  if( status == SHOVE::SH_OK )
369  {
371 
374  {
375  m_fitOk = true;
376  }
377  }
378 
379  return m_fitOk;
380 }
381 
382 
384 {
385  ITEM_SET t;
386 
387  t.Add( &m_currentTrace.PLine() );
388  t.Add( &m_currentTrace.NLine() );
389 
390  return t;
391 }
392 
393 
395 {
397 
398  if( !m_idle )
399  Move( m_currentEnd, nullptr );
400 }
401 
402 
403 NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
404 {
405  if( m_lastNode )
406  return m_lastNode;
407 
408  return m_currentNode;
409 }
410 
411 
412 bool DIFF_PAIR_PLACER::SetLayer( int aLayer )
413 {
414  if( m_idle )
415  {
416  m_currentLayer = aLayer;
417  return true;
418  }
419  else if( m_chainedPlacement || !m_prevPair )
420  {
421  return false;
422  }
423  else if( !m_prevPair->PrimP() || ( m_prevPair->PrimP()->OfKind( ITEM::VIA_T ) &&
424  m_prevPair->PrimP()->Layers().Overlaps( aLayer ) ) )
425  {
426  m_currentLayer = aLayer;
427  m_start = *m_prevPair;
428  initPlacement();
429  Move( m_currentEnd, nullptr );
430  return true;
431  }
432 
433  return false;
434 }
435 
436 
438 {
439  switch( aItem->Kind() )
440  {
441  case ITEM::VIA_T:
442  case ITEM::SOLID_T:
443  return aItem->Anchor( 0 );
444 
445  case ITEM::ARC_T:
446  case ITEM::SEGMENT_T:
447  {
448  SEGMENT* s = static_cast<SEGMENT*>( aItem );
449 
450  JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
451  JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
452 
453  if( jA && jA->LinkCount() == 1 )
454  return s->Seg().A;
455  else if( jB && jB->LinkCount() == 1 )
456  return s->Seg().B;
457  else
458  return OPT_VECTOR2I();
459  }
460 
461  default:
462  return OPT_VECTOR2I();
463  }
464 }
465 
466 
467 
468 bool DIFF_PAIR_PLACER::FindDpPrimitivePair( NODE* aWorld, const VECTOR2I& aP, ITEM* aItem,
469  DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
470 {
471  int netP, netN;
472 
473  bool result = aWorld->GetRuleResolver()->DpNetPair( aItem, netP, netN );
474 
475  if( !result )
476  {
477  if( aErrorMsg )
478  {
479  *aErrorMsg = _( "Unable to find complementary differential pair "
480  "nets. Make sure the names of the nets belonging "
481  "to a differential pair end with either N/P or +/-." );
482  }
483  return false;
484  }
485 
486  int refNet = aItem->Net();
487  int coupledNet = ( refNet == netP ) ? netN : netP;
488 
489  OPT_VECTOR2I refAnchor = getDanglingAnchor( aWorld, aItem );
490  ITEM* primRef = aItem;
491 
492  if( !refAnchor )
493  {
494  if( aErrorMsg )
495  {
496  *aErrorMsg = _( "Can't find a suitable starting point. If starting "
497  "from an existing differential pair make sure you are "
498  "at the end." );
499  }
500 
501  return false;
502  }
503 
504  std::set<ITEM*> coupledItems;
505 
506  aWorld->AllItemsInNet( coupledNet, coupledItems );
507  double bestDist = std::numeric_limits<double>::max();
508  bool found = false;
509 
510  for( ITEM* item : coupledItems )
511  {
512  if( item->Kind() == aItem->Kind() )
513  {
514  OPT_VECTOR2I anchor = getDanglingAnchor( aWorld, item );
515 
516  if( !anchor )
517  continue;
518 
519  double dist = ( *anchor - *refAnchor ).EuclideanNorm();
520 
521  bool shapeMatches = true;
522 
523  if( item->OfKind( ITEM::SOLID_T | ITEM::VIA_T ) && item->Layers() != aItem->Layers() )
524  {
525  shapeMatches = false;
526  }
527 
528  if( dist < bestDist && shapeMatches )
529  {
530  found = true;
531  bestDist = dist;
532 
533  if( refNet != netP )
534  {
535  aPair = DP_PRIMITIVE_PAIR ( item, primRef );
536  aPair.SetAnchors( *anchor, *refAnchor );
537  }
538  else
539  {
540  aPair = DP_PRIMITIVE_PAIR( primRef, item );
541  aPair.SetAnchors( *refAnchor, *anchor );
542  }
543  }
544  }
545  }
546 
547  if( !found )
548  {
549  if( aErrorMsg )
550  {
551  *aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
552  "for coupled net \"%s\"." ),
553  aWorld->GetRuleResolver()->NetName( coupledNet ) );
554  }
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;
596 
597  initPlacement();
598 
599  return true;
600 }
601 
602 
604 {
605  m_idle = false;
606  m_orthoMode = false;
607  m_currentEndItem = nullptr;
609 
610  NODE* world = Router()->GetWorld();
611 
612  world->KillChildren();
613  NODE* rootNode = world->Branch();
614 
615  setWorld( rootNode );
616 
617  m_lastNode = nullptr;
618  m_currentNode = rootNode;
620 
621  if( m_shove )
622  delete m_shove;
623 
624  m_shove = nullptr;
625 
627  {
628  m_shove = new SHOVE( m_currentNode, Router() );
629  }
630 }
631 
632 
634 {
635  m_fitOk = false;
636 
637  DP_GATEWAYS gwsEntry( gap() );
638  DP_GATEWAYS gwsTarget( gap() );
639 
640  if( !m_prevPair )
642 
644 
645  DP_PRIMITIVE_PAIR target;
646 
648  {
649  gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
650  m_snapOnTarget = true;
651  }
652  else
653  {
654  VECTOR2I fp;
655 
656  if( !propagateDpHeadForces( aP, fp ) )
657  return false;
658 
659  VECTOR2I midp, dirV;
660  m_prevPair->CursorOrientation( fp, midp, dirV );
661 
662  VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp );
663 
664  // compute 'leader point' distance from the cursor (project cursor position
665  // on the extension of the starting segment pair of the DP)
666  int lead_dist = ( fpProj - fp ).EuclideanNorm();
667 
668  gwsTarget.SetFitVias( m_placingVia, m_sizes.ViaDiameter(), viaGap() );
669 
670  // far from the initial segment extension line -> allow a 45-degree obtuse turn
671  if( lead_dist > ( m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() ) / 2 )
672  {
673  gwsTarget.BuildForCursor( fp );
674  }
675  else
676  {
677  // close to the initial segment extension line -> keep straight part only, project
678  // as close as possible to the cursor.
679  gwsTarget.BuildForCursor( fpProj );
681  DIRECTION_45( dirV ) );
682  }
683 
684  m_snapOnTarget = false;
685  }
686 
689 
690  bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace );
691 
692  if( result )
693  {
694  m_currentTraceOk = true;
698 
699  if( m_placingVia )
700  {
702  makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) );
703  }
704 
705  return true;
706  }
707 
708  return m_currentTraceOk;
709 }
710 
711 
712 bool DIFF_PAIR_PLACER::Move( const VECTOR2I& aP , ITEM* aEndItem )
713 {
714  m_currentEndItem = aEndItem;
715  m_fitOk = false;
716 
717  delete m_lastNode;
718  m_lastNode = nullptr;
719 
720  bool retval = route( aP );
721 
722  NODE* latestNode = m_currentNode;
723  m_lastNode = latestNode->Branch();
724 
725  assert( m_lastNode != nullptr );
726  m_currentEnd = aP;
727 
729 
730  return retval;
731 }
732 
733 
735 {
736  m_sizes = aSizes;
737 
738  if( !m_idle )
739  {
742 
744  {
747  }
748  }
749 }
750 
751 
752 bool DIFF_PAIR_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
753 {
754  if( !m_fitOk && !Settings().AllowDRCViolations() )
755  return false;
756 
758  return false;
759 
760  if( m_currentTrace.CP().SegmentCount() > 1 )
761  m_initialDiagonal = !DIRECTION_45( m_currentTrace.CP().CSegment( -2 ) ).IsDiagonal();
762 
763  TOPOLOGY topo( m_lastNode );
764 
765  if( !m_snapOnTarget && !m_currentTrace.EndsWithVias() && !aForceFinish &&
767  {
770 
771  if( newP.SegmentCount() > 1 && newN.SegmentCount() > 1 )
772  {
773  newP.Remove( -1, -1 );
774  newN.Remove( -1, -1 );
775  }
776 
777  m_currentTrace.SetShape( newP, newN );
778  }
779 
781  {
784  m_chainedPlacement = false;
785  }
786  else
787  {
788  m_chainedPlacement = !m_snapOnTarget && !aForceFinish;
789  }
790 
791  LINE lineP( m_currentTrace.PLine() );
792  LINE lineN( m_currentTrace.NLine() );
793 
794  m_lastNode->Add( lineP );
795  m_lastNode->Add( lineN );
796 
797  topo.SimplifyLine( &lineP );
798  topo.SimplifyLine( &lineN );
799 
801 
802  CommitPlacement();
803  m_placingVia = false;
804 
805  if( m_snapOnTarget || aForceFinish )
806  {
807  m_idle = true;
808  return true;
809  }
810  else
811  {
812  initPlacement();
813  return false;
814  }
815 }
816 
817 
819 {
821  return true;
822 }
823 
824 
826 {
827  return m_currentTrace.CP().SegmentCount() > 0 || m_currentTrace.CN().SegmentCount() > 0;
828 }
829 
830 
832 {
833  if( m_lastNode )
835 
836  m_lastNode = nullptr;
837  m_currentNode = nullptr;
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)
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:155
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:693
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:393
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:128
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
void SetNet(int aNet)
Definition: pns_item.h:149
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:1399
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:150
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
#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:1134
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: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:215
Definition: seg.h:40
Basic class for a differential 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: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:265
Represent a polyline (an zero-thickness chain of connected line segments).
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems, int aKindMask=-1)
Definition: pns_node.cpp:1405
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:128
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:1516
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
NODE * CurrentNode()
Definition: pns_shove.cpp:1787
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:152
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