KiCad PCB EDA Suite
pns_router.cpp
Go to the documentation of this file.
1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2014 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 <cstdio>
23 #include <memory>
24 #include <vector>
25 
26 #include <view/view.h>
27 #include <view/view_group.h>
29 
31 
32 #include <pcb_painter.h>
33 #include <pcbnew_settings.h>
34 #include <pad.h>
35 #include <zone.h>
36 
37 #include <geometry/shape.h>
38 
39 #include "pns_node.h"
40 #include "pns_line_placer.h"
41 #include "pns_line.h"
42 #include "pns_solid.h"
43 #include "pns_utils.h"
44 #include "pns_router.h"
45 #include "pns_shove.h"
46 #include "pns_dragger.h"
47 #include "pns_component_dragger.h"
48 #include "pns_topology.h"
49 #include "pns_diff_pair_placer.h"
50 #include "pns_meander_placer.h"
52 #include "pns_dp_meander_placer.h"
53 
54 namespace PNS {
55 
56 // an ugly singleton for drawing debug items within the router context.
57 // To be fixed sometime in the future.
58 static ROUTER* theRouter;
59 
61 {
62  theRouter = this;
63 
64  m_state = IDLE;
66 
67  m_logger = new LOGGER;
68 
69  // Initialize all other variables:
70  m_lastNode = nullptr;
71  m_iterLimit = 0;
72  m_settings = nullptr;
73  m_iface = nullptr;
75 }
76 
77 
79 {
80  return theRouter;
81 }
82 
83 
85 {
86  ClearWorld();
87  theRouter = nullptr;
88  delete m_logger;
89 }
90 
91 
93 {
94  ClearWorld();
95 
96  m_world = std::make_unique<NODE>( );
97  m_iface->SyncWorld( m_world.get() );
98  m_world->FixupVirtualVias();
99 }
100 
101 
103 {
104  if( m_world )
105  {
106  m_world->KillChildren();
107  m_world.reset();
108  }
109 
110  m_placer.reset();
111 }
112 
113 
115 {
116  return m_state != IDLE;
117 }
118 
119 
120 const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP, bool aUseClearance )
121 {
122  if( m_state == IDLE || m_placer == nullptr )
123  {
124  if( aUseClearance )
125  {
126  SEGMENT test( SEG( aP, aP ), -1 );
127  test.SetWidth( 1 );
128  test.SetLayers( LAYER_RANGE::All() );
129  NODE::OBSTACLES obs;
130  m_world->QueryColliding( &test, obs, ITEM::ANY_T, -1, false );
131 
132  PNS::ITEM_SET ret;
133 
134  for( OBSTACLE& obstacle : obs )
135  ret.Add( obstacle.m_item, false );
136 
137  return ret;
138  }
139  else
140  {
141  return m_world->HitTest( aP );
142  }
143  }
144  else
145  return m_placer->CurrentNode()->HitTest( aP );
146 }
147 
148 
149 bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aItem, int aDragMode )
150 {
151  return StartDragging( aP, ITEM_SET( aItem ), aDragMode );
152 }
153 
154 
155 bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM_SET aStartItems, int aDragMode )
156 {
157  if( aStartItems.Empty() )
158  return false;
159 
160  if( aStartItems.Count( ITEM::SOLID_T ) == aStartItems.Size() )
161  {
162  m_dragger = std::make_unique<COMPONENT_DRAGGER>( this );
165  }
166  else
167  {
168  if( aDragMode & DM_FREE_ANGLE )
170  else
171  m_forceMarkObstaclesMode = false;
172 
173  m_dragger = std::make_unique<DRAGGER>( this );
175  }
176 
177  m_dragger->SetMode( aDragMode );
178  m_dragger->SetWorld( m_world.get() );
179  m_dragger->SetLogger( m_logger );
180  m_dragger->SetDebugDecorator( m_iface->GetDebugDecorator() );
181 
182  if( m_logger )
183  m_logger->Clear();
184 
185  if( m_logger && aStartItems.Size() )
186  {
187  m_logger->Log( LOGGER::EVT_START_DRAG, aP, aStartItems[0] );
188  }
189 
190  if( m_dragger->Start( aP, aStartItems ) )
191  {
192  return true;
193  }
194  else
195  {
196  m_dragger.reset();
197  m_state = IDLE;
198  return false;
199  }
200 }
201 
202 
203 bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem, int aLayer )
204 {
205  if( Settings().AllowDRCViolations() )
206  return true;
207 
209  {
211  {
212  SetFailureReason( _( "Diff pair gap is less than board minimum clearance." ) );
213  return false;
214  }
215  }
216 
217  ITEM_SET candidates = QueryHoverItems( aWhere );
218 
219  for( ITEM* item : candidates.Items() )
220  {
221  if( !item->IsRoutable() && item->Layers().Overlaps( aLayer ) )
222  {
223  BOARD_ITEM* parent = item->Parent();
224 
225  switch( parent->Type() )
226  {
227  case PCB_PAD_T:
228  {
229  PAD* pad = static_cast<PAD*>( parent );
230 
231  if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
232  SetFailureReason( _( "Cannot start routing from a non-plated hole." ) );
233  }
234  break;
235 
236  case PCB_ZONE_T:
237  case PCB_FP_ZONE_T:
238  {
239  ZONE* zone = static_cast<ZONE*>( parent );
240 
241  if( !zone->GetZoneName().IsEmpty() )
242  {
243  SetFailureReason( wxString::Format( _( "Rule area '%s' disallows tracks." ),
244  zone->GetZoneName() ) );
245  }
246  else
247  {
248  SetFailureReason( _( "Rule area disallows tracks." ) );
249  }
250  }
251  break;
252 
253  case PCB_TEXT_T:
254  case PCB_FP_TEXT_T:
255  SetFailureReason( _( "Cannot start routing from a text item." ) );
256  break;
257 
258  case PCB_SHAPE_T:
259  case PCB_FP_SHAPE_T:
260  SetFailureReason( _( "Cannot start routing from a graphic." ) );
261 
262  default:
263  break;
264  }
265 
266  return false;
267  }
268  }
269 
270  VECTOR2I startPoint = aStartItem ? aStartItem->Anchor( 0 ) : aWhere;
271 
272  if( aStartItem && aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
273  {
274  VECTOR2I otherEnd = aStartItem->Anchor( 1 );
275 
276  if( ( otherEnd - aWhere ).SquaredEuclideanNorm()
277  < ( startPoint - aWhere ).SquaredEuclideanNorm() )
278  {
279  startPoint = otherEnd;
280  }
281  }
282 
284  {
285  SHAPE_LINE_CHAIN dummyStartSeg;
286  LINE dummyStartLine;
287 
288  dummyStartSeg.Append( startPoint );
289  dummyStartSeg.Append( startPoint, true );
290 
291  dummyStartLine.SetShape( dummyStartSeg );
292  dummyStartLine.SetLayer( aLayer );
293  dummyStartLine.SetNet( aStartItem ? aStartItem->Net() : 0 );
294  dummyStartLine.SetWidth( m_sizes.TrackWidth() );
295 
296  if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
297  {
298  ITEM_SET dummyStartSet( &dummyStartLine );
299  NODE::ITEM_VECTOR highlightedItems;
300 
301  markViolations( m_world.get(), dummyStartSet, highlightedItems );
302 
303  for( ITEM* item : highlightedItems )
304  m_iface->HideItem( item );
305 
306  SetFailureReason( _( "The routing start point violates DRC." ) );
307  return false;
308  }
309  }
310  else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR )
311  {
312  if( !aStartItem )
313  {
314  SetFailureReason( _( "Cannot start a differential pair in the middle of nowhere." ) );
315  return false;
316  }
317 
318  DP_PRIMITIVE_PAIR dpPair;
319  wxString errorMsg;
320 
321  if( !DIFF_PAIR_PLACER::FindDpPrimitivePair( m_world.get(), startPoint, aStartItem, dpPair,
322  &errorMsg ) )
323  {
324  SetFailureReason( errorMsg );
325  return false;
326  }
327 
328  SHAPE_LINE_CHAIN dummyStartSegA;
329  SHAPE_LINE_CHAIN dummyStartSegB;
330  LINE dummyStartLineA;
331  LINE dummyStartLineB;
332 
333  dummyStartSegA.Append( dpPair.AnchorN() );
334  dummyStartSegA.Append( dpPair.AnchorN(), true );
335 
336  dummyStartSegB.Append( dpPair.AnchorP() );
337  dummyStartSegB.Append( dpPair.AnchorP(), true );
338 
339  dummyStartLineA.SetShape( dummyStartSegA );
340  dummyStartLineA.SetLayer( aLayer );
341  dummyStartLineA.SetNet( dpPair.PrimN()->Net() );
342  dummyStartLineA.SetWidth( m_sizes.DiffPairWidth() );
343 
344  dummyStartLineB.SetShape( dummyStartSegB );
345  dummyStartLineB.SetLayer( aLayer );
346  dummyStartLineB.SetNet( dpPair.PrimP()->Net() );
347  dummyStartLineB.SetWidth( m_sizes.DiffPairWidth() );
348 
349  if( m_world->CheckColliding( &dummyStartLineA, ITEM::ANY_T )
350  || m_world->CheckColliding( &dummyStartLineB, ITEM::ANY_T ) )
351  {
352  ITEM_SET dummyStartSet;
353  NODE::ITEM_VECTOR highlightedItems;
354 
355  dummyStartSet.Add( dummyStartLineA );
356  dummyStartSet.Add( dummyStartLineB );
357  markViolations( m_world.get(), dummyStartSet, highlightedItems );
358 
359  for( ITEM* item : highlightedItems )
360  m_iface->HideItem( item );
361 
362  SetFailureReason( _( "The routing start point violates DRC." ) );
363  return false;
364  }
365  }
366 
367  return true;
368 }
369 
370 
371 bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer )
372 {
373  if( !isStartingPointRoutable( aP, aStartItem, aLayer ) )
374  return false;
375 
376  m_forceMarkObstaclesMode = false;
377 
378  switch( m_mode )
379  {
381  m_placer = std::make_unique<LINE_PLACER>( this );
382  break;
383 
385  m_placer = std::make_unique<DIFF_PAIR_PLACER>( this );
386  break;
387 
389  m_placer = std::make_unique<MEANDER_PLACER>( this );
390  break;
391 
393  m_placer = std::make_unique<DP_MEANDER_PLACER>( this );
394  break;
395 
397  m_placer = std::make_unique<MEANDER_SKEW_PLACER>( this );
398  break;
399 
400  default:
401  return false;
402  }
403 
404  m_placer->UpdateSizes( m_sizes );
405  m_placer->SetLayer( aLayer );
406  m_placer->SetDebugDecorator( m_iface->GetDebugDecorator() );
407  m_placer->SetLogger( m_logger );
408 
409  if( m_logger )
410  {
411  m_logger->Clear();
412  m_logger->Log( LOGGER::EVT_START_ROUTE, aP, aStartItem );
413  }
414 
415  if( m_placer->Start( aP, aStartItem ) )
416  {
418  return true;
419  }
420  else
421  {
422  m_state = IDLE;
423  return false;
424  }
425 }
426 
427 
428 void ROUTER::Move( const VECTOR2I& aP, ITEM* endItem )
429 {
430  if( m_logger )
431  m_logger->Log( LOGGER::EVT_MOVE, aP, endItem );
432 
433  switch( m_state )
434  {
435  case ROUTE_TRACK:
436  movePlacing( aP, endItem );
437  break;
438 
439  case DRAG_SEGMENT:
440  case DRAG_COMPONENT:
441  moveDragging( aP, endItem );
442  break;
443 
444  default:
445  break;
446  }
447 }
448 
449 
450 void ROUTER::moveDragging( const VECTOR2I& aP, ITEM* aEndItem )
451 {
452  m_iface->EraseView();
453 
454  m_dragger->Drag( aP );
455  ITEM_SET dragged = m_dragger->Traces();
456 
457  updateView( m_dragger->CurrentNode(), dragged, true );
458 }
459 
460 
461 void ROUTER::markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved )
462 {
463  auto updateItem =
464  [&]( ITEM* currentItem, ITEM* itemToMark )
465  {
466  std::unique_ptr<ITEM> tmp( itemToMark->Clone() );
467 
468  int clearance;
469  bool removeOriginal = true;
470  bool holeOnly = ( ( itemToMark->Marker() & MK_HOLE )
471  && !( itemToMark->Marker() & MK_VIOLATION ) );
472 
473  if( holeOnly )
474  clearance = aNode->GetHoleClearance( currentItem, itemToMark );
475  else
476  clearance = aNode->GetClearance( currentItem, itemToMark );
477 
478  if( itemToMark->Layers().IsMultilayer() && !currentItem->Layers().IsMultilayer() )
479  tmp->SetLayer( currentItem->Layer() );
480 
481  if( itemToMark->Kind() == ITEM::SOLID_T )
482  {
483  if( holeOnly || !m_iface->IsFlashedOnLayer( itemToMark, currentItem->Layer() ) )
484  {
485  SOLID* solid = static_cast<SOLID*>( tmp.get() );
486 
487  if( solid->Hole() )
488  {
489  solid->SetShape( solid->Hole()->Clone() );
490 
491  // Leave the pad flashing around the highlighted hole
492  removeOriginal = false;
493  }
494  }
495 
496  if( itemToMark->IsCompoundShapePrimitive() )
497  {
498  // We're only highlighting one (or more) of several primitives so we
499  // don't want all the other parts of the object to disappear
500  removeOriginal = false;
501  }
502  }
503 
504  m_iface->DisplayItem( tmp.get(), clearance );
505 
506  if( removeOriginal )
507  aRemoved.push_back( itemToMark );
508  };
509 
510  for( ITEM* item : aCurrent.Items() )
511  {
512  NODE::OBSTACLES obstacles;
513 
514  aNode->QueryColliding( item, obstacles, ITEM::ANY_T );
515 
516  if( item->OfKind( ITEM::LINE_T ) )
517  {
518  LINE* l = static_cast<LINE*>( item );
519 
520  if( l->EndsWithVia() )
521  {
522  VIA v( l->Via() );
523  aNode->QueryColliding( &v, obstacles, ITEM::ANY_T );
524  }
525  }
526 
527  for( OBSTACLE& obs : obstacles )
528  {
529  obs.m_item->Mark( obs.m_item->Marker() | MK_VIOLATION );
530  updateItem( item, obs.m_item );
531  }
532 
533  if( item->Kind() == ITEM::LINE_T )
534  {
535  LINE* line = static_cast<LINE*>( item );
536 
537  // Show clearance on any blocking obstacles
538  if( line->GetBlockingObstacle() )
539  updateItem( item, line->GetBlockingObstacle() );
540  }
541  }
542 }
543 
544 
545 void ROUTER::updateView( NODE* aNode, ITEM_SET& aCurrent, bool aDragging )
546 {
547  NODE::ITEM_VECTOR removed, added;
548  NODE::OBSTACLES obstacles;
549 
550  if( !aNode )
551  return;
552 
554  markViolations( aNode, aCurrent, removed );
555 
556  aNode->GetUpdatedItems( removed, added );
557 
558  for( ITEM* item : added )
559  {
561  int clearance = GetRuleResolver()->Clearance( item, nullptr );
562  m_iface->DisplayItem( item, clearance, aDragging );
563  }
564 
565  for( ITEM* item : removed )
566  m_iface->HideItem( item );
567 }
568 
569 
570 void ROUTER::UpdateSizes( const SIZES_SETTINGS& aSizes )
571 {
572  m_sizes = aSizes;
573 
574  // Change track/via size settings
575  if( m_state == ROUTE_TRACK )
576  {
577  m_placer->UpdateSizes( m_sizes );
578  }
579 }
580 
581 
582 void ROUTER::movePlacing( const VECTOR2I& aP, ITEM* aEndItem )
583 {
584  m_iface->EraseView();
585 
586  m_placer->Move( aP, aEndItem );
587  ITEM_SET current = m_placer->Traces();
588 
589  for( const ITEM* item : current.CItems() )
590  {
591  if( !item->OfKind( ITEM::LINE_T ) )
592  continue;
593 
594  const LINE* l = static_cast<const LINE*>( item );
595  int clearance = GetRuleResolver()->Clearance( item, nullptr );
596 
597  m_iface->DisplayItem( l, clearance );
598 
599  if( l->EndsWithVia() )
600  {
601  const VIA& via = l->Via();
602  int viaClearance = GetRuleResolver()->Clearance( &via, nullptr );
603  int holeClearance = GetRuleResolver()->HoleClearance( &via, nullptr );
604 
605  if( holeClearance + via.Drill() / 2 > viaClearance + via.Diameter() / 2 )
606  viaClearance = holeClearance + via.Drill() / 2 - via.Diameter() / 2;
607 
608  m_iface->DisplayItem( &l->Via(), viaClearance );
609  }
610  }
611 
612  //ITEM_SET tmp( &current );
613 
614  updateView( m_placer->CurrentNode( true ), current );
615 }
616 
617 
619 {
620  if( m_state == ROUTE_TRACK && !m_placer->HasPlacedAnything() )
621  return;
622 
623  NODE::ITEM_VECTOR removed;
624  NODE::ITEM_VECTOR added;
625  NODE::ITEM_VECTOR changed;
626 
627  aNode->GetUpdatedItems( removed, added );
628 
629  for( ITEM* item : removed )
630  {
631  bool is_changed = false;
632 
633  // Items in remove/add that share the same parent are just updated versions
634  // We move them to the updated vector to preserve attributes such as UUID and pad data
635  if( item->Parent() )
636  {
637  for( NODE::ITEM_VECTOR::iterator added_it = added.begin();
638  added_it != added.end(); ++added_it )
639  {
640  if( ( *added_it )->Parent() && ( *added_it )->Parent() == item->Parent() )
641  {
642  changed.push_back( *added_it );
643  added.erase( added_it );
644  is_changed = true;
645  break;
646  }
647  }
648  }
649 
650  if( !is_changed && !item->IsVirtual() )
651  m_iface->RemoveItem( item );
652  }
653 
654  for( ITEM* item : added )
655  {
656  if( !item->IsVirtual() )
657  {
658  m_iface->AddItem( item );
659  }
660  }
661 
662  for( ITEM* item : changed )
663  {
664  if( !item->IsVirtual() )
665  {
666  m_iface->UpdateItem( item );
667  }
668  }
669 
670  m_iface->Commit();
671  m_world->Commit( aNode );
672 }
673 
674 
675 bool ROUTER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
676 {
677  bool rv = false;
678 
679  if( m_logger )
680  m_logger->Log( LOGGER::EVT_FIX, aP, aEndItem );
681 
682  switch( m_state )
683  {
684  case ROUTE_TRACK:
685  rv = m_placer->FixRoute( aP, aEndItem, aForceFinish );
686  break;
687 
688  case DRAG_SEGMENT:
689  case DRAG_COMPONENT:
690  rv = m_dragger->FixRoute();
691  break;
692 
693  default:
694  break;
695  }
696 
697  return rv;
698 }
699 
700 
702 {
703  if( !RoutingInProgress() )
704  return;
705 
706  m_placer->UnfixRoute();
707 }
708 
709 
711 {
712  if( m_state == ROUTE_TRACK )
713  m_placer->CommitPlacement();
714 
715  StopRouting();
716 }
717 
718 
720 {
721  // Update the ratsnest with new changes
722 
723  if( m_placer )
724  {
725  std::vector<int> nets;
726  m_placer->GetModifiedNets( nets );
727 
728  // Update the ratsnest with new changes
729  for( int n : nets )
730  m_iface->UpdateNet( n );
731  }
732 
733  if( !RoutingInProgress() )
734  return;
735 
736  m_placer.reset();
737  m_dragger.reset();
738 
739  m_iface->EraseView();
740 
741  m_state = IDLE;
742  m_world->KillChildren();
743  m_world->ClearRanks();
744 }
745 
746 
748 {
749  m_iface->EraseView();
750 }
751 
752 
754 {
755  if( m_state == ROUTE_TRACK )
756  {
757  m_placer->FlipPosture();
758  }
759 }
760 
761 
762 bool ROUTER::SwitchLayer( int aLayer )
763 {
764  if( m_state == ROUTE_TRACK )
765  return m_placer->SetLayer( aLayer );
766 
767  return false;
768 }
769 
770 
772 {
773  if( m_state == ROUTE_TRACK )
774  {
775  bool toggle = !m_placer->IsPlacingVia();
776  m_placer->ToggleVia( toggle );
777  }
778 }
779 
780 
781 const std::vector<int> ROUTER::GetCurrentNets() const
782 {
783  if( m_placer )
784  return m_placer->CurrentNets();
785  else if( m_dragger )
786  return m_dragger->CurrentNets();
787 
788  return std::vector<int>();
789 }
790 
791 
793 {
794  if( m_placer )
795  return m_placer->CurrentLayer();
796  else if( m_dragger )
797  return m_dragger->CurrentLayer();
798 
799  return -1;
800 }
801 
802 
804 {
805  return m_logger;
806 }
807 
808 
810 {
811  if( !m_placer )
812  return false;
813 
814  return m_placer->IsPlacingVia();
815 }
816 
817 
819 {
821 
822  switch( m_settings->GetCornerMode() )
823  {
824  case DIRECTION_45::CORNER_MODE::MITERED_45: mode = DIRECTION_45::CORNER_MODE::ROUNDED_45; break;
825  case DIRECTION_45::CORNER_MODE::ROUNDED_45: mode = DIRECTION_45::CORNER_MODE::MITERED_90; break;
826  case DIRECTION_45::CORNER_MODE::MITERED_90: mode = DIRECTION_45::CORNER_MODE::ROUNDED_90; break;
827  case DIRECTION_45::CORNER_MODE::ROUNDED_90: mode = DIRECTION_45::CORNER_MODE::MITERED_45; break;
828  }
829 
830  m_settings->SetCornerMode( mode );
831 }
832 
833 
834 void ROUTER::SetOrthoMode( bool aEnable )
835 {
836  if( !m_placer )
837  return;
838 
839  m_placer->SetOrthoMode( aEnable );
840 }
841 
842 
844 {
845  m_mode = aMode;
846 }
847 
848 
850 {
851  m_iface = aIface;
852 }
853 
854 void ROUTER::BreakSegment( ITEM *aItem, const VECTOR2I& aP )
855 {
856  NODE *node = m_world->Branch();
857 
858  LINE_PLACER placer( this );
859 
860  if( placer.SplitAdjacentSegments( node, aItem, aP ) )
861  {
862  CommitRouting( node );
863  }
864  else
865  {
866  delete node;
867  }
868 }
869 
870 }
Base class for PNS router board items.
Definition: pns_item.h:55
int Count(int aKindMask=-1) const
Definition: pns_itemset.h:114
void moveDragging(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:450
virtual int Layer() const
Definition: pns_item.h:158
bool Empty() const
Definition: pns_itemset.h:130
Keep the router "world" - i.e.
Definition: pns_node.h:148
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
DIRECTION_45::CORNER_MODE GetCornerMode() const
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Definition: pns_node.cpp:102
void ToggleCornerMode()
Definition: pns_router.cpp:818
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
bool IsMultilayer() const
Definition: pns_layerset.h:77
void SetLayer(int aLayer)
Definition: pns_item.h:157
const ITEM_SET QueryHoverItems(const VECTOR2I &aP, bool aUseClearance=false)
Definition: pns_router.cpp:120
void CommitRouting()
Definition: pns_router.cpp:710
RULE_RESOLVER * GetRuleResolver() const
Definition: pns_router.h:170
void ClearViewDecorations()
Definition: pns_router.cpp:747
ENTRIES & Items()
Definition: pns_itemset.h:135
Single track placement algorithm.
virtual void HideItem(ITEM *aItem)=0
bool isStartingPointRoutable(const VECTOR2I &aWhere, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:203
void SyncWorld()
Definition: pns_router.cpp:92
bool IsPlacingVia() const
Definition: pns_router.cpp:809
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
std::unique_ptr< PLACEMENT_ALGO > m_placer
Definition: pns_router.h:231
BOX2I m_visibleViewArea
Definition: pns_router.h:225
void SetCornerMode(DIRECTION_45::CORNER_MODE aMode)
const std::vector< int > GetCurrentNets() const
Definition: pns_router.cpp:781
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
class PAD, a pad in a footprint
Definition: typeinfo.h:89
int m_iterLimit
Definition: pns_router.h:237
virtual int Clearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true)=0
int Size() const
Definition: pns_itemset.h:160
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
Definition: pns_line.h:60
ROUTING_SETTINGS * m_settings
Definition: pns_router.h:240
virtual void AddItem(ITEM *aItem)=0
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
void SetOrthoMode(bool aEnable)
Definition: pns_router.cpp:834
int GetHoleClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Definition: pns_node.cpp:114
bool EndsWithVia() const
Definition: pns_line.h:191
void ToggleViaPlacement()
Definition: pns_router.cpp:771
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
static LAYER_RANGE All()
Definition: pns_layerset.h:109
std::unique_ptr< NODE > m_world
Definition: pns_router.h:228
void ClearWorld()
Definition: pns_router.cpp:102
std::unique_ptr< DRAG_ALGO > m_dragger
Definition: pns_router.h:232
void SetWidth(int aWidth)
Return line width.
Definition: pns_line.h:149
void SetNet(int aNet)
Definition: pns_item.h:151
void UndoLastSegment()
Definition: pns_router.cpp:701
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
Definition: pns_line.h:126
virtual void SyncWorld(NODE *aNode)=0
virtual void DisplayItem(const ITEM *aItem, int aClearance, bool aEdit=false)=0
virtual void UpdateNet(int aNetCode)=0
like PAD_PTH, but not plated
void BreakSegment(ITEM *aItem, const VECTOR2I &aP)
Definition: pns_router.cpp:854
void updateView(NODE *aNode, ITEM_SET &aCurrent, bool aDragging=false)
Definition: pns_router.cpp:545
NODE * m_lastNode
Definition: pns_router.h:229
int Net() const
Definition: pns_item.h:152
bool SplitAdjacentSegments(NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
Check if point aP lies on segment aSeg.
CORNER_MODE
Corner modes.
Definition: direction45.h:66
void SetMaximum()
Definition: box2.h:57
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish=false)
Definition: pns_router.cpp:675
void SetFailureReason(const wxString &aReason)
Definition: pns_router.h:203
void SetShape(SHAPE *shape)
Definition: pns_solid.h:89
RouterState m_state
Definition: pns_router.h:226
virtual void ClearCacheForItem(const ITEM *aItem)
Definition: pns_node.h:100
#define _(s)
virtual SHAPE * Clone() const
Return a dynamically allocated copy of the shape.
Definition: shape.h:139
ROUTER_IFACE * m_iface
Definition: pns_router.h:235
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
class ZONE, a copper pour area
Definition: typeinfo.h:105
void movePlacing(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:582
const SHAPE * Hole() const override
Definition: pns_solid.h:81
void Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:428
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:371
void Clear()
Definition: pns_logger.cpp:40
void SetInterface(ROUTER_IFACE *aIface)
Definition: pns_router.cpp:849
int QueryColliding(const ITEM *aItem, OBSTACLES &aObstacles, int aKindMask=ITEM::ANY_T, int aLimitCount=-1, bool aDifferentNetsOnly=true)
Find items colliding (closer than clearance) with the item aItem.
Definition: pns_node.cpp:267
virtual void UpdateItem(ITEM *aItem)=0
void StopRouting()
Definition: pns_router.cpp:719
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
virtual void EraseView()=0
Definition: seg.h:40
LOGGER * m_logger
Definition: pns_router.h:243
static ROUTER * theRouter
Definition: pns_router.cpp:58
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
ROUTER_MODE
Definition: pns_router.h:62
virtual bool IsFlashedOnLayer(const PNS::ITEM *aItem, int aLayer) const =0
void UpdateSizes(const SIZES_SETTINGS &aSizes)
Applies stored settings.
Definition: pns_router.cpp:570
Ignore collisions, mark obstacles.
void SetMode(ROUTER_MODE aMode)
Definition: pns_router.cpp:843
Store starting/ending primitives (pads, vias or segments) for a differential pair.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
LOGGER * Logger()
Definition: pns_router.cpp:803
bool StartDragging(const VECTOR2I &aP, ITEM *aItem, int aDragMode=DM_ANY)
Definition: pns_router.cpp:149
class ZONE, managed by a footprint
Definition: typeinfo.h:94
bool OfKind(int aKindMask) const
Return true if the item's type matches the mask aKindMask.
Definition: pns_item.h:138
bool SwitchLayer(int layer)
Definition: pns_router.cpp:762
static bool FindDpPrimitivePair(NODE *aWorld, const VECTOR2I &aP, ITEM *aItem, DP_PRIMITIVE_PAIR &aPair, wxString *aErrorMsg=nullptr)
SIZES_SETTINGS m_sizes
Definition: pns_router.h:241
virtual void Commit()=0
const ENTRIES & CItems() const
Definition: pns_itemset.h:136
void GetUpdatedItems(ITEM_VECTOR &aRemoved, ITEM_VECTOR &aAdded)
Return the list of items removed and added in this branch with respect to the root branch.
Definition: pns_node.cpp:1357
ITEM * GetBlockingObstacle() const
Definition: pns_line.h:206
virtual void RemoveItem(ITEM *aItem)=0
ROUTER_MODE m_mode
Definition: pns_router.h:242
void FlipPosture()
Definition: pns_router.cpp:753
bool RoutingInProgress() const
Definition: pns_router.cpp:114
const VIA & Via() const
Definition: pns_line.h:196
Definition: pad.h:57
std::vector< OBSTACLE > OBSTACLES
Definition: pns_node.h:153
wxString GetZoneName() const
Definition: zone.h:129
ROUTER_MODE Mode() const
Definition: pns_router.h:132
Push and Shove diff pair dimensions (gap) settings dialog.
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
ROUTING_SETTINGS & Settings()
Definition: pns_router.h:182
virtual int HoleClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true)=0
static ROUTER * GetInstance()
Definition: pns_router.cpp:78
void Log(EVENT_TYPE evt, const VECTOR2I &pos, const ITEM *item=nullptr)
Definition: pns_logger.cpp:64
const LAYER_RANGE & Layers() const
Definition: pns_item.h:154
bool m_forceMarkObstaclesMode
Definition: pns_router.h:238
std::vector< ITEM * > ITEM_VECTOR
Definition: pns_node.h:152
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:112
void markViolations(NODE *aNode, ITEM_SET &aCurrent, NODE::ITEM_VECTOR &aRemoved)
Definition: pns_router.cpp:461
Hold an object colliding with another object, along with some useful data about the collision.
Definition: pns_node.h:106
int GetCurrentLayer() const
Definition: pns_router.cpp:792