KiCad PCB EDA Suite
connectivity_algo.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KICAD, a free EDA CAD application.
3  *
4  * Copyright (C) 2016-2018 CERN
5  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
28 
29 #include <thread>
30 #include <mutex>
31 #include <algorithm>
32 #include <future>
33 
34 #ifdef PROFILE
35 #include <profile.h>
36 #endif
37 
38 
40 {
41  markItemNetAsDirty( aItem );
42 
43  switch( aItem->Type() )
44  {
45  case PCB_MODULE_T:
46  for( auto pad : static_cast<MODULE*>( aItem ) -> Pads() )
47  {
48  m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( pad ) ].MarkItemsAsInvalid();
49  m_itemMap.erase( static_cast<BOARD_CONNECTED_ITEM*>( pad ) );
50  }
51 
52  m_itemList.SetDirty( true );
53  break;
54 
55  case PCB_PAD_T:
56  m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid();
57  m_itemMap.erase( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) );
58  m_itemList.SetDirty( true );
59  break;
60 
61  case PCB_TRACE_T:
62  m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid();
63  m_itemMap.erase( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) );
64  m_itemList.SetDirty( true );
65  break;
66 
67  case PCB_VIA_T:
68  m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid();
69  m_itemMap.erase( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) );
70  m_itemList.SetDirty( true );
71  break;
72 
73  case PCB_ZONE_AREA_T:
74  {
75  m_itemMap[ static_cast<BOARD_CONNECTED_ITEM*>( aItem ) ].MarkItemsAsInvalid();
76  m_itemMap.erase ( static_cast<BOARD_CONNECTED_ITEM*>( aItem ) );
77  m_itemList.SetDirty( true );
78  break;
79  }
80 
81  case PCB_SEGZONE_T:
82  default:
83  return false;
84  }
85 
86  // Once we delete an item, it may connect between lists, so mark both as potentially invalid
87  m_itemList.SetHasInvalid( true );
88 
89  return true;
90 }
91 
92 
94 {
95  if( aItem->IsConnected() )
96  {
97  auto citem = static_cast<const BOARD_CONNECTED_ITEM*>( aItem );
98  MarkNetAsDirty( citem->GetNetCode() );
99  }
100  else
101  {
102  if( aItem->Type() == PCB_MODULE_T )
103  {
104  auto mod = static_cast <const MODULE*>( aItem );
105 
106  for( D_PAD* pad = mod->PadsList(); pad; pad = pad->Next() )
107  MarkNetAsDirty( pad->GetNetCode() );
108  }
109  }
110 }
111 
112 
114 {
115  if( !IsCopperLayer( aItem->GetLayer() ) )
116  return false;
117 
118  markItemNetAsDirty ( aItem );
119 
120  switch( aItem->Type() )
121  {
122  case PCB_NETINFO_T:
123  {
124  MarkNetAsDirty( static_cast<NETINFO_ITEM*>( aItem )->GetNet() );
125  break;
126  }
127  case PCB_MODULE_T:
128  for( auto pad : static_cast<MODULE*>( aItem ) -> Pads() )
129  {
130  if( m_itemMap.find( pad ) != m_itemMap.end() )
131  return false;
132 
133  add( m_itemList, pad );
134  }
135 
136  break;
137 
138  case PCB_PAD_T:
139  if( m_itemMap.find ( static_cast<D_PAD*>( aItem ) ) != m_itemMap.end() )
140  return false;
141 
142  add( m_itemList, static_cast<D_PAD*>( aItem ) );
143 
144  break;
145 
146  case PCB_TRACE_T:
147  {
148  if( m_itemMap.find( static_cast<TRACK*>( aItem ) ) != m_itemMap.end() )
149  return false;
150 
151  add( m_itemList, static_cast<TRACK*>( aItem ) );
152 
153  break;
154  }
155 
156  case PCB_VIA_T:
157  if( m_itemMap.find( static_cast<VIA*>( aItem ) ) != m_itemMap.end() )
158  return false;
159 
160  add( m_itemList, static_cast<VIA*>( aItem ) );
161 
162  break;
163 
164  case PCB_ZONE_AREA_T:
165  {
166  auto zone = static_cast<ZONE_CONTAINER*>( aItem );
167 
168  if( m_itemMap.find( static_cast<ZONE_CONTAINER*>( aItem ) ) != m_itemMap.end() )
169  return false;
170 
171  m_itemMap[zone] = ITEM_MAP_ENTRY();
172 
173  for( auto zitem : m_itemList.Add( zone ) )
174  m_itemMap[zone].Link(zitem);
175 
176  break;
177  }
178 
179  //N.B. SEGZONE items are deprecated and not to used for connectivity
180  case PCB_SEGZONE_T:
181  default:
182  return false;
183  }
184 
185  return true;
186 }
187 
188 
190 {
191 #ifdef CONNECTIVITY_DEBUG
192  printf("Search start\n");
193 #endif
194 
195 #ifdef PROFILE
196  PROF_COUNTER garbage_collection( "garbage-collection" );
197 #endif
198  std::vector<CN_ITEM*> garbage;
199  garbage.reserve( 1024 );
200 
201  m_itemList.RemoveInvalidItems( garbage );
202 
203  for( auto item : garbage )
204  delete item;
205 
206 #ifdef PROFILE
207  garbage_collection.Show();
208  PROF_COUNTER search_basic( "search-basic" );
209 #endif
210 
211  std::vector<CN_ITEM*> dirtyItems;
212  std::copy_if( m_itemList.begin(), m_itemList.end(), std::back_inserter( dirtyItems ),
213  [] ( CN_ITEM* aItem ) { return aItem->Dirty(); } );
214 
215  if( m_progressReporter )
216  {
217  m_progressReporter->SetMaxProgress( dirtyItems.size() );
219  }
220 
221  if( m_itemList.IsDirty() )
222  {
223  size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
224  ( dirtyItems.size() + 7 ) / 8 );
225 
226  std::atomic<size_t> nextItem( 0 );
227  std::vector<std::future<size_t>> returns( parallelThreadCount );
228 
229  auto conn_lambda = [&nextItem, &dirtyItems]
230  ( CN_LIST* aItemList, PROGRESS_REPORTER* aReporter) -> size_t
231  {
232  for( size_t i = nextItem++; i < dirtyItems.size(); i = nextItem++ )
233  {
234  CN_VISITOR visitor( dirtyItems[i] );
235  aItemList->FindNearby( dirtyItems[i], visitor );
236 
237  if( aReporter )
238  aReporter->AdvanceProgress();
239  }
240 
241  return 1;
242  };
243 
244  if( parallelThreadCount <= 1 )
245  conn_lambda( &m_itemList, m_progressReporter );
246  else
247  {
248  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
249  returns[ii] = std::async( std::launch::async, conn_lambda,
251 
252  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
253  {
254  // Here we balance returns with a 100ms timeout to allow UI updating
255  std::future_status status;
256  do
257  {
258  if( m_progressReporter )
260 
261  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
262  } while( status != std::future_status::ready );
263  }
264  }
265 
266  if( m_progressReporter )
268  }
269 
270 #ifdef PROFILE
271  search_basic.Show();
272 #endif
273 
275 
276 #ifdef CONNECTIVITY_DEBUG
277  printf("Search end\n");
278 #endif
279 
280 }
281 
282 
284 {
286  constexpr KICAD_T no_zones[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_MODULE_T, EOT };
287 
288  if( aMode == CSM_PROPAGATE )
289  return SearchClusters( aMode, no_zones, -1 );
290  else
291  return SearchClusters( aMode, types, -1 );
292 }
293 
294 
296  const KICAD_T aTypes[], int aSingleNet )
297 {
298  bool withinAnyNet = ( aMode != CSM_PROPAGATE );
299 
300  std::deque<CN_ITEM*> Q;
301  CN_ITEM* head = nullptr;
302  CLUSTERS clusters;
303 
304  if( m_itemList.IsDirty() )
306 
307  auto addToSearchList = [&head, withinAnyNet, aSingleNet, aTypes] ( CN_ITEM *aItem )
308  {
309  if( withinAnyNet && aItem->Net() <= 0 )
310  return;
311 
312  if( !aItem->Valid() )
313  return;
314 
315  if( aSingleNet >=0 && aItem->Net() != aSingleNet )
316  return;
317 
318  bool found = false;
319 
320  for( int i = 0; aTypes[i] != EOT; i++ )
321  {
322  if( aItem->Parent()->Type() == aTypes[i] )
323  {
324  found = true;
325  break;
326  }
327  }
328 
329  if( !found )
330  return;
331 
332  aItem->ListClear();
333  aItem->SetVisited( false );
334 
335  if( !head )
336  head = aItem;
337  else
338  head->ListInsert( aItem );
339  };
340 
341  std::for_each( m_itemList.begin(), m_itemList.end(), addToSearchList );
342 
343  while( head )
344  {
345  CN_CLUSTER_PTR cluster ( new CN_CLUSTER() );
346 
347  Q.clear();
348  CN_ITEM* root = head;
349  root->SetVisited ( true );
350 
351  head = root->ListRemove();
352 
353  Q.push_back( root );
354 
355  while( Q.size() )
356  {
357  CN_ITEM* current = Q.front();
358 
359  Q.pop_front();
360  cluster->Add( current );
361 
362  for( auto n : current->ConnectedItems() )
363  {
364  if( withinAnyNet && n->Net() != root->Net() )
365  continue;
366 
367  if( !n->Visited() && n->Valid() )
368  {
369  n->SetVisited( true );
370  Q.push_back( n );
371  head = n->ListRemove();
372  }
373  }
374  }
375 
376  clusters.push_back( cluster );
377  }
378 
379 
380  std::sort( clusters.begin(), clusters.end(), []( CN_CLUSTER_PTR a, CN_CLUSTER_PTR b ) {
381  return a->OriginNet() < b->OriginNet();
382  } );
383 
384 #ifdef CONNECTIVITY_DEBUG
385  printf("Active clusters: %d\n", clusters.size() );
386 
387  for( auto cl : clusters )
388  {
389  printf( "Net %d\n", cl->OriginNet() );
390  cl->Dump();
391  }
392 #endif
393 
394  return clusters;
395 }
396 
397 
399 {
400  for( int i = 0; i<aBoard->GetAreaCount(); i++ )
401  {
402  auto zone = aBoard->GetArea( i );
403  Add( zone );
404  }
405 
406  for( auto tv : aBoard->Tracks() )
407  Add( tv );
408 
409  for( auto mod : aBoard->Modules() )
410  {
411  for( auto pad : mod->Pads() )
412  Add( pad );
413  }
414 
415  /*wxLogTrace( "CN", "zones : %lu, pads : %lu vias : %lu tracks : %lu\n",
416  m_zoneList.Size(), m_padList.Size(),
417  m_viaList.Size(), m_trackList.Size() );*/
418 }
419 
420 
421 void CN_CONNECTIVITY_ALGO::Build( const std::vector<BOARD_ITEM*>& aItems )
422 {
423  for( auto item : aItems )
424  {
425  switch( item->Type() )
426  {
427  case PCB_TRACE_T:
428  case PCB_VIA_T:
429  case PCB_PAD_T:
430  Add( item );
431  break;
432 
433  case PCB_MODULE_T:
434  {
435  for( auto pad : static_cast<MODULE*>( item )->Pads() )
436  {
437  Add( pad );
438  }
439 
440  break;
441  }
442 
443  //N.B. SEGZONE items are deprecated and not to used for connectivity
444  case PCB_SEGZONE_T:
445  default:
446  break;
447  }
448  }
449 }
450 
451 
453 {
454  for( const auto& cluster : m_connClusters )
455  {
456  if( cluster->IsConflicting() )
457  {
458  wxLogTrace( "CN", "Conflicting nets in cluster %p\n", cluster.get() );
459  }
460  else if( cluster->IsOrphaned() )
461  {
462  wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]\n", cluster.get(),
463  (const char*) cluster->OriginNetName().c_str() );
464  }
465  else if( cluster->HasValidNet() )
466  {
467  // normal cluster: just propagate from the pads
468  int n_changed = 0;
469 
470  for( auto item : *cluster )
471  {
472  if( item->CanChangeNet() )
473  {
474  if( item->Valid() && item->Parent()->GetNetCode() != cluster->OriginNet() )
475  {
476  MarkNetAsDirty( item->Parent()->GetNetCode() );
477  MarkNetAsDirty( cluster->OriginNet() );
478 
479  item->Parent()->SetNetCode( cluster->OriginNet() );
480  n_changed++;
481  }
482  }
483  }
484 
485  if( n_changed )
486  wxLogTrace( "CN", "Cluster %p : net : %d %s\n", cluster.get(),
487  cluster->OriginNet(), (const char*) cluster->OriginNetName().c_str() );
488  else
489  wxLogTrace( "CN", "Cluster %p : nothing to propagate\n", cluster.get() );
490  }
491  else
492  {
493  wxLogTrace( "CN", "Cluster %p : connected to unused net\n", cluster.get() );
494  }
495  }
496 }
497 
498 
500 {
503 }
504 
505 
506 void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( ZONE_CONTAINER* aZone, std::vector<int>& aIslands )
507 {
508  if( aZone->GetFilledPolysList().IsEmpty() )
509  return;
510 
511  aIslands.clear();
512 
513  Remove( aZone );
514  Add( aZone );
515 
517 
518  for( const auto& cluster : m_connClusters )
519  {
520  if( cluster->Contains( aZone ) && cluster->IsOrphaned() )
521  {
522  for( auto z : *cluster )
523  {
524  if( z->Parent() == aZone )
525  {
526  aIslands.push_back( static_cast<CN_ZONE*>(z)->SubpolyIndex() );
527  }
528  }
529  }
530  }
531 
532  wxLogTrace( "CN", "Found %u isolated islands\n", (unsigned)aIslands.size() );
533 }
534 
535 void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
536 {
537  for ( auto& z : aZones )
538  Remove( z.m_zone );
539 
540  for ( auto& z : aZones )
541  {
542  if( !z.m_zone->GetFilledPolysList().IsEmpty() )
543  Add( z.m_zone );
544  }
545 
547 
548  for ( auto& zone : aZones )
549  {
550  if( zone.m_zone->GetFilledPolysList().IsEmpty() )
551  continue;
552 
553  for( const auto& cluster : m_connClusters )
554  {
555  if( cluster->Contains( zone.m_zone ) && cluster->IsOrphaned() )
556  {
557  for( auto z : *cluster )
558  {
559  if( z->Parent() == zone.m_zone )
560  {
561  zone.m_islands.push_back( static_cast<CN_ZONE*>(z)->SubpolyIndex() );
562  }
563  }
564  }
565  }
566  }
567 }
568 
569 
571 {
573  return m_ratsnestClusters;
574 }
575 
576 
578 {
579  if( aNet < 0 )
580  return;
581 
582  if( (int) m_dirtyNets.size() <= aNet )
583  {
584  int lastNet = m_dirtyNets.size() - 1;
585 
586  if( lastNet < 0 )
587  lastNet = 0;
588 
589  m_dirtyNets.resize( aNet + 1 );
590 
591  for( int i = lastNet; i < aNet + 1; i++ )
592  m_dirtyNets[i] = true;
593  }
594 
595  m_dirtyNets[aNet] = true;
596 }
597 
598 
600 {
601  auto zoneItem = static_cast<CN_ZONE*> ( aZone );
602 
603  if( zoneItem->Net() != aItem->Net() && !aItem->CanChangeNet() )
604  return;
605 
606  if( zoneItem->ContainsPoint( aItem->GetAnchor( 0 ) ) ||
607  ( aItem->Parent()->Type() == PCB_TRACE_T &&
608  zoneItem->ContainsPoint( aItem->GetAnchor( 1 ) ) ) )
609  {
610  zoneItem->Connect( aItem );
611  aItem->Connect( zoneItem );
612  }
613 }
614 
616 {
617  const auto refParent = static_cast<const ZONE_CONTAINER*>( aZoneA->Parent() );
618  const auto testedParent = static_cast<const ZONE_CONTAINER*>( aZoneB->Parent() );
619 
620  if( testedParent->Type () != PCB_ZONE_AREA_T )
621  return;
622 
623  if( aZoneB == aZoneA || refParent == testedParent )
624  return;
625 
626  if( aZoneB->Net() != aZoneA->Net() )
627  return; // we only test zones belonging to the same net
628 
629  const auto& outline = refParent->GetFilledPolysList().COutline( aZoneA->SubpolyIndex() );
630 
631  for( int i = 0; i < outline.PointCount(); i++ )
632  {
633  if( aZoneB->ContainsPoint( outline.CPoint( i ) ) )
634  {
635  aZoneA->Connect( aZoneB );
636  aZoneB->Connect( aZoneA );
637  return;
638  }
639  }
640 
641  const auto& outline2 = testedParent->GetFilledPolysList().COutline( aZoneB->SubpolyIndex() );
642 
643  for( int i = 0; i < outline2.PointCount(); i++ )
644  {
645  if( aZoneA->ContainsPoint( outline2.CPoint( i ) ) )
646  {
647  aZoneA->Connect( aZoneB );
648  aZoneB->Connect( aZoneA );
649  return;
650  }
651  }
652 }
653 
654 
655 bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
656 {
657  const auto parentA = aCandidate->Parent();
658  const auto parentB = m_item->Parent();
659 
660  if( !aCandidate->Valid() || !m_item->Valid() )
661  return true;
662 
663  if( parentA == parentB )
664  return true;
665 
666  if( !( parentA->GetLayerSet() & parentB->GetLayerSet() ).any() )
667  return true;
668 
669  // If both m_item and aCandidate are marked dirty, they will both be searched
670  // Since we are reciprocal in our connection, we arbitrarily pick one of the connections
671  // to conduct the expensive search
672  if( aCandidate->Dirty() && aCandidate < m_item )
673  return true;
674 
675  // We should handle zone-zone connection separately
676  if ( parentA->Type() == PCB_ZONE_AREA_T && parentB->Type() == PCB_ZONE_AREA_T )
677  {
678  checkZoneZoneConnection( static_cast<CN_ZONE*>( m_item ),
679  static_cast<CN_ZONE*>( aCandidate ) );
680  return true;
681  }
682 
683  if( parentA->Type() == PCB_ZONE_AREA_T )
684  {
685  checkZoneItemConnection( static_cast<CN_ZONE*>( aCandidate ), m_item );
686  return true;
687  }
688 
689  if( parentB->Type() == PCB_ZONE_AREA_T )
690  {
691  checkZoneItemConnection( static_cast<CN_ZONE*>( m_item ), aCandidate );
692  return true;
693  }
694 
695  // Items do not necessarily have reciprocity as we only check for anchors
696  // therefore, we check HitTest both directions A->B & B->A
697  // TODO: Check for collision geometry on extended features
698  wxPoint ptA1( aCandidate->GetAnchor( 0 ).x, aCandidate->GetAnchor( 0 ).y );
699  wxPoint ptA2( aCandidate->GetAnchor( 1 ).x, aCandidate->GetAnchor( 1 ).y );
700  wxPoint ptB1( m_item->GetAnchor( 0 ).x, m_item->GetAnchor( 0 ).y );
701  wxPoint ptB2( m_item->GetAnchor( 1 ).x, m_item->GetAnchor( 1 ).y );
702  if( parentA->HitTest( ptB1 ) || parentB->HitTest( ptA1 ) ||
703  ( parentA->Type() == PCB_TRACE_T && parentB->HitTest( ptA2 ) ) ||
704  ( parentB->Type() == PCB_TRACE_T && parentA->HitTest( ptB2 ) ) )
705  {
706  m_item->Connect( aCandidate );
707  aCandidate->Connect( m_item );
708  }
709 
710  return true;
711 };
712 
713 
715 {
716  m_ratsnestClusters.clear();
717  m_connClusters.clear();
718  m_itemMap.clear();
719  m_itemList.Clear();
720 
721 }
722 
723 
724 void CN_CONNECTIVITY_ALGO::ForEachItem( const std::function<void( CN_ITEM& )>& aFunc )
725 {
726  for( auto item : m_itemList )
727  aFunc( *item );
728 }
729 
730 
731 void CN_CONNECTIVITY_ALGO::ForEachAnchor( const std::function<void( CN_ANCHOR& )>& aFunc )
732 {
733  ForEachItem( [aFunc] ( CN_ITEM& item ) {
734  for( const auto& anchor : item.Anchors() )
735  aFunc( *anchor );
736  }
737  );
738 }
739 
740 
742 {
743  m_progressReporter = aReporter;
744 }
void RemoveInvalidItems(std::vector< CN_ITEM * > &aGarbage)
KICAD_T Type() const
Function Type()
Definition: base_struct.h:201
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
void ListInsert(T *item)
bool Remove(BOARD_ITEM *aItem)
void SetHasInvalid(bool aInvalid=true)
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
A progress reporter for use in multi-threaded environments.
void checkZoneItemConnection(CN_ZONE *aZone, CN_ITEM *aItem)
CN_ITEM * Add(D_PAD *pad)
void ClearDirtyFlags()
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:102
void ForEachAnchor(const std::function< void(CN_ANCHOR &)> &aFunc)
void SetVisited(bool aVisited)
void MarkNetAsDirty(int aNet)
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
bool Add(BOARD_ITEM *aItem)
void add(Container &c, BItem brditem)
void Show()
Print the elapsed time (in ms) to STDERR.
Definition: profile.h:93
CN_ANCHORS & Anchors()
The class PROF_COUNTER is a small class to help profiling.
Definition: profile.h:45
Class BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected an...
std::unordered_map< const BOARD_CONNECTED_ITEM *, ITEM_MAP_ENTRY > m_itemMap
void SetDirty(bool aDirty=true)
search types array terminator (End Of Types)
Definition: typeinfo.h:82
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:78
std::vector< bool > m_dirtyNets
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
bool ContainsPoint(const VECTOR2I p) const
const CLUSTERS SearchClusters(CLUSTER_SEARCH_MODE aMode, const KICAD_T aTypes[], int aSingleNet)
class MODULE, a footprint
Definition: typeinfo.h:89
void markItemNetAsDirty(const BOARD_ITEM *aItem)
DLIST_ITERATOR_WRAPPER< MODULE > Modules()
Definition: class_board.h:254
int SubpolyIndex() const
bool Valid() const
void ForEachItem(const std::function< void(CN_ITEM &)> &aFunc)
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
a few functions useful in geometry calculations.
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1020
int Net() const
const CONNECTED_ITEMS & ConnectedItems() const
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:540
virtual const VECTOR2I GetAnchor(int n) const
void FindIsolatedCopperIslands(ZONE_CONTAINER *aZone, std::vector< int > &aIslands)
void Build(BOARD *aBoard)
bool operator()(CN_ITEM *aCandidate)
const CLUSTERS & GetClusters()
BOARD_CONNECTED_ITEM * Parent() const
void checkZoneZoneConnection(CN_ZONE *aZoneA, CN_ZONE *aZoneB)
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:991
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
Struct CN_VISTOR.
virtual bool IsConnected() const
Function IsConnected() Returns information if the object is derived from BOARD_CONNECTED_ITEM.
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:104
size_t i
Definition: json11.cpp:597
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
std::shared_ptr< CN_CLUSTER > CN_CLUSTER_PTR
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
void Connect(CN_ITEM *b)
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST_ITERATOR_WRAPPER< TRACK > Tracks()
Definition: class_board.h:253
bool IsDirty() const
bool CanChangeNet() const
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
void SetMaxProgress(int aMaxProgress)
Fix the value thar gives the 100 precent progress bar length (inside the current virtual zone) ...
class SEGZONE, a segment used to fill a zone area (segment on a
Definition: typeinfo.h:97
std::vector< CN_CLUSTER_PTR > CLUSTERS
#define mod(a, n)
Definition: greymap.cpp:24
bool Dirty() const
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
PROGRESS_REPORTER * m_progressReporter