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 <class_board.h>
23 #include <class_board_item.h>
24 #include <netinfo.h>
25 
26 #include "pns_node.h"
27 #include "pns_walkaround.h"
28 #include "pns_shove.h"
29 #include "pns_utils.h"
30 #include "pns_router.h"
31 #include "pns_diff_pair_placer.h"
32 #include "pns_solid.h"
33 #include "pns_topology.h"
34 #include "pns_debug_decorator.h"
35 
36 namespace PNS {
37 
39  PLACEMENT_ALGO( aRouter )
40 {
41  m_state = RT_START;
42  m_chainedPlacement = false;
43  m_initialDiagonal = false;
44  m_startDiagonal = false;
45  m_fitOk = false;
46  m_netP = 0;
47  m_netN = 0;
48  m_iteration = 0;
49  m_world = NULL;
50  m_shove = NULL;
52  m_lastNode = NULL;
53  m_placingVia = false;
54  m_viaDiameter = 0;
55  m_viaDrill = 0;
56  m_currentWidth = 0;
57  m_currentNet = 0;
58  m_currentLayer = 0;
59  m_startsOnVia = false;
60  m_orthoMode = false;
61  m_snapOnTarget = false;
64  m_idle = true;
65 }
66 
68 {
69  if( m_shove )
70  delete m_shove;
71 }
72 
73 
75 {
76  m_world = aWorld;
77 }
78 
79 const VIA DIFF_PAIR_PLACER::makeVia( const VECTOR2I& aP, int aNet )
80 {
82 
83  VIA v( aP, layers, m_sizes.ViaDiameter(), m_sizes.ViaDrill(), -1, m_sizes.ViaType() );
84  v.SetNet( aNet );
85 
86  return v;
87 }
88 
89 
90 void DIFF_PAIR_PLACER::SetOrthoMode ( bool aOrthoMode )
91 {
92  m_orthoMode = aOrthoMode;
93 
94  if( !m_idle )
96 }
97 
98 
99 bool DIFF_PAIR_PLACER::ToggleVia( bool aEnabled )
100 {
101  m_placingVia = aEnabled;
102 
103  if( !m_idle )
104  Move( m_currentEnd, NULL );
105 
106  return true;
107 }
108 
109 
111 {
112  if( !routeHead( aP ) )
113  return false;
114 
115  bool collP = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.PLine() ) );
116  bool collN = static_cast<bool>( m_currentNode->CheckColliding( &m_currentTrace.NLine() ) );
117 
118  m_fitOk = !( collP || collN ) ;
119 
120  return m_fitOk;
121 }
122 
123 
125 {
126  VIA virtHead = makeVia( aP, -1 );
127 
128  if( m_placingVia )
129  virtHead.SetDiameter( viaGap() + 2 * virtHead.Diameter() );
130  else
131  {
132  virtHead.SetLayer( m_currentLayer );
133  virtHead.SetDiameter( m_sizes.DiffPairGap() + 2 * m_sizes.DiffPairWidth() );
134  }
135 
136  VECTOR2I lead( 0, 0 );// = aP - m_currentStart ;
137  VECTOR2I force;
138  bool solidsOnly = true;
139 
141  {
142  aNewP = aP;
143  return true;
144  }
145  else if( m_currentMode == RM_Walkaround )
146  {
147  solidsOnly = false;
148  }
149 
150  // fixme: I'm too lazy to do it well. Circular approximaton will do for the moment.
151  if( virtHead.PushoutForce( m_currentNode, lead, force, solidsOnly, 40 ) )
152  {
153  aNewP = aP + force;
154  return true;
155  }
156 
157  return false;
158 }
159 
160 
162  DIFF_PAIR& aWalk, bool aPFirst, bool aWindCw, bool aSolidsOnly )
163 {
164  WALKAROUND walkaround( aNode, Router() );
166 
167  walkaround.SetSolidsOnly( aSolidsOnly );
168  walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
169 
170  SHOVE shove( aNode, Router() );
171  LINE walkP, walkN;
172 
173  aWalk = *aCurrent;
174 
175  int iter = 0;
176 
177  DIFF_PAIR cur( *aCurrent );
178 
179  bool currentIsP = aPFirst;
180 
181  int mask = aSolidsOnly ? ITEM::SOLID_T : ITEM::ANY_T;
182 
183  do
184  {
185  LINE preWalk = ( currentIsP ? cur.PLine() : cur.NLine() );
186  LINE preShove = ( currentIsP ? cur.NLine() : cur.PLine() );
187  LINE postWalk;
188 
189  if( !aNode->CheckColliding ( &preWalk, mask ) )
190  {
191  currentIsP = !currentIsP;
192 
193  if( !aNode->CheckColliding( &preShove, mask ) )
194  break;
195  else
196  continue;
197  }
198 
199  wf1 = walkaround.Route( preWalk, postWalk, false );
200 
201  if( wf1 != WALKAROUND::DONE )
202  return false;
203 
204  LINE postShove( preShove );
205 
206  shove.ForceClearance( true, cur.Gap() - 2 * PNS_HULL_MARGIN );
207 
209 
210  sh1 = shove.ProcessSingleLine( postWalk, preShove, postShove );
211 
212  if( sh1 != SHOVE::SH_OK )
213  return false;
214 
215  postWalk.Line().Simplify();
216  postShove.Line().Simplify();
217 
218  cur.SetShape( postWalk.CLine(), postShove.CLine(), !currentIsP );
219 
220  currentIsP = !currentIsP;
221 
222  if( !aNode->CheckColliding( &postShove, mask ) )
223  break;
224 
225  iter++;
226  }
227  while( iter < 3 );
228 
229  if( iter == 3 )
230  return false;
231 
232  aWalk.SetShape( cur.CP(), cur.CN() );
233 
234  return true;
235 }
236 
237 
238 bool DIFF_PAIR_PLACER::tryWalkDp( NODE* aNode, DIFF_PAIR &aPair, bool aSolidsOnly )
239 {
240  DIFF_PAIR best;
241  double bestScore = 100000000000000.0;
242 
243  for( int attempt = 0; attempt <= 3; attempt++ )
244  {
245  DIFF_PAIR p;
246  NODE *tmp = m_currentNode->Branch();
247 
248  bool pfirst = ( attempt & 1 ) ? true : false;
249  bool wind_cw = ( attempt & 2 ) ? true : false;
250 
251  if( attemptWalk( tmp, &aPair, p, pfirst, wind_cw, aSolidsOnly ) )
252  {
253  // double len = p.TotalLength();
254  double cl = p.CoupledLength();
255  double skew = p.Skew();
256 
257  double score = cl + fabs( skew ) * 3.0;
258 
259  if( score < bestScore )
260  {
261  bestScore = score;
262  best = p;
263  }
264  }
265 
266  delete tmp;
267  }
268 
269  if( bestScore > 0.0 )
270  {
271  OPTIMIZER optimizer( m_currentNode );
272 
273  aPair.SetShape( best );
274  optimizer.Optimize( &aPair );
275 
276  return true;
277  }
278 
279  return false;
280 }
281 
282 
284 {
285  if( !routeHead ( aP ) )
286  return false;
287 
289 
290  return m_fitOk;
291 }
292 
293 
295 {
296  switch( m_currentMode )
297  {
298  case RM_MarkObstacles:
299  return rhMarkObstacles( aP );
300  case RM_Walkaround:
301  return rhWalkOnly( aP );
302  case RM_Shove:
303  return rhShoveOnly( aP );
304  default:
305  break;
306  }
307 
308  return false;
309 }
310 
311 
313 {
315 
316  bool ok = routeHead( aP );
317 
318  m_fitOk = false;
319 
320  if( !ok )
321  return false;
322 
323  if( !tryWalkDp( m_currentNode, m_currentTrace, true ) )
324  return false;
325 
326  LINE pLine( m_currentTrace.PLine() );
327  LINE nLine( m_currentTrace.NLine() );
328  ITEM_SET head;
329 
330  head.Add( &pLine );
331  head.Add( &nLine );
332 
333  SHOVE::SHOVE_STATUS status = m_shove->ShoveMultiLines( head );
334 
336 
337  if( status == SHOVE::SH_OK )
338  {
340 
343  {
344  m_fitOk = true;
345  }
346  }
347 
348  return m_fitOk;
349 }
350 
351 
353 {
354  ITEM_SET t;
355 
356  t.Add( const_cast<LINE*>( &m_currentTrace.PLine() ) );
357  t.Add( const_cast<LINE*>( &m_currentTrace.NLine() ) );
358 
359  return t;
360 }
361 
362 
364 {
366 
367  if( !m_idle )
368  Move( m_currentEnd, NULL );
369 }
370 
371 
372 NODE* DIFF_PAIR_PLACER::CurrentNode( bool aLoopsRemoved ) const
373 {
374  if( m_lastNode )
375  return m_lastNode;
376 
377  return m_currentNode;
378 }
379 
380 
381 bool DIFF_PAIR_PLACER::SetLayer( int aLayer )
382 {
383  if( m_idle )
384  {
385  m_currentLayer = aLayer;
386  return true;
387  }
388  else if( m_chainedPlacement || !m_prevPair )
389  {
390  return false;
391  }
392  else if( !m_prevPair->PrimP() || ( m_prevPair->PrimP()->OfKind( ITEM::VIA_T ) &&
393  m_prevPair->PrimP()->Layers().Overlaps( aLayer ) ) )
394  {
395  m_currentLayer = aLayer;
396  m_start = *m_prevPair;
397  initPlacement();
398  Move( m_currentEnd, NULL );
399  return true;
400  }
401 
402  return false;
403 }
404 
405 
407 {
408  switch( aItem->Kind() )
409  {
410  case ITEM::VIA_T:
411  case ITEM::SOLID_T:
412  return aItem->Anchor( 0 );
413 
414  case ITEM::ARC_T:
415  case ITEM::SEGMENT_T:
416  {
417  SEGMENT* s = static_cast<SEGMENT*>( aItem );
418 
419  JOINT* jA = aNode->FindJoint( aItem->Anchor( 0 ), aItem );
420  JOINT* jB = aNode->FindJoint( aItem->Anchor( 1 ), aItem );
421 
422  if( jA && jA->LinkCount() == 1 )
423  return s->Seg().A;
424  else if( jB && jB->LinkCount() == 1 )
425  return s->Seg().B;
426  else
427  return OPT_VECTOR2I();
428  }
429 
430  default:
431  return OPT_VECTOR2I();
432  break;
433  }
434 }
435 
436 
437 
439  DP_PRIMITIVE_PAIR& aPair, wxString* aErrorMsg )
440 {
441  int netP, netN;
442 
443  wxLogTrace( "PNS", "world %p", m_world );
444 
445  bool result = m_world->GetRuleResolver()->DpNetPair( aItem, netP, netN );
446 
447  if( !result )
448  {
449  if( aErrorMsg )
450  {
451  *aErrorMsg = _( "Unable to find complementary differential pair "
452  "nets. Make sure the names of the nets belonging "
453  "to a differential pair end with either _N/_P or +/-." );
454  }
455  return false;
456  }
457 
458  int refNet = aItem->Net();
459  int coupledNet = ( refNet == netP ) ? netN : netP;
460 
461  wxLogTrace( "PNS", "result %d", !!result );
462 
463  OPT_VECTOR2I refAnchor = getDanglingAnchor( m_currentNode, aItem );
464  ITEM* primRef = aItem;
465 
466  wxLogTrace( "PNS", "refAnchor %p", aItem );
467 
468  if( !refAnchor )
469  {
470  if( aErrorMsg )
471  {
472  *aErrorMsg = _( "Can't find a suitable starting point. If starting "
473  "from an existing differential pair make sure you are "
474  "at the end." );
475  }
476  return false;
477  }
478 
479  std::set<ITEM*> coupledItems;
480 
481  m_currentNode->AllItemsInNet( coupledNet, coupledItems );
482  double bestDist = std::numeric_limits<double>::max();
483  bool found = false;
484 
485  for( ITEM* item : coupledItems )
486  {
487  if( item->Kind() == aItem->Kind() )
488  {
489  OPT_VECTOR2I anchor = getDanglingAnchor( m_currentNode, item );
490  if( !anchor )
491  continue;
492 
493  double dist = ( *anchor - *refAnchor ).EuclideanNorm();
494 
495  bool shapeMatches = true;
496 
497  if( item->OfKind( ITEM::SOLID_T ) && item->Layers() != aItem->Layers() )
498  {
499  shapeMatches = false;
500  }
501 
502  if( dist < bestDist && shapeMatches )
503  {
504  found = true;
505  bestDist = dist;
506 
507  if( refNet != netP )
508  {
509  aPair = DP_PRIMITIVE_PAIR ( item, primRef );
510  aPair.SetAnchors( *anchor, *refAnchor );
511  }
512  else
513  {
514  aPair = DP_PRIMITIVE_PAIR( primRef, item );
515  aPair.SetAnchors( *refAnchor, *anchor );
516  }
517  }
518  }
519  }
520 
521  if( !found )
522  {
523  if( aErrorMsg )
524  {
525  *aErrorMsg = wxString::Format( _( "Can't find a suitable starting point "
526  "for coupled net \"%s\"." ),
527  m_world->GetRuleResolver()->NetName( coupledNet ) );
528  }
529  return false;
530  }
531 
532  return true;
533 }
534 
535 
537 {
538  return m_sizes.DiffPairViaGap();
539 }
540 
541 
543 {
545 }
546 
547 
548 bool DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, ITEM* aStartItem )
549 {
550  VECTOR2I p( aP );
551  wxString msg;
552 
553  if( !aStartItem )
554  {
555  Router()->SetFailureReason( _( "Can't start a differential pair "
556  " in the middle of nowhere." ) );
557  return false;
558  }
559 
560  setWorld( Router()->GetWorld() );
562 
563  if( !findDpPrimitivePair( aP, aStartItem, m_start, &msg ) )
564  {
565  Router()->SetFailureReason( msg );
566  return false;
567  }
568 
569  m_netP = m_start.PrimP()->Net();
570  m_netN = m_start.PrimN()->Net();
571 
572  #if 0
573  // FIXME: this also needs to be factored out but not so important right now
574  // Check if the current track/via gap & track width settings are violated
575  BOARD* brd = NULL; // FIXME Router()->GetBoard();
576  NETCLASSPTR netclassP = brd->FindNet( m_netP )->GetNetClass();
577  NETCLASSPTR netclassN = brd->FindNet( m_netN )->GetNetClass();
578  int clearance = std::min( m_sizes.DiffPairGap(), m_sizes.DiffPairViaGap() );
579 
580  if( clearance < netclassP->GetClearance() || clearance < netclassN->GetClearance() )
581  {
582  Router()->SetFailureReason( _( "Current track/via gap setting violates "
583  "design rules for this net." ) );
584  return false;
585  }
586 
588  {
589  Router()->SetFailureReason( _( "Current track width setting violates design rules." ) );
590  return false;
591  }
592  #endif
593 
594  m_currentStart = p;
595  m_currentEnd = p;
596  m_placingVia = false;
597  m_chainedPlacement = false;
598 
599  initPlacement();
600 
601  return true;
602 }
603 
604 
606 {
607  m_idle = false;
608  m_orthoMode = false;
611 
612  NODE* world = Router()->GetWorld();
613 
614  world->KillChildren();
615  NODE* rootNode = world->Branch();
616 
617  setWorld( rootNode );
618 
619  m_lastNode = NULL;
620  m_currentNode = rootNode;
622 
623  if( m_shove )
624  delete m_shove;
625 
626  m_shove = NULL;
627 
629  {
630  m_shove = new SHOVE( m_currentNode, Router() );
631  }
632 }
633 
634 
636 {
637  m_fitOk = false;
638 
639  DP_GATEWAYS gwsEntry( gap() );
640  DP_GATEWAYS gwsTarget( gap() );
641 
642  if( !m_prevPair )
644 
646 
647  DP_PRIMITIVE_PAIR target;
648 
649  if( findDpPrimitivePair( aP, m_currentEndItem, target ) )
650  {
651  gwsTarget.BuildFromPrimitivePair( target, m_startDiagonal );
652  m_snapOnTarget = true;
653  }
654  else
655  {
656  VECTOR2I fp;
657 
658  if( !propagateDpHeadForces( aP, fp ) )
659  return false;
660 
661  VECTOR2I midp, dirV;
662  m_prevPair->CursorOrientation( fp, midp, dirV );
663 
664  VECTOR2I fpProj = SEG( midp, midp + dirV ).LineProject( fp );
665 
666  // compute 'leader point' distance from the cursor (project cursor position
667  // on the extension of the starting segment pair of the DP)
668  int lead_dist = ( fpProj - fp ).EuclideanNorm();
669 
670  gwsTarget.SetFitVias( m_placingVia, m_sizes.ViaDiameter(), viaGap() );
671 
672  // far from the initial segment extension line -> allow a 45-degree obtuse turn
673  if( lead_dist > m_sizes.DiffPairGap() + m_sizes.DiffPairWidth() )
674  {
675  gwsTarget.BuildForCursor( fp );
676  }
677  // close to the initial segment extension line -> keep straight part only, project as close
678  // as possible to the cursor
679  else
680  {
681  gwsTarget.BuildForCursor( fpProj );
683  }
684 
685  m_snapOnTarget = false;
686  }
687 
691 
692  bool result = gwsEntry.FitGateways( gwsEntry, gwsTarget, m_startDiagonal, m_currentTrace );
693 
694  if( result )
695  {
699 
700  if( m_placingVia )
701  {
703  makeVia( m_currentTrace.CN().CPoint( -1 ), m_netN ) );
704  }
705 
706  return true;
707  }
708 
709  return false;
710 }
711 
712 
713 bool DIFF_PAIR_PLACER::Move( const VECTOR2I& aP , ITEM* aEndItem )
714 {
715  m_currentEndItem = aEndItem;
716  m_fitOk = false;
717 
718  delete m_lastNode;
719  m_lastNode = NULL;
720 
721  bool retval = route( aP );
722 
723  NODE* latestNode = m_currentNode;
724  m_lastNode = latestNode->Branch();
725 
726  assert( m_lastNode != NULL );
727  m_currentEnd = aP;
728 
730 
731  return retval;
732 }
733 
734 
736 {
737  m_sizes = aSizes;
738 
739  if( !m_idle )
740  {
741  initPlacement();
742  Move( m_currentEnd, NULL );
743  }
744 }
745 
746 
747 bool DIFF_PAIR_PLACER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
748 {
749  if( !m_fitOk && !Settings().CanViolateDRC() )
750  return false;
751 
752  if( m_currentTrace.CP().SegmentCount() < 1 ||
753  m_currentTrace.CN().SegmentCount() < 1 )
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 )
762  {
765 
766  if( newP.SegmentCount() > 1 && newN.SegmentCount() > 1 )
767  {
768  newP.Remove( -1, -1 );
769  newN.Remove( -1, -1 );
770  }
771 
772  m_currentTrace.SetShape( newP, newN );
773  }
774 
776  {
779  m_chainedPlacement = false;
780  }
781  else
782  {
783  m_chainedPlacement = !m_snapOnTarget && !aForceFinish;
784  }
785 
786  LINE lineP( m_currentTrace.PLine() );
787  LINE lineN( m_currentTrace.NLine() );
788 
789  m_lastNode->Add( lineP );
790  m_lastNode->Add( lineN );
791 
792  topo.SimplifyLine( &lineP );
793  topo.SimplifyLine( &lineN );
794 
796 
797  CommitPlacement();
798  m_placingVia = false;
799 
800  if( m_snapOnTarget || aForceFinish )
801  {
802  m_idle = true;
803  return true;
804  }
805  else
806  {
807  initPlacement();
808  return false;
809  }
810 }
811 
812 
814 {
816  return true;
817 }
818 
819 
821 {
822  return m_currentTrace.CP().SegmentCount() > 0 ||
824 }
825 
826 
828 {
829  if( m_lastNode )
831 
832  m_lastNode = NULL;
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  {
852  Dbg()->AddLine( ratLineP, 1, 10000 );
853  }
854 
855  if( topo.LeadingRatLine ( &m_currentTrace.NLine(), ratLineN ) )
856  {
857  Dbg()->AddLine( ratLineN, 3, 10000 );
858  }
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:128
NETCLASS * GetNetClass()
Function GetNetClass.
Definition: netinfo.h:128
const SHAPE_LINE_CHAIN & CLine() const
Const accessor to the underlying shape
Definition: pns_line.h:149
bool rhWalkOnly(const VECTOR2I &aP)
route step, walkaround mode
ITEM.
Definition: pns_item.h:53
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
ROUTER * Router() const
Returns the instance of our router
Definition: pns_algo_base.h:51
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)
NODE.
Definition: pns_node.h:145
virtual void AddLine(const SHAPE_LINE_CHAIN &aLine, int aType=0, int aWidth=0, const std::string aName="")
bool FixRoute(const VECTOR2I &aP, ITEM *aEndItem, bool aForceFinish) override
Function FixRoute()
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
SHOVE.
Definition: pns_shove.h:48
int Gap() const
void GetModifiedNets(std::vector< int > &aNets) const override
Function GetModifiedNets.
void SetLayer(int aLayer)
Definition: pns_item.h:154
bool route(const VECTOR2I &aP)
Function route()
void AppendVias(const VIA &aViaP, const VIA &aViaN)
bool EndsWithVias() const
Classes BOARD_ITEM and BOARD_CONNECTED_ITEM.
bool rhShoveOnly(const VECTOR2I &aP)
route step, shove mode
void CommitRouting()
Definition: pns_router.cpp:443
Ignore collisions, mark obstacles
const SHAPE_LINE_CHAIN & CN() const
int m_iteration
current algorithm iteration
void FilterByOrientation(int aAngleMask, DIRECTION_45 aRefOrientation)
SHOVE_STATUS ProcessSingleLine(LINE &aCurrent, LINE &aObstacle, LINE &aShoved)
Definition: pns_shove.cpp:274
void AllItemsInNet(int aNet, std::set< ITEM * > &aItems)
Definition: pns_node.cpp:1294
bool PushoutForce(NODE *aNode, const VECTOR2I &aDirection, VECTOR2I &aForce, bool aSolidsOnly=true, int aMaxIterations=10)
Definition: pns_via.cpp:32
SHOVE * m_shove
The shove engine
#define PNS_HULL_MARGIN
LINE.
Definition: pns_line.h:60
int m_viaDiameter
current via diameter
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:553
WALKAROUND_STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
NODE * CurrentNode(bool aLoopsRemoved=false) const override
Function CurrentNode()
double CoupledLength() const
NODE * m_world
pointer to world to search colliding items
const SEG & Seg() const
Definition: pns_segment.h:83
const VIA makeVia(const VECTOR2I &aP, int aNet)
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
bool routeHead(const VECTOR2I &aP)
NODE * Branch()
Function Branch()
Definition: pns_node.cpp:106
ITEM * PrimP() const
void SetNet(int aNet)
Definition: pns_item.h:148
VIATYPE ViaType() const
int m_viaDrill
current via drill
void SetDiameter(int aDiameter)
Definition: pns_via.h:126
ROUTING_SETTINGS & Settings() const
Returns current router settings
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
const VECTOR2I & CPoint(int aIndex) const
Function Point()
bool HasPlacedAnything() const override
JOINT.
Definition: pns_joint.h:43
bool findDpPrimitivePair(const VECTOR2I &aP, ITEM *aItem, DP_PRIMITIVE_PAIR &aPair, wxString *aErrorMsg=nullptr)
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:121
VECTOR2I LineProject(const VECTOR2I &aP) const
Function LineProject()
Definition: seg.h:362
void KillChildren()
Destroys all child nodes. Applicable only to the root node.
Definition: pns_node.cpp:1288
#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:37
bool ToggleVia(bool aEnabled) override
Function ToggleVia()
int Net() const
Definition: pns_item.h:149
DIRECTION_45.
Definition: direction45.h:37
void UpdateSizes(const SIZES_SETTINGS &aSizes) override
Function UpdateSizes()
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I aV=VECTOR2I(0, 0))
a quick shortcut to optmize a line without creating and setting up an optimizer
bool Start(const VECTOR2I &aP, ITEM *aStartItem) override
Function Start()
const ITEM_SET Traces() override
Function Traces()
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:77
void SetFailureReason(const wxString &aReason)
Definition: pns_router.h:228
PNS_MODE Mode() const
Returns the routing mode.
bool m_placingVia
Are we placing a via?
DIFF_PAIR_PLACER(ROUTER *aRouter)
void SetSolidsOnly(bool aSolidsOnly)
void SetWidth(int aWidth)
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
virtual bool DpNetPair(ITEM *aItem, int &aNetP, int &aNetN)=0
double Skew() const
int SegmentCount() const
Function SegmentCount()
JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, int aNet)
Function FindJoint()
Definition: pns_node.cpp:1027
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape
Definition: pns_line.h:143
bool SimplifyLine(LINE *aLine)
RULE_RESOLVER * GetRuleResolver() const
Definition: pns_node.h:176
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:271
virtual VECTOR2I Anchor(int n) const
Definition: pns_item.h:226
Definition: seg.h:39
DIFF_PAIR.
void FlipPosture() override
Function FlipPosture()
Only walkaround
const SHAPE_LINE_CHAIN & CP() const
NODE * m_currentNode
Current world state
void updateLeadingRatLine()
Function updateLeadingRatLine()
bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Function Move()
void ForceClearance(bool aEnabled, int aClearance)
Definition: pns_shove.h:75
ITEM * PrimN() const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
DP_PRIMITIVE_PAIR.
const SEG CSegment(int aIndex) const
Function CSegment()
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
#define _(s)
Definition: 3d_actions.cpp:33
SHAPE_LINE_CHAIN.
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Function CheckColliding()
Definition: pns_node.cpp:427
VECTOR2I A
Definition: seg.h:47
void initPlacement()
Function startPlacement()
bool SetLayer(int aLayer) override
Function SetLayer()
PnsKind Kind() const
Function Kind()
Definition: pns_item.h:123
OPTIMIZER.
Definition: pns_optimizer.h:95
const std::vector< int > CurrentNets() const override
Function CurrentNets()
virtual wxString NetName(int aNet)=0
OPT< DP_PRIMITIVE_PAIR > m_prevPair
bool tryWalkDp(NODE *aNode, DIFF_PAIR &aPair, bool aSolidsOnly)
void SetOrthoMode(bool aOrthoMode) override
Function SetOrthoMode()
int LinkCount(int aMask=-1) const
Definition: pns_joint.h:211
void setWorld(NODE *aWorld)
Function setWorld()
SHOVE_STATUS ShoveMultiLines(const ITEM_SET &aHeadSet)
Definition: pns_shove.cpp:1374
const VIA & Via() const
Definition: pns_line.h:239
DP_GATEWAYS.
Push and Shove diff pair dimensions (gap) settings dialog.
NODE * GetWorld() const
Definition: pns_router.h:154
int m_currentWidth
current track width
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Function Add()
Definition: pns_node.cpp:620
NODE * CurrentNode()
Definition: pns_shove.cpp:1616
void SetIterationLimit(const int aIterLimit)
LAYER_RANGE.
Definition: pns_layerset.h:32
const LAYER_RANGE & Layers() const
Definition: pns_item.h:151
DP_PRIMITIVE_PAIR EndingPrimitives()
void SetAnchors(const VECTOR2I &aAnchorP, const VECTOR2I &aAnchorN)
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
void SetNets(int aP, int aN)
OPT_VECTOR2I getDanglingAnchor(NODE *aNode, ITEM *aItem)
bool rhMarkObstacles(const VECTOR2I &aP)
route step, mark obstacles mode
VECTOR2I B
Definition: seg.h:48