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  for( const auto& cluster : m_connClusters )
483  {
484  if( cluster->IsConflicting() )
485  {
486  wxLogTrace( "CN", "Conflicting nets in cluster %p\n", cluster.get() );
487  }
488  else if( cluster->IsOrphaned() )
489  {
490  wxLogTrace( "CN", "Skipping orphaned cluster %p [net: %s]\n", cluster.get(),
491  (const char*) cluster->OriginNetName().c_str() );
492  }
493  else if( cluster->HasValidNet() )
494  {
495  // normal cluster: just propagate from the pads
496  int n_changed = 0;
497 
498  for( auto item : *cluster )
499  {
500  if( item->CanChangeNet() )
501  {
502  if( item->Valid() && item->Parent()->GetNetCode() != cluster->OriginNet() )
503  {
504  MarkNetAsDirty( item->Parent()->GetNetCode() );
505  MarkNetAsDirty( cluster->OriginNet() );
506 
507  if( aCommit )
508  aCommit->Modify( item->Parent() );
509 
510  item->Parent()->SetNetCode( cluster->OriginNet() );
511  n_changed++;
512  }
513  }
514  }
515 
516  if( n_changed )
517  {
518  wxLogTrace( "CN", "Cluster %p : net : %d %s\n", cluster.get(),
519  cluster->OriginNet(), (const char*) cluster->OriginNetName().c_str() );
520  }
521  else
522  wxLogTrace( "CN", "Cluster %p : nothing to propagate\n", cluster.get() );
523  }
524  else
525  {
526  wxLogTrace( "CN", "Cluster %p : connected to unused net\n", cluster.get() );
527  }
528  }
529 }
530 
531 
533 {
535  propagateConnections( aCommit );
536 }
537 
538 
540  std::vector<int>& aIslands )
541 {
542  if( aZone->GetFilledPolysList( aLayer ).IsEmpty() )
543  return;
544 
545  aIslands.clear();
546 
547  Remove( aZone );
548  Add( aZone );
549 
551 
552  for( const auto& cluster : m_connClusters )
553  {
554  if( cluster->Contains( aZone ) && cluster->IsOrphaned() )
555  {
556  for( auto z : *cluster )
557  {
558  if( z->Parent() == aZone && z->Layer() == aLayer )
559  {
560  aIslands.push_back( static_cast<CN_ZONE_LAYER*>(z)->SubpolyIndex() );
561  }
562  }
563  }
564  }
565 
566  wxLogTrace( "CN", "Found %u isolated islands\n", (unsigned)aIslands.size() );
567 }
568 
569 void CN_CONNECTIVITY_ALGO::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
570 {
571  for( auto& z : aZones )
572  {
573  Remove( z.m_zone );
574  Add( z.m_zone );
575  }
576 
578 
579  for( CN_ZONE_ISOLATED_ISLAND_LIST& zone : aZones )
580  {
581  for( PCB_LAYER_ID layer : zone.m_zone->GetLayerSet().Seq() )
582  {
583  if( zone.m_zone->GetFilledPolysList( layer ).IsEmpty() )
584  continue;
585 
586  for( const CN_CLUSTER_PTR& cluster : m_connClusters )
587  {
588  if( cluster->Contains( zone.m_zone ) && cluster->IsOrphaned() )
589  {
590  for( CN_ITEM* z : *cluster )
591  {
592  if( z->Parent() == zone.m_zone && z->Layer() == layer )
593  {
594  zone.m_islands[layer].push_back(
595  static_cast<CN_ZONE_LAYER*>( z )->SubpolyIndex() );
596  }
597  }
598  }
599  }
600  }
601  }
602 }
603 
604 
606 {
608  return m_ratsnestClusters;
609 }
610 
611 
613 {
614  if( aNet < 0 )
615  return;
616 
617  if( (int) m_dirtyNets.size() <= aNet )
618  {
619  int lastNet = m_dirtyNets.size() - 1;
620 
621  if( lastNet < 0 )
622  lastNet = 0;
623 
624  m_dirtyNets.resize( aNet + 1 );
625 
626  for( int i = lastNet; i < aNet + 1; i++ )
627  m_dirtyNets[i] = true;
628  }
629 
630  m_dirtyNets[aNet] = true;
631 }
632 
633 
635 {
636  if( aZoneLayer->Net() != aItem->Net() && !aItem->CanChangeNet() )
637  return;
638 
639  if( !aZoneLayer->BBox().Intersects( aItem->BBox() ) )
640  return;
641 
642  int accuracy = 0;
643 
644  if( aItem->Parent()->Type() == PCB_VIA_T
645  || aItem->Parent()->Type() == PCB_TRACE_T
646  || aItem->Parent()->Type() == PCB_ARC_T )
647  {
648  accuracy = ( static_cast<TRACK*>( aItem->Parent() )->GetWidth() + 1 ) / 2;
649  }
650 
651  for( int i = 0; i < aItem->AnchorCount(); ++i )
652  {
653  if( aZoneLayer->ContainsPoint( aItem->GetAnchor( i ), accuracy ) )
654  {
655  aZoneLayer->Connect( aItem );
656  aItem->Connect( aZoneLayer );
657  return;
658  }
659  }
660 }
661 
663 {
664  const ZONE* zoneA = static_cast<const ZONE*>( aZoneLayerA->Parent() );
665  const ZONE* zoneB = static_cast<const ZONE*>( aZoneLayerB->Parent() );
666 
667  if( aZoneLayerA->Layer() != aZoneLayerB->Layer() )
668  return;
669 
670  if( aZoneLayerB->Net() != aZoneLayerA->Net() )
671  return; // we only test zones belonging to the same net
672 
673  const BOX2I& boxA = aZoneLayerA->BBox();
674  const BOX2I& boxB = aZoneLayerB->BBox();
675 
676  int radiusA = 0;
677  int radiusB = 0;
678 
679  if( zoneA->GetFilledPolysUseThickness() )
680  radiusA = ( zoneA->GetMinThickness() + 1 ) / 2;
681 
682  if( zoneB->GetFilledPolysUseThickness() )
683  radiusB = ( zoneB->GetMinThickness() + 1 ) / 2;
684 
685  PCB_LAYER_ID layer = static_cast<PCB_LAYER_ID>( aZoneLayerA->Layer() );
686 
687  const SHAPE_LINE_CHAIN& outline =
688  zoneA->GetFilledPolysList( layer ).COutline( aZoneLayerA->SubpolyIndex() );
689 
690  for( int i = 0; i < outline.PointCount(); i++ )
691  {
692  if( !boxB.Contains( outline.CPoint( i ) ) )
693  continue;
694 
695  if( aZoneLayerB->ContainsPoint( outline.CPoint( i ), radiusA ) )
696  {
697  aZoneLayerA->Connect( aZoneLayerB );
698  aZoneLayerB->Connect( aZoneLayerA );
699  return;
700  }
701  }
702 
703  const SHAPE_LINE_CHAIN& outline2 =
704  zoneB->GetFilledPolysList( layer ).COutline( aZoneLayerB->SubpolyIndex() );
705 
706  for( int i = 0; i < outline2.PointCount(); i++ )
707  {
708  if( !boxA.Contains( outline2.CPoint( i ) ) )
709  continue;
710 
711  if( aZoneLayerA->ContainsPoint( outline2.CPoint( i ), radiusB ) )
712  {
713  aZoneLayerA->Connect( aZoneLayerB );
714  aZoneLayerB->Connect( aZoneLayerA );
715  return;
716  }
717  }
718 }
719 
720 
721 bool CN_VISITOR::operator()( CN_ITEM* aCandidate )
722 {
723  const BOARD_CONNECTED_ITEM* parentA = aCandidate->Parent();
724  const BOARD_CONNECTED_ITEM* parentB = m_item->Parent();
725 
726  if( !aCandidate->Valid() || !m_item->Valid() )
727  return true;
728 
729  if( parentA == parentB )
730  return true;
731 
732  if( !( parentA->GetLayerSet() & parentB->GetLayerSet() ).any() )
733  return true;
734 
735  // If both m_item and aCandidate are marked dirty, they will both be searched
736  // Since we are reciprocal in our connection, we arbitrarily pick one of the connections
737  // to conduct the expensive search
738  if( aCandidate->Dirty() && aCandidate < m_item )
739  return true;
740 
741  // We should handle zone-zone connection separately
742  if ( parentA->Type() == PCB_ZONE_T && parentB->Type() == PCB_ZONE_T )
743  {
744  checkZoneZoneConnection( static_cast<CN_ZONE_LAYER*>( m_item ),
745  static_cast<CN_ZONE_LAYER*>( aCandidate ) );
746  return true;
747  }
748 
749  if( parentA->Type() == PCB_ZONE_T )
750  {
751  checkZoneItemConnection( static_cast<CN_ZONE_LAYER*>( aCandidate ), m_item );
752  return true;
753  }
754 
755  if( parentB->Type() == PCB_ZONE_T )
756  {
757  checkZoneItemConnection( static_cast<CN_ZONE_LAYER*>( m_item ), aCandidate );
758  return true;
759  }
760 
761  int accuracyA = 0;
762  int accuracyB = 0;
763 
764  if( parentA->Type() == PCB_VIA_T
765  || parentA->Type() == PCB_TRACE_T
766  || parentA->Type() == PCB_ARC_T)
767  accuracyA = ( static_cast<const TRACK*>( parentA )->GetWidth() + 1 ) / 2;
768 
769  if( parentB->Type() == PCB_VIA_T
770  || parentB->Type() == PCB_TRACE_T
771  || parentB->Type() == PCB_ARC_T )
772  accuracyB = ( static_cast<const TRACK*>( parentB )->GetWidth() + 1 ) / 2;
773 
774  // Items do not necessarily have reciprocity as we only check for anchors
775  // therefore, we check HitTest both directions A->B & B->A
776  for( int i = 0; i < aCandidate->AnchorCount(); ++i )
777  {
778  if( parentB->HitTest( wxPoint( aCandidate->GetAnchor( i ) ), accuracyA ) )
779  {
780  m_item->Connect( aCandidate );
781  aCandidate->Connect( m_item );
782  return true;
783  }
784  }
785 
786  for( int i = 0; i < m_item->AnchorCount(); ++i )
787  {
788  if( parentA->HitTest( wxPoint( m_item->GetAnchor( i ) ), accuracyB ) )
789  {
790  m_item->Connect( aCandidate );
791  aCandidate->Connect( m_item );
792  return true;
793  }
794  }
795 
796  return true;
797 };
798 
799 
801 {
802  m_ratsnestClusters.clear();
803  m_connClusters.clear();
804  m_itemMap.clear();
805  m_itemList.Clear();
806 
807 }
808 
810 {
811  m_progressReporter = aReporter;
812 }
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
void propagateConnections(BOARD_COMMIT *aCommit=nullptr)
bool Remove(BOARD_ITEM *aItem)
void SetHasInvalid(bool aInvalid=true)
ZONES & Zones()
Definition: board.h:309
void PropagateNets(BOARD_COMMIT *aCommit=nullptr)
Propagates nets from pads to other items in 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:288
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
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: zone.h:655
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
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:274
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:247
FOOTPRINTS & Footprints()
Definition: board.h:303
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.
ZONE handles 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:300
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:162
bool GetFilledPolysUseThickness() const
Definition: zone.h:712
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
PROGRESS_REPORTER * m_progressReporter