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 );
164  }
165  else
166  {
167  if( aDragMode & DM_FREE_ANGLE )
169  else
170  m_forceMarkObstaclesMode = false;
171 
172  m_dragger = std::make_unique<DRAGGER>( this );
173  }
174 
175  m_dragger->SetMode( aDragMode );
176  m_dragger->SetWorld( m_world.get() );
177  m_dragger->SetLogger( m_logger );
178  m_dragger->SetDebugDecorator( m_iface->GetDebugDecorator() );
179 
180  if( m_logger )
181  m_logger->Clear();
182 
183  if( m_logger && aStartItems.Size() )
184  {
185  m_logger->Log( LOGGER::EVT_START_DRAG, aP, aStartItems[0] );
186  }
187 
188  if( m_dragger->Start( aP, aStartItems ) )
189  {
191  return true;
192  }
193  else
194  {
195  m_dragger.reset();
196  m_state = IDLE;
197  return false;
198  }
199 }
200 
201 
202 bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, ITEM* aStartItem, int aLayer )
203 {
204  if( Settings().AllowDRCViolations() )
205  return true;
206 
208  {
210  {
211  SetFailureReason( _( "Diff pair gap is less than board minimum clearance." ) );
212  return false;
213  }
214  }
215 
216  ITEM_SET candidates = QueryHoverItems( aWhere );
217 
218  for( ITEM* item : candidates.Items() )
219  {
220  if( !item->IsRoutable() && item->Layers().Overlaps( aLayer ) )
221  {
222  BOARD_ITEM* parent = item->Parent();
223 
224  switch( parent->Type() )
225  {
226  case PCB_PAD_T:
227  {
228  PAD* pad = static_cast<PAD*>( parent );
229 
230  if( pad->GetAttribute() == PAD_ATTRIB::NPTH )
231  SetFailureReason( _( "Cannot start routing from a non-plated hole." ) );
232  }
233  break;
234 
235  case PCB_ZONE_T:
236  case PCB_FP_ZONE_T:
237  {
238  ZONE* zone = static_cast<ZONE*>( parent );
239 
240  if( !zone->GetZoneName().IsEmpty() )
241  {
242  SetFailureReason( wxString::Format( _( "Rule area '%s' disallows tracks." ),
243  zone->GetZoneName() ) );
244  }
245  else
246  {
247  SetFailureReason( _( "Rule area disallows tracks." ) );
248  }
249  }
250  break;
251 
252  case PCB_TEXT_T:
253  case PCB_FP_TEXT_T:
254  SetFailureReason( _( "Cannot start routing from a text item." ) );
255  break;
256 
257  case PCB_SHAPE_T:
258  case PCB_FP_SHAPE_T:
259  SetFailureReason( _( "Cannot start routing from a graphic." ) );
260 
261  default:
262  break;
263  }
264 
265  return false;
266  }
267  }
268 
269  VECTOR2I startPoint = aStartItem ? aStartItem->Anchor( 0 ) : aWhere;
270 
271  if( aStartItem && aStartItem->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) )
272  {
273  VECTOR2I otherEnd = aStartItem->Anchor( 1 );
274 
275  if( ( otherEnd - aWhere ).SquaredEuclideanNorm()
276  < ( startPoint - aWhere ).SquaredEuclideanNorm() )
277  {
278  startPoint = otherEnd;
279  }
280  }
281 
283  {
284  SHAPE_LINE_CHAIN dummyStartSeg;
285  LINE dummyStartLine;
286 
287  dummyStartSeg.Append( startPoint );
288  dummyStartSeg.Append( startPoint, true );
289 
290  dummyStartLine.SetShape( dummyStartSeg );
291  dummyStartLine.SetLayer( aLayer );
292  dummyStartLine.SetNet( aStartItem ? aStartItem->Net() : 0 );
293  dummyStartLine.SetWidth( m_sizes.TrackWidth() );
294 
295  if( m_world->CheckColliding( &dummyStartLine, ITEM::ANY_T ) )
296  {
297  ITEM_SET dummyStartSet( &dummyStartLine );
298  NODE::ITEM_VECTOR highlightedItems;
299 
300  markViolations( m_world.get(), dummyStartSet, highlightedItems );
301 
302  for( ITEM* item : highlightedItems )
303  m_iface->HideItem( item );
304 
305  SetFailureReason( _( "The routing start point violates DRC." ) );
306  return false;
307  }
308  }
309  else if( m_mode == PNS_MODE_ROUTE_DIFF_PAIR )
310  {
311  if( !aStartItem )
312  {
313  SetFailureReason( _( "Cannot start a differential pair in the middle of nowhere." ) );
314  return false;
315  }
316 
317  DP_PRIMITIVE_PAIR dpPair;
318  wxString errorMsg;
319 
320  if( !DIFF_PAIR_PLACER::FindDpPrimitivePair( m_world.get(), startPoint, aStartItem, dpPair,
321  &errorMsg ) )
322  {
323  SetFailureReason( errorMsg );
324  return false;
325  }
326 
327  SHAPE_LINE_CHAIN dummyStartSegA;
328  SHAPE_LINE_CHAIN dummyStartSegB;
329  LINE dummyStartLineA;
330  LINE dummyStartLineB;
331 
332  dummyStartSegA.Append( dpPair.AnchorN() );
333  dummyStartSegA.Append( dpPair.AnchorN(), true );
334 
335  dummyStartSegB.Append( dpPair.AnchorP() );
336  dummyStartSegB.Append( dpPair.AnchorP(), true );
337 
338  dummyStartLineA.SetShape( dummyStartSegA );
339  dummyStartLineA.SetLayer( aLayer );
340  dummyStartLineA.SetNet( dpPair.PrimN()->Net() );
341  dummyStartLineA.SetWidth( m_sizes.DiffPairWidth() );
342 
343  dummyStartLineB.SetShape( dummyStartSegB );
344  dummyStartLineB.SetLayer( aLayer );
345  dummyStartLineB.SetNet( dpPair.PrimP()->Net() );
346  dummyStartLineB.SetWidth( m_sizes.DiffPairWidth() );
347 
348  if( m_world->CheckColliding( &dummyStartLineA, ITEM::ANY_T )
349  || m_world->CheckColliding( &dummyStartLineB, ITEM::ANY_T ) )
350  {
351  ITEM_SET dummyStartSet;
352  NODE::ITEM_VECTOR highlightedItems;
353 
354  dummyStartSet.Add( dummyStartLineA );
355  dummyStartSet.Add( dummyStartLineB );
356  markViolations( m_world.get(), dummyStartSet, highlightedItems );
357 
358  for( ITEM* item : highlightedItems )
359  m_iface->HideItem( item );
360 
361  SetFailureReason( _( "The routing start point violates DRC." ) );
362  return false;
363  }
364  }
365 
366  return true;
367 }
368 
369 
370 bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer )
371 {
372  if( !isStartingPointRoutable( aP, aStartItem, aLayer ) )
373  return false;
374 
375  m_forceMarkObstaclesMode = false;
376 
377  switch( m_mode )
378  {
380  m_placer = std::make_unique<LINE_PLACER>( this );
381  break;
382 
384  m_placer = std::make_unique<DIFF_PAIR_PLACER>( this );
385  break;
386 
388  m_placer = std::make_unique<MEANDER_PLACER>( this );
389  break;
390 
392  m_placer = std::make_unique<DP_MEANDER_PLACER>( this );
393  break;
394 
396  m_placer = std::make_unique<MEANDER_SKEW_PLACER>( this );
397  break;
398 
399  default:
400  return false;
401  }
402 
403  m_placer->UpdateSizes( m_sizes );
404  m_placer->SetLayer( aLayer );
405  m_placer->SetDebugDecorator( m_iface->GetDebugDecorator() );
406  m_placer->SetLogger( m_logger );
407 
408  if( m_logger )
409  {
410  m_logger->Clear();
411  m_logger->Log( LOGGER::EVT_START_ROUTE, aP, aStartItem );
412  }
413 
414  if( m_placer->Start( aP, aStartItem ) )
415  {
417  return true;
418  }
419  else
420  {
421  m_state = IDLE;
422  return false;
423  }
424 }
425 
426 
427 void ROUTER::Move( const VECTOR2I& aP, ITEM* endItem )
428 {
429  if( m_logger )
430  m_logger->Log( LOGGER::EVT_MOVE, aP, endItem );
431 
432  switch( m_state )
433  {
434  case ROUTE_TRACK:
435  movePlacing( aP, endItem );
436  break;
437 
438  case DRAG_SEGMENT:
439  moveDragging( aP, endItem );
440  break;
441 
442  default:
443  break;
444  }
445 }
446 
447 
448 void ROUTER::moveDragging( const VECTOR2I& aP, ITEM* aEndItem )
449 {
450  m_iface->EraseView();
451 
452  m_dragger->Drag( aP );
453  ITEM_SET dragged = m_dragger->Traces();
454 
455  updateView( m_dragger->CurrentNode(), dragged, true );
456 }
457 
458 
459 void ROUTER::markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved )
460 {
461  auto updateItem =
462  [&]( ITEM* currentItem, ITEM* itemToMark )
463  {
464  std::unique_ptr<ITEM> tmp( itemToMark->Clone() );
465 
466  int clearance;
467  bool removeOriginal = true;
468  bool holeOnly = ( ( itemToMark->Marker() & MK_HOLE )
469  && !( itemToMark->Marker() & MK_VIOLATION ) );
470 
471  if( holeOnly )
472  clearance = aNode->GetHoleClearance( currentItem, itemToMark );
473  else
474  clearance = aNode->GetClearance( currentItem, itemToMark );
475 
476  if( itemToMark->Layers().IsMultilayer() && !currentItem->Layers().IsMultilayer() )
477  tmp->SetLayer( currentItem->Layer() );
478 
479  if( itemToMark->Kind() == ITEM::SOLID_T )
480  {
481  if( holeOnly || !m_iface->IsFlashedOnLayer( itemToMark, currentItem->Layer() ) )
482  {
483  SOLID* solid = static_cast<SOLID*>( tmp.get() );
484 
485  if( solid->Hole() )
486  {
487  solid->SetShape( solid->Hole()->Clone() );
488 
489  // Leave the pad flashing around the highlighted hole
490  removeOriginal = false;
491  }
492  }
493 
494  if( itemToMark->IsCompoundShapePrimitive() )
495  {
496  // We're only highlighting one (or more) of several primitives so we
497  // don't want all the other parts of the object to disappear
498  removeOriginal = false;
499  }
500  }
501 
502  m_iface->DisplayItem( tmp.get(), clearance );
503 
504  if( removeOriginal )
505  aRemoved.push_back( itemToMark );
506  };
507 
508  for( ITEM* item : aCurrent.Items() )
509  {
510  NODE::OBSTACLES obstacles;
511 
512  aNode->QueryColliding( item, obstacles, ITEM::ANY_T );
513 
514  if( item->OfKind( ITEM::LINE_T ) )
515  {
516  LINE* l = static_cast<LINE*>( item );
517 
518  if( l->EndsWithVia() )
519  {
520  VIA v( l->Via() );
521  aNode->QueryColliding( &v, obstacles, ITEM::ANY_T );
522  }
523  }
524 
525  for( OBSTACLE& obs : obstacles )
526  {
527  obs.m_item->Mark( obs.m_item->Marker() | MK_VIOLATION );
528  updateItem( item, obs.m_item );
529  }
530 
531  if( item->Kind() == ITEM::LINE_T )
532  {
533  LINE* line = static_cast<LINE*>( item );
534 
535  // Show clearance on any blocking obstacles
536  if( line->GetBlockingObstacle() )
537  updateItem( item, line->GetBlockingObstacle() );
538  }
539  }
540 }
541 
542 
543 void ROUTER::updateView( NODE* aNode, ITEM_SET& aCurrent, bool aDragging )
544 {
545  NODE::ITEM_VECTOR removed, added;
546  NODE::OBSTACLES obstacles;
547 
548  if( !aNode )
549  return;
550 
552  markViolations( aNode, aCurrent, removed );
553 
554  aNode->GetUpdatedItems( removed, added );
555 
556  for( ITEM* item : added )
557  {
559  int clearance = GetRuleResolver()->Clearance( item, nullptr );
560  m_iface->DisplayItem( item, clearance, aDragging );
561  }
562 
563  for( ITEM* item : removed )
564  m_iface->HideItem( item );
565 }
566 
567 
568 void ROUTER::UpdateSizes( const SIZES_SETTINGS& aSizes )
569 {
570  m_sizes = aSizes;
571 
572  // Change track/via size settings
573  if( m_state == ROUTE_TRACK )
574  {
575  m_placer->UpdateSizes( m_sizes );
576  }
577 }
578 
579 
580 void ROUTER::movePlacing( const VECTOR2I& aP, ITEM* aEndItem )
581 {
582  m_iface->EraseView();
583 
584  m_placer->Move( aP, aEndItem );
585  ITEM_SET current = m_placer->Traces();
586 
587  for( const ITEM* item : current.CItems() )
588  {
589  if( !item->OfKind( ITEM::LINE_T ) )
590  continue;
591 
592  const LINE* l = static_cast<const LINE*>( item );
593  int clearance = GetRuleResolver()->Clearance( item, nullptr );
594 
595  m_iface->DisplayItem( l, clearance );
596 
597  if( l->EndsWithVia() )
598  {
599  const VIA& via = l->Via();
600  int viaClearance = GetRuleResolver()->Clearance( &via, nullptr );
601  int holeClearance = GetRuleResolver()->HoleClearance( &via, nullptr );
602 
603  if( holeClearance + via.Drill() / 2 > viaClearance + via.Diameter() / 2 )
604  viaClearance = holeClearance + via.Drill() / 2 - via.Diameter() / 2;
605 
606  m_iface->DisplayItem( &l->Via(), viaClearance );
607  }
608  }
609 
610  //ITEM_SET tmp( &current );
611 
612  updateView( m_placer->CurrentNode( true ), current );
613 }
614 
615 
617 {
618  if( m_state == ROUTE_TRACK && !m_placer->HasPlacedAnything() )
619  return;
620 
621  NODE::ITEM_VECTOR removed;
622  NODE::ITEM_VECTOR added;
623  NODE::ITEM_VECTOR changed;
624 
625  aNode->GetUpdatedItems( removed, added );
626 
627  for( ITEM* item : removed )
628  {
629  bool is_changed = false;
630 
631  // Items in remove/add that share the same parent are just updated versions
632  // We move them to the updated vector to preserve attributes such as UUID and pad data
633  if( item->Parent() )
634  {
635  for( NODE::ITEM_VECTOR::iterator added_it = added.begin();
636  added_it != added.end(); ++added_it )
637  {
638  if( ( *added_it )->Parent() && ( *added_it )->Parent() == item->Parent() )
639  {
640  changed.push_back( *added_it );
641  added.erase( added_it );
642  is_changed = true;
643  break;
644  }
645  }
646  }
647 
648  if( !is_changed && !item->IsVirtual() )
649  m_iface->RemoveItem( item );
650  }
651 
652  for( ITEM* item : added )
653  {
654  if( !item->IsVirtual() )
655  {
656  m_iface->AddItem( item );
657  }
658  }
659 
660  for( ITEM* item : changed )
661  {
662  if( !item->IsVirtual() )
663  {
664  m_iface->UpdateItem( item );
665  }
666  }
667 
668  m_iface->Commit();
669  m_world->Commit( aNode );
670 }
671 
672 
673 bool ROUTER::FixRoute( const VECTOR2I& aP, ITEM* aEndItem, bool aForceFinish )
674 {
675  bool rv = false;
676 
677  if( m_logger )
678  m_logger->Log( LOGGER::EVT_FIX, aP, aEndItem );
679 
680  switch( m_state )
681  {
682  case ROUTE_TRACK:
683  rv = m_placer->FixRoute( aP, aEndItem, aForceFinish );
684  break;
685 
686  case DRAG_SEGMENT:
687  rv = m_dragger->FixRoute();
688  break;
689 
690  default:
691  break;
692  }
693 
694  return rv;
695 }
696 
697 
699 {
700  if( !RoutingInProgress() )
701  return;
702 
703  m_placer->UnfixRoute();
704 }
705 
706 
708 {
709  if( m_state == ROUTE_TRACK )
710  m_placer->CommitPlacement();
711 
712  StopRouting();
713 }
714 
715 
717 {
718  // Update the ratsnest with new changes
719 
720  if( m_placer )
721  {
722  std::vector<int> nets;
723  m_placer->GetModifiedNets( nets );
724 
725  // Update the ratsnest with new changes
726  for( int n : nets )
727  m_iface->UpdateNet( n );
728  }
729 
730  if( !RoutingInProgress() )
731  return;
732 
733  m_placer.reset();
734  m_dragger.reset();
735 
736  m_iface->EraseView();
737 
738  m_state = IDLE;
739  m_world->KillChildren();
740  m_world->ClearRanks();
741 }
742 
743 
745 {
746  m_iface->EraseView();
747 }
748 
749 
751 {
752  if( m_state == ROUTE_TRACK )
753  {
754  m_placer->FlipPosture();
755  }
756 }
757 
758 
759 bool ROUTER::SwitchLayer( int aLayer )
760 {
761  if( m_state == ROUTE_TRACK )
762  return m_placer->SetLayer( aLayer );
763 
764  return false;
765 }
766 
767 
769 {
770  if( m_state == ROUTE_TRACK )
771  {
772  bool toggle = !m_placer->IsPlacingVia();
773  m_placer->ToggleVia( toggle );
774  }
775 }
776 
777 
778 const std::vector<int> ROUTER::GetCurrentNets() const
779 {
780  if( m_placer )
781  return m_placer->CurrentNets();
782  else if( m_dragger )
783  return m_dragger->CurrentNets();
784 
785  return std::vector<int>();
786 }
787 
788 
790 {
791  if( m_placer )
792  return m_placer->CurrentLayer();
793  else if( m_dragger )
794  return m_dragger->CurrentLayer();
795 
796  return -1;
797 }
798 
799 
801 {
802  return m_logger;
803 }
804 
805 
807 {
808  if( !m_placer )
809  return false;
810 
811  return m_placer->IsPlacingVia();
812 }
813 
814 
816 {
818 
819  switch( m_settings->GetCornerMode() )
820  {
821  case DIRECTION_45::CORNER_MODE::MITERED_45: mode = DIRECTION_45::CORNER_MODE::ROUNDED_45; break;
822  case DIRECTION_45::CORNER_MODE::ROUNDED_45: mode = DIRECTION_45::CORNER_MODE::MITERED_90; break;
823  case DIRECTION_45::CORNER_MODE::MITERED_90: mode = DIRECTION_45::CORNER_MODE::ROUNDED_90; break;
824  case DIRECTION_45::CORNER_MODE::ROUNDED_90: mode = DIRECTION_45::CORNER_MODE::MITERED_45; break;
825  }
826 
827  m_settings->SetCornerMode( mode );
828 }
829 
830 
831 void ROUTER::SetOrthoMode( bool aEnable )
832 {
833  if( !m_placer )
834  return;
835 
836  m_placer->SetOrthoMode( aEnable );
837 }
838 
839 
841 {
842  m_mode = aMode;
843 }
844 
845 
847 {
848  m_iface = aIface;
849 }
850 
851 void ROUTER::BreakSegment( ITEM *aItem, const VECTOR2I& aP )
852 {
853  NODE *node = m_world->Branch();
854 
855  LINE_PLACER placer( this );
856 
857  if( placer.SplitAdjacentSegments( node, aItem, aP ) )
858  {
859  CommitRouting( node );
860  }
861  else
862  {
863  delete node;
864  }
865 }
866 
867 }
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:448
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:146
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
DIRECTION_45::CORNER_MODE GetCornerMode() const
void ToggleCornerMode()
Definition: pns_router.cpp:815
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:707
RULE_RESOLVER * GetRuleResolver() const
Definition: pns_router.h:169
void ClearViewDecorations()
Definition: pns_router.cpp:744
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:202
void SyncWorld()
Definition: pns_router.cpp:92
bool IsPlacingVia() const
Definition: pns_router.cpp:806
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
std::unique_ptr< PLACEMENT_ALGO > m_placer
Definition: pns_router.h:230
BOX2I m_visibleViewArea
Definition: pns_router.h:224
void SetCornerMode(DIRECTION_45::CORNER_MODE aMode)
const std::vector< int > GetCurrentNets() const
Definition: pns_router.cpp:778
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:236
virtual int Clearance(const ITEM *aA, const ITEM *aB)=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:239
virtual void AddItem(ITEM *aItem)=0
int GetHoleClearance(const ITEM *aA, const ITEM *aB) const
Definition: pns_node.cpp:113
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
void SetOrthoMode(bool aEnable)
Definition: pns_router.cpp:831
bool EndsWithVia() const
Definition: pns_line.h:191
void ToggleViaPlacement()
Definition: pns_router.cpp:768
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:227
void ClearWorld()
Definition: pns_router.cpp:102
std::unique_ptr< DRAG_ALGO > m_dragger
Definition: pns_router.h:231
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:698
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
int GetClearance(const ITEM *aA, const ITEM *aB) const
Definition: pns_node.cpp:101
void BreakSegment(ITEM *aItem, const VECTOR2I &aP)
Definition: pns_router.cpp:851
void updateView(NODE *aNode, ITEM_SET &aCurrent, bool aDragging=false)
Definition: pns_router.cpp:543
NODE * m_lastNode
Definition: pns_router.h:228
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
virtual int HoleClearance(const ITEM *aA, const ITEM *aB)=0
void SetMaximum()
Definition: box2.h:57
bool FixRoute(const VECTOR2I &aP, ITEM *aItem, bool aForceFinish=false)
Definition: pns_router.cpp:673
void SetFailureReason(const wxString &aReason)
Definition: pns_router.h:202
void SetShape(SHAPE *shape)
Definition: pns_solid.h:89
RouterState m_state
Definition: pns_router.h:225
virtual void ClearCacheForItem(const ITEM *aItem)
Definition: pns_node.h:98
#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:234
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:580
const SHAPE * Hole() const override
Definition: pns_solid.h:81
void Move(const VECTOR2I &aP, ITEM *aItem)
Definition: pns_router.cpp:427
bool StartRouting(const VECTOR2I &aP, ITEM *aItem, int aLayer)
Definition: pns_router.cpp:370
void Clear()
Definition: pns_logger.cpp:40
void SetInterface(ROUTER_IFACE *aIface)
Definition: pns_router.cpp:846
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:266
virtual void UpdateItem(ITEM *aItem)=0
void StopRouting()
Definition: pns_router.cpp:716
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:242
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:568
Ignore collisions, mark obstacles.
void SetMode(ROUTER_MODE aMode)
Definition: pns_router.cpp:840
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:800
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:759
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:240
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:1338
ITEM * GetBlockingObstacle() const
Definition: pns_line.h:206
virtual void RemoveItem(ITEM *aItem)=0
ROUTER_MODE m_mode
Definition: pns_router.h:241
void FlipPosture()
Definition: pns_router.cpp:750
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:151
wxString GetZoneName() const
Definition: zone.h:129
ROUTER_MODE Mode() const
Definition: pns_router.h:131
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:181
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:237
std::vector< ITEM * > ITEM_VECTOR
Definition: pns_node.h:150
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:459
Hold an object colliding with another object, along with some useful data about the collision.
Definition: pns_node.h:104
int GetCurrentLayer() const
Definition: pns_router.cpp:789