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