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_FOOTPRINT_T:
49  for( PAD* pad : static_cast<FOOTPRINT*>( 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_T:
78  m_itemMap[aItem].MarkItemsAsInvalid();
79  m_itemMap.erase ( aItem );
80  m_itemList.SetDirty( true );
81  break;
82 
83  default:
84  return false;
85  }
86 
87  // Once we delete an item, it may connect between lists, so mark both as potentially invalid
88  m_itemList.SetHasInvalid( true );
89 
90  return true;
91 }
92 
93 
95 {
96  if( aItem->IsConnected() )
97  {
98  auto citem = static_cast<const BOARD_CONNECTED_ITEM*>( aItem );
99  MarkNetAsDirty( citem->GetNetCode() );
100  }
101  else
102  {
103  if( aItem->Type() == PCB_FOOTPRINT_T )
104  {
105  const FOOTPRINT* footprint = static_cast<const FOOTPRINT*>( aItem );
106 
107  for( PAD* pad : footprint->Pads() )
108  MarkNetAsDirty( pad->GetNetCode() );
109  }
110  }
111 }
112 
113 
115 {
116  if( !aItem->IsOnCopperLayer() )
117  return false;
118 
119  markItemNetAsDirty ( aItem );
120 
121  switch( aItem->Type() )
122  {
123  case PCB_NETINFO_T:
124  MarkNetAsDirty( static_cast<NETINFO_ITEM*>( aItem )->GetNetCode() );
125  break;
126 
127  case PCB_FOOTPRINT_T:
128  for( PAD* pad : static_cast<FOOTPRINT*>( 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 ( aItem ) != m_itemMap.end() )
140  return false;
141 
142  add( m_itemList, static_cast<PAD*>( aItem ) );
143  break;
144 
145  case PCB_TRACE_T:
146  if( m_itemMap.find( aItem ) != m_itemMap.end() )
147  return false;
148 
149  add( m_itemList, static_cast<TRACK*>( aItem ) );
150  break;
151 
152  case PCB_ARC_T:
153  if( m_itemMap.find( aItem ) != m_itemMap.end() )
154  return false;
155 
156  add( m_itemList, static_cast<ARC*>( aItem ) );
157  break;
158 
159  case PCB_VIA_T:
160  if( m_itemMap.find( aItem ) != m_itemMap.end() )
161  return false;
162 
163  add( m_itemList, static_cast<VIA*>( aItem ) );
164  break;
165 
166  case PCB_ZONE_T:
167  {
168  ZONE* zone = static_cast<ZONE*>( aItem );
169 
170  if( m_itemMap.find( aItem ) != m_itemMap.end() )
171  return false;
172 
173  m_itemMap[zone] = ITEM_MAP_ENTRY();
174 
175  for( PCB_LAYER_ID layer : zone->GetLayerSet().Seq() )
176  {
177  for( CN_ITEM* zitem : m_itemList.Add( zone, layer ) )
178  m_itemMap[zone].Link( zitem );
179  }
180  }
181  break;
182 
183  default:
184  return false;
185  }
186 
187  return true;
188 }
189 
190 
192 {
193 #ifdef PROFILE
194  PROF_COUNTER garbage_collection( "garbage-collection" );
195 #endif
196  std::vector<CN_ITEM*> garbage;
197  garbage.reserve( 1024 );
198 
199  m_itemList.RemoveInvalidItems( garbage );
200 
201  for( auto item : garbage )
202  delete item;
203 
204 #ifdef PROFILE
205  garbage_collection.Show();
206  PROF_COUNTER search_basic( "search-basic" );
207 #endif
208 
209  std::vector<CN_ITEM*> dirtyItems;
210  std::copy_if( m_itemList.begin(), m_itemList.end(), std::back_inserter( dirtyItems ),
211  [] ( CN_ITEM* aItem )
212  {
213  return aItem->Dirty();
214  } );
215 
216  if( m_progressReporter )
217  {
218  m_progressReporter->SetMaxProgress( dirtyItems.size() );
219 
221  return;
222  }
223 
224  if( m_itemList.IsDirty() )
225  {
226  size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
227  ( dirtyItems.size() + 7 ) / 8 );
228 
229  std::atomic<size_t> nextItem( 0 );
230  std::vector<std::future<size_t>> returns( parallelThreadCount );
231 
232  auto conn_lambda =
233  [&nextItem, &dirtyItems]( CN_LIST* aItemList,
234  PROGRESS_REPORTER* aReporter) -> size_t
235  {
236  for( size_t i = nextItem++; i < dirtyItems.size(); i = nextItem++ )
237  {
238  CN_VISITOR visitor( dirtyItems[i] );
239  aItemList->FindNearby( dirtyItems[i], visitor );
240 
241  if( aReporter )
242  {
243  if( aReporter->IsCancelled() )
244  break;
245  else
246  aReporter->AdvanceProgress();
247  }
248  }
249 
250  return 1;
251  };
252 
253  if( parallelThreadCount <= 1 )
254  conn_lambda( &m_itemList, m_progressReporter );
255  else
256  {
257  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
258  {
259  returns[ii] = std::async( std::launch::async, conn_lambda, &m_itemList,
261  }
262 
263  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
264  {
265  // Here we balance returns with a 100ms timeout to allow UI updating
266  std::future_status status;
267  do
268  {
269  if( m_progressReporter )
271 
272  status = returns[ii].wait_for( std::chrono::milliseconds( 100 ) );
273  } while( status != std::future_status::ready );
274  }
275  }
276 
277  if( m_progressReporter )
279  }
280 
281 #ifdef PROFILE
282  search_basic.Show();
283 #endif
284 
286 }
287 
288 
290 {
291  constexpr KICAD_T types[] = { PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T, PCB_ZONE_T,
292  PCB_FOOTPRINT_T, EOT };
293  constexpr KICAD_T no_zones[] = { PCB_TRACE_T, PCB_ARC_T, PCB_PAD_T, PCB_VIA_T,
294  PCB_FOOTPRINT_T, EOT };
295 
296  if( aMode == CSM_PROPAGATE )
297  return SearchClusters( aMode, no_zones, -1 );
298  else
299  return SearchClusters( aMode, types, -1 );
300 }
301 
302 
304  const KICAD_T aTypes[],
305  int aSingleNet )
306 {
307  bool withinAnyNet = ( aMode != CSM_PROPAGATE );
308 
309  std::deque<CN_ITEM*> Q;
310  std::set<CN_ITEM*> item_set;
311 
312  CLUSTERS clusters;
313 
314  if( m_itemList.IsDirty() )
316 
317  auto addToSearchList =
318  [&item_set, withinAnyNet, aSingleNet, aTypes]( CN_ITEM *aItem )
319  {
320  if( withinAnyNet && aItem->Net() <= 0 )
321  return;
322 
323  if( !aItem->Valid() )
324  return;
325 
326  if( aSingleNet >=0 && aItem->Net() != aSingleNet )
327  return;
328 
329  bool found = false;
330 
331  for( int i = 0; aTypes[i] != EOT; i++ )
332  {
333  if( aItem->Parent()->Type() == aTypes[i] )
334  {
335  found = true;
336  break;
337  }
338  }
339 
340  if( !found )
341  return;
342 
343  aItem->SetVisited( false );
344 
345  item_set.insert( aItem );
346  };
347 
348  std::for_each( m_itemList.begin(), m_itemList.end(), addToSearchList );
349 
351  return CLUSTERS();
352 
353  while( !item_set.empty() )
354  {
355  CN_CLUSTER_PTR cluster = std::make_shared<CN_CLUSTER>();
356  CN_ITEM* root;
357  auto it = item_set.begin();
358 
359  while( it != item_set.end() && (*it)->Visited() )
360  it = item_set.erase( item_set.begin() );
361 
362  if( it == item_set.end() )
363  break;
364 
365  root = *it;
366  root->SetVisited( true );
367 
368  Q.clear();
369  Q.push_back( root );
370 
371  while( Q.size() )
372  {
373  CN_ITEM* current = Q.front();
374 
375  Q.pop_front();
376  cluster->Add( current );
377 
378  for( auto n : current->ConnectedItems() )
379  {
380  if( withinAnyNet && n->Net() != root->Net() )
381  continue;
382 
383  if( !n->Visited() && n->Valid() )
384  {
385  n->SetVisited( true );
386  Q.push_back( n );
387  }
388  }
389  }
390 
391  clusters.push_back( cluster );
392  }
393 
395  return CLUSTERS();
396 
397  std::sort( clusters.begin(), clusters.end(),
398  []( CN_CLUSTER_PTR a, CN_CLUSTER_PTR b )
399  {
400  return a->OriginNet() < b->OriginNet();
401  } );
402 
403  return clusters;
404 }
405 
406 
407 void reportProgress( PROGRESS_REPORTER* aReporter, int aCount, int aSize, int aDelta )
408 {
409  if( aReporter && ( ( aCount % aDelta ) == 0 || aCount == aSize - 1 ) )
410  {
411  aReporter->SetCurrentProgress( (double) aCount / (double) aSize );
412  aReporter->KeepRefreshing( false );
413  }
414 }
415 
416 
418 {
419  const int delta = 100; // Number of additions between 2 calls to the progress bar
420  int ii = 0;
421  int size = 0;
422 
423  size += aBoard->Zones().size();
424  size += aBoard->Tracks().size();
425 
426  for( FOOTPRINT* footprint : aBoard->Footprints() )
427  size += footprint->Pads().size();
428 
429  size *= 2; // Our caller us gets the other half of the progress bar
430 
431  for( ZONE* zone : aBoard->Zones() )
432  {
433  Add( zone );
434  reportProgress( aReporter, ii++, size, delta );
435  }
436 
437  for( TRACK* tv : aBoard->Tracks() )
438  {
439  Add( tv );
440  reportProgress( aReporter, ii++, size, delta );
441  }
442 
443  for( FOOTPRINT* footprint : aBoard->Footprints() )
444  {
445  for( PAD* pad : footprint->Pads() )
446  {
447  Add( pad );
448  reportProgress( aReporter, ii++, size, delta );
449  }
450  }
451 }
452 
453 
454 void CN_CONNECTIVITY_ALGO::Build( const std::vector<BOARD_ITEM*>& aItems )
455 {
456  for( auto item : aItems )
457  {
458  switch( item->Type() )
459  {
460  case PCB_TRACE_T:
461  case PCB_ARC_T:
462  case PCB_VIA_T:
463  case PCB_PAD_T:
464  Add( item );
465  break;
466 
467  case PCB_FOOTPRINT_T:
468  for( PAD* pad : static_cast<FOOTPRINT*>( item )->Pads() )
469  Add( pad );
470 
471  break;
472 
473  default:
474  break;
475  }
476  }
477 }
478 
479 
481 {
482  bool skipConflicts = ( aMode == PROPAGATE_MODE::SKIP_CONFLICTS );
483 
484  wxLogTrace( "CN", "propagateConnections: propagate skip conflicts? %d", skipConflicts );
485 
486  for( const auto& cluster : m_connClusters )
487  {
488  if( skipConflicts && cluster->IsConflicting() )
489  {
490  wxLogTrace( "CN", "Conflicting nets in cluster %p; skipping update", cluster.get() );
491  }
492  else if( cluster->IsOrphaned() )
493  {
494  wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]", cluster.get(),
495  (const char*) cluster->OriginNetName().c_str() );
496  }
497  else if( cluster->HasValidNet() )
498  {
499  if( cluster->IsConflicting() )
500  {
501  wxLogTrace( "CN", "Conflicting nets in cluster %p; chose %d (%s)", cluster.get(),
502  cluster->OriginNet(), cluster->OriginNetName() );
503  }
504 
505  // normal cluster: just propagate from the pads
506  int n_changed = 0;
507 
508  for( auto item : *cluster )
509  {
510  if( item->CanChangeNet() )
511  {
512  if( item->Valid() && item->Parent()->GetNetCode() != cluster->OriginNet() )
513  {
514  MarkNetAsDirty( item->Parent()->GetNetCode() );
515  MarkNetAsDirty( cluster->OriginNet() );
516 
517  if( aCommit )
518  aCommit->Modify( item->Parent() );
519 
520  item->Parent()->SetNetCode( cluster->OriginNet() );
521  n_changed++;
522  }
523  }
524  }
525 
526  if( n_changed )
527  {
528  wxLogTrace( "CN", "Cluster %p : net : %d %s", cluster.get(),
529  cluster->OriginNet(), (const char*) cluster->OriginNetName().c_str() );
530  }
531  else
532  wxLogTrace( "CN", "Cluster %p : nothing to propagate", cluster.get() );
533  }
534  else
535  {
536  wxLogTrace( "CN", "Cluster %p : connected to unused net", cluster.get() );
537  }
538  }
539 }
540 
541 
543 {
545  propagateConnections( aCommit, aMode );
546 }
547 
548 
550  std::vector<int>& aIslands )
551 {
552  if( aZone->GetFilledPolysList( aLayer ).IsEmpty() )
553  return;
554 
555  aIslands.clear();
556 
557  Remove( aZone );
558  Add( aZone );
559 
561 
562  for( const auto& cluster : m_connClusters )
563  {
564  if( cluster->Contains( aZone ) && cluster->IsOrphaned() )
565  {
566  for( auto z : *cluster )
567  {
568  if( z->Parent() == aZone && z->Layer() == aLayer )
569  {
570  aIslands.push_back( static_cast<CN_ZONE_LAYER*>(z)->SubpolyIndex() );
571  }
572  }
573  }
574  }
575 
576  wxLogTrace( "CN", "Found %u isolated islands\n", (unsigned)aIslands.size() );
577 }
578 
579 void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
580 {
581  for( auto& z : aZones )
582  {
583  Remove( z.m_zone );
584  Add( z.m_zone );
585  }
586 
588 
589  for( CN_ZONE_ISOLATED_ISLAND_LIST& zone : aZones )
590  {
591  for( PCB_LAYER_ID layer : zone.m_zone->GetLayerSet().Seq() )
592  {
593  if( zone.m_zone->GetFilledPolysList( layer ).IsEmpty() )
594  continue;
595 
596  for( const CN_CLUSTER_PTR& cluster : m_connClusters )
597  {
598  if( cluster->Contains( zone.m_zone ) && cluster->IsOrphaned() )
599  {
600  for( CN_ITEM* z : *cluster )
601  {
602  if( z->Parent() == zone.m_zone && z->Layer() == layer )
603  {
604  zone.m_islands[layer].push_back(
605  static_cast<CN_ZONE_LAYER*>( z )->SubpolyIndex() );
606  }
607  }
608  }
609  }
610  }
611  }
612 }
613 
614 
616 {
618  return m_ratsnestClusters;
619 }
620 
621 
623 {
624  if( aNet < 0 )
625  return;
626 
627  if( (int) m_dirtyNets.size() <= aNet )
628  {
629  int lastNet = m_dirtyNets.size() - 1;
630 
631  if( lastNet < 0 )
632  lastNet = 0;
633 
634  m_dirtyNets.resize( aNet + 1 );
635 
636  for( int i = lastNet; i < aNet + 1; i++ )
637  m_dirtyNets[i] = true;
638  }
639 
640  m_dirtyNets[aNet] = true;
641 }
642 
643 
645 {
646  if( aZoneLayer->Net() != aItem->Net() && !aItem->CanChangeNet() )
647  return;
648 
649  if( !aZoneLayer->BBox().Intersects( aItem->BBox() ) )
650  return;
651 
652  int accuracy = 0;
653 
654  if( aItem->Parent()->Type() == PCB_VIA_T
655  || aItem->Parent()->Type() == PCB_TRACE_T
656  || aItem->Parent()->Type() == PCB_ARC_T )
657  {
658  accuracy = ( static_cast<TRACK*>( aItem->Parent() )->GetWidth() + 1 ) / 2;
659  }
660 
661  for( int i = 0; i < aItem->AnchorCount(); ++i )
662  {
663  if( aZoneLayer->ContainsPoint( aItem->GetAnchor( i ), accuracy ) )
664  {
665  aZoneLayer->Connect( aItem );
666  aItem->Connect( aZoneLayer );
667  return;
668  }
669  }
670 }
671 
673 {
674  const ZONE* zoneA = static_cast<const ZONE*>( aZoneLayerA->Parent() );
675  const ZONE* zoneB = static_cast<const ZONE*>( aZoneLayerB->Parent() );
676 
677  if( aZoneLayerA->Layer() != aZoneLayerB->Layer() )
678  return;
679 
680  if( aZoneLayerB->Net() != aZoneLayerA->Net() )
681  return; // we only test zones belonging to the same net
682 
683  const BOX2I& boxA = aZoneLayerA->BBox();
684  const BOX2I& boxB = aZoneLayerB->BBox();
685 
686  int radiusA = 0;
687  int radiusB = 0;
688 
689  if( zoneA->GetFilledPolysUseThickness() )
690  radiusA = ( zoneA->GetMinThickness() + 1 ) / 2;
691 
692  if( zoneB->GetFilledPolysUseThickness() )
693  radiusB = ( zoneB->GetMinThickness() + 1 ) / 2;
694 
695  PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aZoneLayerA->Layer() );
696 
697  const SHAPE_LINE_CHAIN& outline =
698  zoneA->GetFilledPolysList( layer ).COutline( aZoneLayerA->SubpolyIndex() );
699 
700  for( int i = 0; i < outline.PointCount(); i++ )
701  {
702  if( !boxB.Contains( outline.CPoint( i ) ) )
703  continue;
704 
705  if( aZoneLayerB->ContainsPoint( outline.CPoint( i ), radiusA ) )
706  {
707  aZoneLayerA->Connect( aZoneLayerB );
708  aZoneLayerB->Connect( aZoneLayerA );
709  return;
710  }
711  }
712 
713  const SHAPE_LINE_CHAIN& outline2 =
714  zoneB->GetFilledPolysList( layer ).COutline( aZoneLayerB->SubpolyIndex() );
715 
716  for( int i = 0; i < outline2.PointCount(); i++ )
717  {
718  if( !boxA.Contains( outline2.CPoint( i ) ) )
719  continue;
720 
721  if( aZoneLayerA->ContainsPoint( outline2.CPoint( i ), radiusB ) )
722  {
723  aZoneLayerA->Connect( aZoneLayerB );
724  aZoneLayerB->Connect( aZoneLayerA );
725  return;
726  }
727  }
728 }
729 
730 
731 bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
732 {
733  const BOARD_CONNECTED_ITEM* parentA = aCandidate->Parent();
734  const BOARD_CONNECTED_ITEM* parentB = m_item->Parent();
735 
736  if( !aCandidate->Valid() || !m_item->Valid() )
737  return true;
738 
739  if( parentA == parentB )
740  return true;
741 
742  if( !( parentA->GetLayerSet() & parentB->GetLayerSet() ).any() )
743  return true;
744 
745  // If both m_item and aCandidate are marked dirty, they will both be searched
746  // Since we are reciprocal in our connection, we arbitrarily pick one of the connections
747  // to conduct the expensive search
748  if( aCandidate->Dirty() && aCandidate < m_item )
749  return true;
750 
751  // We should handle zone-zone connection separately
752  if ( parentA->Type() == PCB_ZONE_T && parentB->Type() == PCB_ZONE_T )
753  {
754  checkZoneZoneConnection( static_cast<CN_ZONE_LAYER*>( m_item ),
755  static_cast<CN_ZONE_LAYER*>( aCandidate ) );
756  return true;
757  }
758 
759  if( parentA->Type() == PCB_ZONE_T )
760  {
761  checkZoneItemConnection( static_cast<CN_ZONE_LAYER*>( aCandidate ), m_item );
762  return true;
763  }
764 
765  if( parentB->Type() == PCB_ZONE_T )
766  {
767  checkZoneItemConnection( static_cast<CN_ZONE_LAYER*>( m_item ), aCandidate );
768  return true;
769  }
770 
771  int accuracyA = 0;
772  int accuracyB = 0;
773 
774  if( parentA->Type() == PCB_VIA_T
775  || parentA->Type() == PCB_TRACE_T
776  || parentA->Type() == PCB_ARC_T)
777  accuracyA = ( static_cast<const TRACK*>( parentA )->GetWidth() + 1 ) / 2;
778 
779  if( parentB->Type() == PCB_VIA_T
780  || parentB->Type() == PCB_TRACE_T
781  || parentB->Type() == PCB_ARC_T )
782  accuracyB = ( static_cast<const TRACK*>( parentB )->GetWidth() + 1 ) / 2;
783 
784  // Items do not necessarily have reciprocity as we only check for anchors
785  // therefore, we check HitTest both directions A->B & B->A
786  for( int i = 0; i < aCandidate->AnchorCount(); ++i )
787  {
788  if( parentB->HitTest( wxPoint( aCandidate->GetAnchor( i ) ), accuracyA ) )
789  {
790  m_item->Connect( aCandidate );
791  aCandidate->Connect( m_item );
792  return true;
793  }
794  }
795 
796  for( int i = 0; i < m_item->AnchorCount(); ++i )
797  {
798  if( parentA->HitTest( wxPoint( m_item->GetAnchor( i ) ), accuracyB ) )
799  {
800  m_item->Connect( aCandidate );
801  aCandidate->Connect( m_item );
802  return true;
803  }
804  }
805 
806  return true;
807 };
808 
809 
811 {
812  m_ratsnestClusters.clear();
813  m_connClusters.clear();
814  m_itemMap.clear();
815  m_itemList.Clear();
816 
817 }
818 
820 {
821  m_progressReporter = aReporter;
822 }
void RemoveInvalidItems(std::vector< CN_ITEM * > &aGarbage)
const CONNECTED_ITEMS & ConnectedItems() const
COMMIT & Modify(EDA_ITEM *aItem)
Create an undo entry for an item that has been already modified.
Definition: commit.h:103
bool Remove(BOARD_ITEM *aItem)
void SetHasInvalid(bool aInvalid=true)
ZONES & Zones()
Definition: board.h:311
PROPAGATE_MODE
Controls how nets are propagated through clusters.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
void checkZoneItemConnection(CN_ZONE_LAYER *aZoneLayer, CN_ITEM *aItem)
A progress reporter for use in multi-threaded environments.
CN_ITEM * Add(PAD *pad)
const BOX2I & BBox()
bool IsEmpty() const
void ClearDirtyFlags()
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
Definition: zone.cpp:289
void SetVisited(bool aVisited)
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
bool IsDirty() const
void MarkNetAsDirty(int aNet)
class PAD, a pad in a footprint
Definition: typeinfo.h:89
bool Add(BOARD_ITEM *aItem)
const SHAPE_POLY_SET & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition: zone.h:632
bool Dirty() const
BOARD_CONNECTED_ITEM * Parent() const
void FindIsolatedCopperIslands(ZONE *aZone, PCB_LAYER_ID aLayer, std::vector< int > &aIslands)
void add(Container &c, BItem brditem)
int PointCount() const
Function PointCount()
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Return an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:411
A small class to help profiling.
Definition: profile.h:45
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
void SetDirty(bool aDirty=true)
int Net() const
allow parallel connection threads
search types array terminator (End Of Types)
Definition: typeinfo.h:81
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition: typeinfo.h:77
std::vector< bool > m_dirtyNets
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
PADS & Pads()
Definition: footprint.h:164
virtual int AnchorCount() const
void PropagateNets(BOARD_COMMIT *aCommit=nullptr, PROPAGATE_MODE aMode=PROPAGATE_MODE::SKIP_CONFLICTS)
Propagates nets from pads to other items in clusters.
const CLUSTERS SearchClusters(CLUSTER_SEARCH_MODE aMode, const KICAD_T aTypes[], int aSingleNet)
virtual bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const
Test if aPosition is contained within or on the bounding box of an item.
Definition: eda_item.h:275
bool Intersects(const BOX2< Vec > &aRect) const
Function Intersects.
Definition: box2.h:236
const VECTOR2I & CPoint(int aIndex) const
Function Point()
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)
bool IsCancelled() const
int GetMinThickness() const
Definition: zone.h:241
void propagateConnections(BOARD_COMMIT *aCommit=nullptr, PROPAGATE_MODE aMode=PROPAGATE_MODE::SKIP_CONFLICTS)
FOOTPRINTS & Footprints()
Definition: board.h:305
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)
The item we are looking for connections to.
Handle a list of polygons defining a copper zone.
Definition: zone.h:57
class ZONE, a copper pour area
Definition: typeinfo.h:105
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
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
bool CanChangeNet() const
bool operator()(CN_ITEM *aCandidate)
const CLUSTERS & GetClusters()
void Build(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr)
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
SHAPE_LINE_CHAIN.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
class NETINFO_ITEM, a description of a net
Definition: typeinfo.h:107
bool KeepRefreshing(bool aWait=false)
Update the UI dialog.
std::shared_ptr< CN_CLUSTER > CN_CLUSTER_PTR
virtual int Layer() const
Return the item's layer, for single-layered items only.
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:136
void Connect(CN_ITEM *b)
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition: profile.h:102
Definition: pad.h:60
CN_ITEM * m_item
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: board.h:302
virtual bool IsOnCopperLayer() const
Definition: board_item.h:144
std::unordered_map< const BOARD_ITEM *, ITEM_MAP_ENTRY > m_itemMap
A structure used for calculating isolated islands on a given zone across all its layers.
Definition: track.h:83
const BOX2I & BBox()
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:178
bool Valid() const
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:163
bool GetFilledPolysUseThickness() const
Definition: zone.h:686
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
PROGRESS_REPORTER * m_progressReporter