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  * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, you may find one here:
21  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22  * or you may search the http://www.gnu.org website for the version 2 license,
23  * or you may write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26 
30 #include <board_commit.h>
31 
32 #include <thread>
33 #include <mutex>
34 #include <algorithm>
35 #include <future>
36 
37 #ifdef PROFILE
38 #include <profile.h>
39 #endif
40 
41 
43 {
44  markItemNetAsDirty( aItem );
45 
46  switch( aItem->Type() )
47  {
48  case PCB_MODULE_T:
49  for( auto pad : static_cast<MODULE*>( aItem ) -> Pads() )
50  {
51  m_itemMap[pad].MarkItemsAsInvalid();
52  m_itemMap.erase( pad );
53  }
54 
55  m_itemList.SetDirty( true );
56  break;
57 
58  case PCB_PAD_T:
59  m_itemMap[aItem].MarkItemsAsInvalid();
60  m_itemMap.erase( aItem );
61  m_itemList.SetDirty( true );
62  break;
63 
64  case PCB_TRACE_T:
65  case PCB_ARC_T:
66  m_itemMap[aItem].MarkItemsAsInvalid();
67  m_itemMap.erase( aItem );
68  m_itemList.SetDirty( true );
69  break;
70 
71  case PCB_VIA_T:
72  m_itemMap[aItem].MarkItemsAsInvalid();
73  m_itemMap.erase( aItem );
74  m_itemList.SetDirty( true );
75  break;
76 
77  case PCB_ZONE_AREA_T:
78  {
79  m_itemMap[aItem].MarkItemsAsInvalid();
80  m_itemMap.erase ( aItem );
81  m_itemList.SetDirty( true );
82  break;
83  }
84 
85  default:
86  return false;
87  }
88 
89  // Once we delete an item, it may connect between lists, so mark both as potentially invalid
90  m_itemList.SetHasInvalid( true );
91 
92  return true;
93 }
94 
95 
97 {
98  if( aItem->IsConnected() )
99  {
100  auto citem = static_cast<const BOARD_CONNECTED_ITEM*>( aItem );
101  MarkNetAsDirty( citem->GetNetCode() );
102  }
103  else
104  {
105  if( aItem->Type() == PCB_MODULE_T )
106  {
107  auto mod = static_cast <const MODULE*>( aItem );
108 
109  for( auto pad : mod->Pads() )
110  MarkNetAsDirty( pad->GetNetCode() );
111  }
112  }
113 }
114 
115 
117 {
118  if( !aItem->IsOnCopperLayer() )
119  return false;
120 
121  markItemNetAsDirty ( aItem );
122 
123  switch( aItem->Type() )
124  {
125  case PCB_NETINFO_T:
126  {
127  MarkNetAsDirty( static_cast<NETINFO_ITEM*>( aItem )->GetNet() );
128  break;
129  }
130  case PCB_MODULE_T:
131  for( auto pad : static_cast<MODULE*>( aItem ) -> Pads() )
132  {
133  if( m_itemMap.find( pad ) != m_itemMap.end() )
134  return false;
135 
136  add( m_itemList, pad );
137  }
138 
139  break;
140 
141  case PCB_PAD_T:
142  if( m_itemMap.find ( aItem ) != m_itemMap.end() )
143  return false;
144 
145  add( m_itemList, static_cast<D_PAD*>( aItem ) );
146 
147  break;
148 
149  case PCB_TRACE_T:
150  {
151  if( m_itemMap.find( aItem ) != m_itemMap.end() )
152  return false;
153 
154  add( m_itemList, static_cast<TRACK*>( aItem ) );
155 
156  break;
157  }
158 
159  case PCB_ARC_T:
160  {
161  if( m_itemMap.find( aItem ) != m_itemMap.end() )
162  return false;
163 
164  add( m_itemList, static_cast<ARC*>( aItem ) );
165 
166  break;
167  }
168 
169  case PCB_VIA_T:
170  if( m_itemMap.find( aItem ) != m_itemMap.end() )
171  return false;
172 
173  add( m_itemList, static_cast<VIA*>( aItem ) );
174 
175  break;
176 
177  case PCB_ZONE_AREA_T:
178  {
179  auto zone = static_cast<ZONE_CONTAINER*>( aItem );
180 
181  if( m_itemMap.find( aItem ) != m_itemMap.end() )
182  return false;
183 
184  m_itemMap[zone] = ITEM_MAP_ENTRY();
185 
186  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
187  for( auto zitem : m_itemList.Add( zone, layer ) )
188  m_itemMap[zone].Link( zitem );
189 
190  break;
191  }
192 
193  default:
194  return false;
195  }
196 
197  return true;
198 }
199 
200 
202 {
203 #ifdef PROFILE
204  PROF_COUNTER garbage_collection( "garbage-collection" );
205 #endif
206  std::vector<CN_ITEM*> garbage;
207  garbage.reserve( 1024 );
208 
209  m_itemList.RemoveInvalidItems( garbage );
210 
211  for( auto item : garbage )
212  delete item;
213 
214 #ifdef PROFILE
215  garbage_collection.Show();
216  PROF_COUNTER search_basic( "search-basic" );
217 #endif
218 
219  std::vector<CN_ITEM*> dirtyItems;
220  std::copy_if( m_itemList.begin(), m_itemList.end(), std::back_inserter( dirtyItems ),
221  [] ( CN_ITEM* aItem ) { return aItem->Dirty(); } );
222 
223  if( m_progressReporter )
224  {
225  m_progressReporter->SetMaxProgress( dirtyItems.size() );
227  }
228 
229  if( m_itemList.IsDirty() )
230  {
231  size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
232  ( dirtyItems.size() + 7 ) / 8 );
233 
234  std::atomic<size_t> nextItem( 0 );
235  std::vector<std::future<size_t>> returns( parallelThreadCount );
236 
237  auto conn_lambda = [&nextItem, &dirtyItems]
238  ( CN_LIST* aItemList, PROGRESS_REPORTER* aReporter) -> size_t
239  {
240  for( size_t i = nextItem++; i < dirtyItems.size(); i = nextItem++ )
241  {
242  CN_VISITOR visitor( dirtyItems[i] );
243  aItemList->FindNearby( dirtyItems[i], visitor );
244 
245  if( aReporter )
246  aReporter->AdvanceProgress();
247  }
248 
249  return 1;
250  };
251 
252  if( parallelThreadCount <= 1 )
253  conn_lambda( &m_itemList, m_progressReporter );
254  else
255  {
256  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
257  returns[ii] = std::async( std::launch::async, conn_lambda,
259 
260  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
261  {
262  // Here we balance returns with a 100ms timeout to allow UI updating
263  std::future_status status;
264  do
265  {
266  if( m_progressReporter )
268 
269  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
270  } while( status != std::future_status::ready );
271  }
272  }
273 
274  if( m_progressReporter )
276  }
277 
278 #ifdef PROFILE
279  search_basic.Show();
280 #endif
281 
283 }
284 
285 
287 {
288  constexpr KICAD_T types[] =
290  constexpr KICAD_T no_zones[] =
292 
293  if( aMode == CSM_PROPAGATE )
294  return SearchClusters( aMode, no_zones, -1 );
295  else
296  return SearchClusters( aMode, types, -1 );
297 }
298 
299 
301  const KICAD_T aTypes[], int aSingleNet )
302 {
303  bool withinAnyNet = ( aMode != CSM_PROPAGATE );
304 
305  std::deque<CN_ITEM*> Q;
306  std::set<CN_ITEM*> item_set;
307 
308  CLUSTERS clusters;
309 
310  if( m_itemList.IsDirty() )
312 
313  auto addToSearchList = [&item_set, withinAnyNet, aSingleNet, aTypes] ( CN_ITEM *aItem )
314  {
315  if( withinAnyNet && aItem->Net() <= 0 )
316  return;
317 
318  if( !aItem->Valid() )
319  return;
320 
321  if( aSingleNet >=0 && aItem->Net() != aSingleNet )
322  return;
323 
324  bool found = false;
325 
326  for( int i = 0; aTypes[i] != EOT; i++ )
327  {
328  if( aItem->Parent()->Type() == aTypes[i] )
329  {
330  found = true;
331  break;
332  }
333  }
334 
335  if( !found )
336  return;
337 
338  aItem->SetVisited( false );
339 
340  item_set.insert( aItem );
341  };
342 
343  std::for_each( m_itemList.begin(), m_itemList.end(), addToSearchList );
344 
345  while( !item_set.empty() )
346  {
347  CN_CLUSTER_PTR cluster ( new CN_CLUSTER() );
348  CN_ITEM* root;
349  auto it = item_set.begin();
350 
351  while( it != item_set.end() && (*it)->Visited() )
352  it = item_set.erase( item_set.begin() );
353 
354  if( it == item_set.end() )
355  break;
356 
357  root = *it;
358  root->SetVisited ( true );
359 
360  Q.clear();
361  Q.push_back( root );
362 
363  while( Q.size() )
364  {
365  CN_ITEM* current = Q.front();
366 
367  Q.pop_front();
368  cluster->Add( current );
369 
370  for( auto n : current->ConnectedItems() )
371  {
372  if( withinAnyNet && n->Net() != root->Net() )
373  continue;
374 
375  if( !n->Visited() && n->Valid() )
376  {
377  n->SetVisited( true );
378  Q.push_back( n );
379  }
380  }
381  }
382 
383  clusters.push_back( cluster );
384  }
385 
386 
387  std::sort( clusters.begin(), clusters.end(), []( CN_CLUSTER_PTR a, CN_CLUSTER_PTR b ) {
388  return a->OriginNet() < b->OriginNet();
389  } );
390 
391  return clusters;
392 }
393 
394 
395 void reportProgress( PROGRESS_REPORTER* aReporter, int aCount, int aSize, int aDelta )
396 {
397  if( aReporter && ( ( aCount % aDelta ) == 0 || aCount == aSize - 1 ) )
398  {
399  aReporter->SetCurrentProgress( (double) aCount / (double) aSize );
400  aReporter->KeepRefreshing( false );
401  }
402 }
403 
404 
406 {
407  const int delta = 100; // Number of additions between 2 calls to the progress bar
408  int ii = 0;
409  int size = 0;
410 
411  size += aBoard->Zones().size();
412  size += aBoard->Tracks().size();
413 
414  for( MODULE* mod : aBoard->Modules() )
415  size += mod->Pads().size();
416 
417  size *= 2; // Our caller us gets the other half of the progress bar
418 
419  for( ZONE_CONTAINER* zone : aBoard->Zones() )
420  {
421  Add( zone );
422  reportProgress( aReporter, ii++, size, delta );
423  }
424 
425  for( TRACK* tv : aBoard->Tracks() )
426  {
427  Add( tv );
428  reportProgress( aReporter, ii++, size, delta );
429  }
430 
431  for( MODULE* mod : aBoard->Modules() )
432  {
433  for( D_PAD* pad : mod->Pads() )
434  {
435  Add( pad );
436  reportProgress( aReporter, ii++, size, delta );
437  }
438  }
439 }
440 
441 
442 void CN_CONNECTIVITY_ALGO::Build( const std::vector<BOARD_ITEM*>& aItems )
443 {
444  for( auto item : aItems )
445  {
446  switch( item->Type() )
447  {
448  case PCB_TRACE_T:
449  case PCB_ARC_T:
450  case PCB_VIA_T:
451  case PCB_PAD_T:
452  Add( item );
453  break;
454 
455  case PCB_MODULE_T:
456  {
457  for( auto pad : static_cast<MODULE*>( item )->Pads() )
458  {
459  Add( pad );
460  }
461 
462  break;
463  }
464 
465  default:
466  break;
467  }
468  }
469 }
470 
471 
473 {
474  for( const auto& cluster : m_connClusters )
475  {
476  if( cluster->IsConflicting() )
477  {
478  wxLogTrace( "CN", "Conflicting nets in cluster %p\n", cluster.get() );
479  }
480  else if( cluster->IsOrphaned() )
481  {
482  wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]\n", cluster.get(),
483  (const char*) cluster->OriginNetName().c_str() );
484  }
485  else if( cluster->HasValidNet() )
486  {
487  // normal cluster: just propagate from the pads
488  int n_changed = 0;
489 
490  for( auto item : *cluster )
491  {
492  if( item->CanChangeNet() )
493  {
494  if( item->Valid() && item->Parent()->GetNetCode() != cluster->OriginNet() )
495  {
496  MarkNetAsDirty( item->Parent()->GetNetCode() );
497  MarkNetAsDirty( cluster->OriginNet() );
498 
499  if( aCommit )
500  aCommit->Modify( item->Parent() );
501 
502  item->Parent()->SetNetCode( cluster->OriginNet() );
503  n_changed++;
504  }
505  }
506  }
507 
508  if( n_changed )
509  {
510  wxLogTrace( "CN", "Cluster %p : net : %d %s\n", cluster.get(),
511  cluster->OriginNet(), (const char*) cluster->OriginNetName().c_str() );
512  }
513  else
514  wxLogTrace( "CN", "Cluster %p : nothing to propagate\n", cluster.get() );
515  }
516  else
517  {
518  wxLogTrace( "CN", "Cluster %p : connected to unused net\n", cluster.get() );
519  }
520  }
521 }
522 
523 
525 {
527  propagateConnections( aCommit );
528 }
529 
530 
532  PCB_LAYER_ID aLayer,
533  std::vector<int>& aIslands )
534 {
535  if( aZone->GetFilledPolysList( aLayer ).IsEmpty() )
536  return;
537 
538  aIslands.clear();
539 
540  Remove( aZone );
541  Add( aZone );
542 
544 
545  for( const auto& cluster : m_connClusters )
546  {
547  if( cluster->Contains( aZone ) && cluster->IsOrphaned() )
548  {
549  for( auto z : *cluster )
550  {
551  if( z->Parent() == aZone && z->Layer() == aLayer )
552  {
553  aIslands.push_back( static_cast<CN_ZONE_LAYER*>(z)->SubpolyIndex() );
554  }
555  }
556  }
557  }
558 
559  wxLogTrace( "CN", "Found %u isolated islands\n", (unsigned)aIslands.size() );
560 }
561 
562 void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
563 {
564  for( auto& z : aZones )
565  {
566  Remove( z.m_zone );
567  Add( z.m_zone );
568  }
569 
571 
572  for( auto& zone : aZones )
573  {
574  for( PCB_LAYER_ID layer : zone.m_zone->GetLayerSet().Seq() )
575  {
576  if( zone.m_zone->GetFilledPolysList( layer ).IsEmpty() )
577  continue;
578 
579  for( const auto& cluster : m_connClusters )
580  {
581  if( cluster->Contains( zone.m_zone ) && cluster->IsOrphaned() )
582  {
583  for( auto z : *cluster )
584  {
585  if( z->Parent() == zone.m_zone && z->Layer() == layer )
586  {
587  zone.m_islands[layer].push_back(
588  static_cast<CN_ZONE_LAYER*>( z )->SubpolyIndex() );
589  }
590  }
591  }
592  }
593  }
594  }
595 }
596 
597 
599 {
601  return m_ratsnestClusters;
602 }
603 
604 
606 {
607  if( aNet < 0 )
608  return;
609 
610  if( (int) m_dirtyNets.size() <= aNet )
611  {
612  int lastNet = m_dirtyNets.size() - 1;
613 
614  if( lastNet < 0 )
615  lastNet = 0;
616 
617  m_dirtyNets.resize( aNet + 1 );
618 
619  for( int i = lastNet; i < aNet + 1; i++ )
620  m_dirtyNets[i] = true;
621  }
622 
623  m_dirtyNets[aNet] = true;
624 }
625 
626 
628 {
629  if( aZoneLayer->Net() != aItem->Net() && !aItem->CanChangeNet() )
630  return;
631 
632  if( !aZoneLayer->BBox().Intersects( aItem->BBox() ) )
633  return;
634 
635  int accuracy = 0;
636 
637  if( aItem->Parent()->Type() == PCB_VIA_T
638  || aItem->Parent()->Type() == PCB_TRACE_T
639  || aItem->Parent()->Type() == PCB_ARC_T )
640  {
641  accuracy = ( static_cast<TRACK*>( aItem->Parent() )->GetWidth() + 1 ) / 2;
642  }
643 
644  for( int i = 0; i < aItem->AnchorCount(); ++i )
645  {
646  if( aZoneLayer->ContainsPoint( aItem->GetAnchor( i ), accuracy ) )
647  {
648  aZoneLayer->Connect( aItem );
649  aItem->Connect( aZoneLayer );
650  return;
651  }
652  }
653 }
654 
656 {
657  const auto zoneA = static_cast<const ZONE_CONTAINER*>( aZoneLayerA->Parent() );
658  const auto zoneB = static_cast<const ZONE_CONTAINER*>( aZoneLayerB->Parent() );
659 
660  if( aZoneLayerA->Layer() != aZoneLayerB->Layer() )
661  return;
662 
663  if( aZoneLayerB->Net() != aZoneLayerA->Net() )
664  return; // we only test zones belonging to the same net
665 
666  const BOX2I& boxA = aZoneLayerA->BBox();
667  const BOX2I& boxB = aZoneLayerB->BBox();
668 
669  int radiusA = 0;
670  int radiusB = 0;
671 
672  if( zoneA->GetFilledPolysUseThickness() )
673  radiusA = ( zoneA->GetMinThickness() + 1 ) / 2;
674 
675  if( zoneB->GetFilledPolysUseThickness() )
676  radiusB = ( zoneB->GetMinThickness() + 1 ) / 2;
677 
678  PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aZoneLayerA->Layer() );
679 
680  const SHAPE_LINE_CHAIN& outline =
681  zoneA->GetFilledPolysList( layer ).COutline( aZoneLayerA->SubpolyIndex() );
682 
683  for( int i = 0; i < outline.PointCount(); i++ )
684  {
685  if( !boxB.Contains( outline.CPoint( i ) ) )
686  continue;
687 
688  if( aZoneLayerB->ContainsPoint( outline.CPoint( i ), radiusA ) )
689  {
690  aZoneLayerA->Connect( aZoneLayerB );
691  aZoneLayerB->Connect( aZoneLayerA );
692  return;
693  }
694  }
695 
696  const SHAPE_LINE_CHAIN& outline2 =
697  zoneB->GetFilledPolysList( layer ).COutline( aZoneLayerB->SubpolyIndex() );
698 
699  for( int i = 0; i < outline2.PointCount(); i++ )
700  {
701  if( !boxA.Contains( outline2.CPoint( i ) ) )
702  continue;
703 
704  if( aZoneLayerA->ContainsPoint( outline2.CPoint( i ), radiusB ) )
705  {
706  aZoneLayerA->Connect( aZoneLayerB );
707  aZoneLayerB->Connect( aZoneLayerA );
708  return;
709  }
710  }
711 }
712 
713 
714 bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
715 {
716  const BOARD_CONNECTED_ITEM* parentA = aCandidate->Parent();
717  const BOARD_CONNECTED_ITEM* parentB = m_item->Parent();
718 
719  if( !aCandidate->Valid() || !m_item->Valid() )
720  return true;
721 
722  if( parentA == parentB )
723  return true;
724 
725  if( !( parentA->GetLayerSet() & parentB->GetLayerSet() ).any() )
726  return true;
727 
728  // If both m_item and aCandidate are marked dirty, they will both be searched
729  // Since we are reciprocal in our connection, we arbitrarily pick one of the connections
730  // to conduct the expensive search
731  if( aCandidate->Dirty() && aCandidate < m_item )
732  return true;
733 
734  // We should handle zone-zone connection separately
735  if ( parentA->Type() == PCB_ZONE_AREA_T && parentB->Type() == PCB_ZONE_AREA_T )
736  {
737  checkZoneZoneConnection( static_cast<CN_ZONE_LAYER*>( m_item ),
738  static_cast<CN_ZONE_LAYER*>( aCandidate ) );
739  return true;
740  }
741 
742  if( parentA->Type() == PCB_ZONE_AREA_T )
743  {
744  checkZoneItemConnection( static_cast<CN_ZONE_LAYER*>( aCandidate ), m_item );
745  return true;
746  }
747 
748  if( parentB->Type() == PCB_ZONE_AREA_T )
749  {
750  checkZoneItemConnection( static_cast<CN_ZONE_LAYER*>( m_item ), aCandidate );
751  return true;
752  }
753 
754  int accuracyA = 0;
755  int accuracyB = 0;
756 
757  if( parentA->Type() == PCB_VIA_T
758  || parentA->Type() == PCB_TRACE_T
759  || parentA->Type() == PCB_ARC_T)
760  accuracyA = ( static_cast<const TRACK*>( parentA )->GetWidth() + 1 ) / 2;
761 
762  if( parentB->Type() == PCB_VIA_T
763  || parentB->Type() == PCB_TRACE_T
764  || parentB->Type() == PCB_ARC_T )
765  accuracyB = ( static_cast<const TRACK*>( parentB )->GetWidth() + 1 ) / 2;
766 
767  // Items do not necessarily have reciprocity as we only check for anchors
768  // therefore, we check HitTest both directions A->B & B->A
769  for( int i = 0; i < aCandidate->AnchorCount(); ++i )
770  {
771  if( parentB->HitTest( wxPoint( aCandidate->GetAnchor( i ) ), accuracyA ) )
772  {
773  m_item->Connect( aCandidate );
774  aCandidate->Connect( m_item );
775  return true;
776  }
777  }
778 
779  for( int i = 0; i < m_item->AnchorCount(); ++i )
780  {
781  if( parentA->HitTest( wxPoint( m_item->GetAnchor( i ) ), accuracyB ) )
782  {
783  m_item->Connect( aCandidate );
784  aCandidate->Connect( m_item );
785  return true;
786  }
787  }
788 
789  return true;
790 };
791 
792 
794 {
795  m_ratsnestClusters.clear();
796  m_connClusters.clear();
797  m_itemMap.clear();
798  m_itemList.Clear();
799 
800 }
801 
803 {
804  m_progressReporter = aReporter;
805 }
void RemoveInvalidItems(std::vector< CN_ITEM * > &aGarbage)
const CONNECTED_ITEMS & ConnectedItems() const
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
COMMIT & Modify(EDA_ITEM *aItem)
Modifies a given item in the model.
Definition: commit.h:103
void propagateConnections(BOARD_COMMIT *aCommit=nullptr)
bool Remove(BOARD_ITEM *aItem)
void SetHasInvalid(bool aInvalid=true)
void PropagateNets(BOARD_COMMIT *aCommit=nullptr)
Propagates nets from pads to other items in clusters.
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
void checkZoneItemConnection(CN_ZONE_LAYER *aZoneLayer, CN_ITEM *aItem)
A progress reporter for use in multi-threaded environments.
const BOX2I & BBox()
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
CN_ITEM * Add(D_PAD *pad)
void ClearDirtyFlags()
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:106
const SHAPE_POLY_SET & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:629
void SetVisited(bool aVisited)
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
bool IsDirty() const
void MarkNetAsDirty(int aNet)
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
bool Add(BOARD_ITEM *aItem)
bool Dirty() const
BOARD_CONNECTED_ITEM * Parent() const
void add(Container &c, BItem brditem)
int PointCount() const
Function PointCount()
The class PROF_COUNTER is a small class to help profiling.
Definition: profile.h:44
BOARD_CONNECTED_ITEM is a base class derived from BOARD_ITEM for items that can be connected and have...
void SetDirty(bool aDirty=true)
int Net() const
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:96
virtual int AnchorCount() const
const CLUSTERS SearchClusters(CLUSTER_SEARCH_MODE aMode, const KICAD_T aTypes[], int aSingleNet)
virtual bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
Definition: eda_item.h:295
bool Intersects(const BOX2< Vec > &aRect) const
Function Intersects.
Definition: box2.h:236
const VECTOR2I & CPoint(int aIndex) const
Function Point()
class MODULE, a footprint
Definition: typeinfo.h:89
virtual void SetCurrentProgress(double aProgress)
Set the progress value to aProgress (0..1)
PCB_LAYER_ID
A quick note on layer IDs:
void markItemNetAsDirty(const BOARD_ITEM *aItem)
void FindIsolatedCopperIslands(ZONE_CONTAINER *aZone, PCB_LAYER_ID aLayer, std::vector< int > &aIslands)
MODULES & Modules()
Definition: class_board.h:284
bool Contains(const Vec &aPoint) const
Function Contains.
Definition: box2.h:151
a few functions useful in geometry calculations.
void checkZoneZoneConnection(CN_ZONE_LAYER *aZoneLayerA, CN_ZONE_LAYER *aZoneLayerB)
int SubpolyIndex() const
bool ContainsPoint(const VECTOR2I p, int aAccuracy=0) const
void reportProgress(PROGRESS_REPORTER *aReporter, int aCount, int aSize, int aDelta)
virtual const VECTOR2I GetAnchor(int n) const
bool CanChangeNet() const
bool operator()(CN_ITEM *aCandidate)
const CLUSTERS & GetClusters()
void Build(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr)
ZONE_CONTAINERS & Zones()
Definition: class_board.h:290
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:186
Struct CN_VISTOR.
SHAPE_LINE_CHAIN.
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:108
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
std::shared_ptr< CN_CLUSTER > CN_CLUSTER_PTR
virtual int Layer() const
Function Layer()
virtual bool IsConnected() const
Function IsConnected() Returns information if the object is derived from BOARD_CONNECTED_ITEM.
void Connect(CN_ITEM *b)
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition: profile.h:99
CN_ITEM * m_item
the item we are looking for connections to
void SetMaxProgress(int aMaxProgress)
Fix the value thar gives the 100 precent progress bar length (inside the current virtual zone)
std::vector< CN_CLUSTER_PTR > CLUSTERS
TRACKS & Tracks()
Definition: class_board.h:281
virtual bool IsOnCopperLayer() const
std::unordered_map< const BOARD_ITEM *, ITEM_MAP_ENTRY > m_itemMap
const BOX2I & BBox()
virtual LSET GetLayerSet() const
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
bool Valid() const
KICAD_T Type() const
Function Type()
Definition: eda_item.h:181
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
PROGRESS_REPORTER * m_progressReporter