KiCad PCB EDA Suite
connectivity_data.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) 2017 CERN
5  * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Tomasz Wlostowski <[email protected]>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #ifdef PROFILE
27 #include <profile.h>
28 #endif
29 
30 #include <thread>
31 #include <algorithm>
32 #include <future>
33 
37 
38 #include <ratsnest/ratsnest_data.h>
39 #include <trigo.h>
40 
42 {
43  m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
44  m_progressReporter = nullptr;
45  m_fromToCache.reset( new FROM_TO_CACHE );
46 }
47 
48 
49 CONNECTIVITY_DATA::CONNECTIVITY_DATA( const std::vector<BOARD_ITEM*>& aItems, bool aSkipRatsnest )
50  : m_skipRatsnest( aSkipRatsnest )
51 {
52  Build( aItems );
53  m_progressReporter = nullptr;
54  m_fromToCache.reset( new FROM_TO_CACHE );
55 }
56 
57 
59 {
60  Clear();
61 }
62 
63 
65 {
66  m_connAlgo->Add( aItem );
67  return true;
68 }
69 
70 
72 {
73  m_connAlgo->Remove( aItem );
74  return true;
75 }
76 
77 
79 {
80  m_connAlgo->Remove( aItem );
81  m_connAlgo->Add( aItem );
82  return true;
83 }
84 
85 
87 {
88  m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
89  m_connAlgo->Build( aBoard, aReporter );
90 
91  m_netclassMap.clear();
92 
93  for( NETINFO_ITEM* net : aBoard->GetNetInfo() )
94  if( net->GetNetClass()->GetName() != NETCLASS::Default )
95  m_netclassMap[ net->GetNetCode() ] = net->GetNetClass()->GetName();
96 
98 }
99 
100 
101 void CONNECTIVITY_DATA::Build( const std::vector<BOARD_ITEM*>& aItems )
102 {
103  m_connAlgo.reset( new CN_CONNECTIVITY_ALGO );
104  m_connAlgo->Build( aItems );
105 
107 }
108 
109 
110 void CONNECTIVITY_DATA::Move( const VECTOR2I& aDelta )
111 {
112  m_connAlgo->ForEachAnchor( [&aDelta]( CN_ANCHOR& anchor )
113  {
114  anchor.Move( aDelta );
115  } );
116 }
117 
118 
120 {
121  #ifdef PROFILE
122  PROF_COUNTER rnUpdate( "update-ratsnest" );
123  #endif
124  std::vector<RN_NET*> dirty_nets;
125 
126  // Start with net 1 as net 0 is reserved for not-connected
127  // Nets without nodes are also ignored
128  std::copy_if( m_nets.begin() + 1, m_nets.end(), std::back_inserter( dirty_nets ),
129  [] ( RN_NET* aNet ) { return aNet->IsDirty() && aNet->GetNodeCount() > 0; } );
130 
131  // We don't want to spin up a new thread for fewer than 8 nets (overhead costs)
132  size_t parallelThreadCount = std::min<size_t>( std::thread::hardware_concurrency(),
133  ( dirty_nets.size() + 7 ) / 8 );
134 
135  std::atomic<size_t> nextNet( 0 );
136  std::vector<std::future<size_t>> returns( parallelThreadCount );
137 
138  auto update_lambda = [&nextNet, &dirty_nets]() -> size_t
139  {
140  for( size_t i = nextNet++; i < dirty_nets.size(); i = nextNet++ )
141  dirty_nets[i]->Update();
142 
143  return 1;
144  };
145 
146  if( parallelThreadCount == 1 )
147  update_lambda();
148  else
149  {
150  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
151  returns[ii] = std::async( std::launch::async, update_lambda );
152 
153  // Finalize the ratsnest threads
154  for( size_t ii = 0; ii < parallelThreadCount; ++ii )
155  returns[ii].wait();
156  }
157 
158  #ifdef PROFILE
159  rnUpdate.Show();
160  #endif /* PROFILE */
161 }
162 
163 
164 void CONNECTIVITY_DATA::addRatsnestCluster( const std::shared_ptr<CN_CLUSTER>& aCluster )
165 {
166  auto rnNet = m_nets[ aCluster->OriginNet() ];
167 
168  rnNet->AddCluster( aCluster );
169 }
170 
171 
173 {
174  m_connAlgo->PropagateNets( aCommit );
175 
176  int lastNet = m_connAlgo->NetCount();
177 
178  if( lastNet >= (int) m_nets.size() )
179  {
180  unsigned int prevSize = m_nets.size();
181  m_nets.resize( lastNet + 1 );
182 
183  for( unsigned int i = prevSize; i < m_nets.size(); i++ )
184  m_nets[i] = new RN_NET;
185  }
186 
187  auto clusters = m_connAlgo->GetClusters();
188 
189  int dirtyNets = 0;
190 
191  for( int net = 0; net < lastNet; net++ )
192  {
193  if( m_connAlgo->IsNetDirty( net ) )
194  {
195  m_nets[net]->Clear();
196  dirtyNets++;
197  }
198  }
199 
200  for( const auto& c : clusters )
201  {
202  int net = c->OriginNet();
203 
204  // Don't add intentionally-kept zone islands to the ratsnest
205  if( c->IsOrphaned() && c->Size() == 1 )
206  {
207  if( dynamic_cast<CN_ZONE_LAYER*>( *c->begin() ) )
208  continue;
209  }
210 
211  if( m_connAlgo->IsNetDirty( net ) )
212  {
213  addRatsnestCluster( c );
214  }
215  }
216 
217  m_connAlgo->ClearDirtyFlags();
218 
219  if( !m_skipRatsnest )
220  updateRatsnest();
221 }
222 
223 
224 void CONNECTIVITY_DATA::BlockRatsnestItems( const std::vector<BOARD_ITEM*>& aItems )
225 {
226  std::vector<BOARD_CONNECTED_ITEM*> citems;
227 
228  for( auto item : aItems )
229  {
230  if( item->Type() == PCB_FOOTPRINT_T )
231  {
232  for( PAD* pad : static_cast<FOOTPRINT*>(item)->Pads() )
233  citems.push_back( pad );
234  }
235  else
236  {
237  if( auto citem = dynamic_cast<BOARD_CONNECTED_ITEM*>( item ) )
238  citems.push_back( citem );
239  }
240  }
241 
242  for( const auto& item : citems )
243  {
244  if ( m_connAlgo->ItemExists( item ) )
245  {
246  auto& entry = m_connAlgo->ItemEntry( item );
247 
248  for( const auto& cnItem : entry.GetItems() )
249  {
250  for( auto anchor : cnItem->Anchors() )
251  anchor->SetNoLine( true );
252  }
253  }
254  }
255 }
256 
257 
259 {
260  return m_connAlgo->NetCount();
261 }
262 
263 
264 void CONNECTIVITY_DATA::FindIsolatedCopperIslands( ZONE* aZone, std::vector<int>& aIslands )
265 {
266  // TODO(JE) ZONES
267 #if 0
268  m_connAlgo->FindIsolatedCopperIslands( aZone, aIslands );
269 #endif
270 }
271 
272 void CONNECTIVITY_DATA::FindIsolatedCopperIslands( std::vector<CN_ZONE_ISOLATED_ISLAND_LIST>& aZones )
273 {
274  m_connAlgo->FindIsolatedCopperIslands( aZones );
275 }
276 
277 
278 void CONNECTIVITY_DATA::ComputeDynamicRatsnest( const std::vector<BOARD_ITEM*>& aItems,
279  const CONNECTIVITY_DATA* aDynamicData )
280 {
281  if( !aDynamicData )
282  return;
283 
284  m_dynamicRatsnest.clear();
285 
286  // This gets connections between the stationary board and the
287  // moving selection
288  for( unsigned int nc = 1; nc < aDynamicData->m_nets.size(); nc++ )
289  {
290  auto dynNet = aDynamicData->m_nets[nc];
291 
292  if( dynNet->GetNodeCount() != 0 )
293  {
294  auto ourNet = m_nets[nc];
295  CN_ANCHOR_PTR nodeA, nodeB;
296 
297  if( ourNet->NearestBicoloredPair( *dynNet, nodeA, nodeB ) )
298  {
299  RN_DYNAMIC_LINE l;
300  l.a = nodeA->Pos();
301  l.b = nodeB->Pos();
302  l.netCode = nc;
303 
304  m_dynamicRatsnest.push_back( l );
305  }
306  }
307  }
308 
309  // This gets the ratsnest for internal connections in the moving set
310  const auto& edges = GetRatsnestForItems( aItems );
311 
312  for( const auto& edge : edges )
313  {
314  const auto& nodeA = edge.GetSourceNode();
315  const auto& nodeB = edge.GetTargetNode();
316  RN_DYNAMIC_LINE l;
317 
318  // Use the parents' positions
319  l.a = nodeA->Parent()->GetPosition();
320  l.b = nodeB->Parent()->GetPosition();
321  l.netCode = 0;
322  m_dynamicRatsnest.push_back( l );
323  }
324 }
325 
326 
328 {
329  m_connAlgo->ForEachAnchor( []( CN_ANCHOR& anchor )
330  {
331  anchor.SetNoLine( false );
332  } );
334 }
335 
336 
338 {
339  m_dynamicRatsnest.clear();
340 }
341 
342 
344 {
345  m_connAlgo->PropagateNets( aCommit, aMode );
346 }
347 
348 
350  std::vector<KICAD_T> aTypes ) const
351 {
352  CN_CONNECTIVITY_ALGO::ITEM_MAP_ENTRY &entry = m_connAlgo->ItemEntry( aItem );
353 
354  auto matchType = [&]( KICAD_T aItemType )
355  {
356  if( aTypes.empty() )
357  return true;
358 
359  return std::count( aTypes.begin(), aTypes.end(), aItemType ) > 0;
360  };
361 
362  for( CN_ITEM* citem : entry.GetItems() )
363  {
364  for( CN_ITEM* connected : citem->ConnectedItems() )
365  {
366  if( connected->Valid()
367  && connected->Layers().Overlaps( aLayer )
368  && connected->Net() == aItem->GetNetCode()
369  && matchType( connected->Parent()->Type() ) )
370  {
371  return true;
372  }
373  }
374  }
375 
376  return false;
377 }
378 
379 
381 {
382  unsigned int unconnected = 0;
383 
384  for( auto net : m_nets )
385  {
386  if( !net )
387  continue;
388 
389  const auto& edges = net->GetUnconnected();
390 
391  if( edges.empty() )
392  continue;
393 
394  unconnected += edges.size();
395  }
396 
397  return unconnected;
398 }
399 
400 
402 {
403  for( auto net : m_nets )
404  delete net;
405 
406  m_nets.clear();
407 }
408 
409 
410 const std::vector<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetConnectedItems(
411  const BOARD_CONNECTED_ITEM* aItem,
412  const KICAD_T aTypes[],
413  bool aIgnoreNetcodes ) const
414 {
415  std::vector<BOARD_CONNECTED_ITEM*> rv;
416  const auto clusters = m_connAlgo->SearchClusters(
417  aIgnoreNetcodes ?
420  aIgnoreNetcodes ? -1 : aItem->GetNetCode() );
421 
422  for( auto cl : clusters )
423  {
424  if( cl->Contains( aItem ) )
425  {
426  for( const auto item : *cl )
427  {
428  if( item->Valid() )
429  rv.push_back( item->Parent() );
430  }
431  }
432  }
433 
434  return rv;
435 }
436 
437 
438 const std::vector<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetNetItems( int aNetCode,
439  const KICAD_T aTypes[] ) const
440 {
441  std::vector<BOARD_CONNECTED_ITEM*> items;
442  items.reserve( 32 );
443 
444  std::bitset<MAX_STRUCT_TYPE_ID> type_bits;
445 
446  for( unsigned int i = 0; aTypes[i] != EOT; ++i )
447  {
448  wxASSERT( aTypes[i] < MAX_STRUCT_TYPE_ID );
449  type_bits.set( aTypes[i] );
450  }
451 
452  m_connAlgo->ForEachItem( [&]( CN_ITEM& aItem ) {
453  if( aItem.Valid() && ( aItem.Net() == aNetCode ) && type_bits[aItem.Parent()->Type()] )
454  items.push_back( aItem.Parent() );
455  } );
456 
457  std::sort( items.begin(), items.end() );
458  items.erase( std::unique( items.begin(), items.end() ), items.end() );
459  return items;
460 }
461 
462 
463 bool CONNECTIVITY_DATA::CheckConnectivity( std::vector<CN_DISJOINT_NET_ENTRY>& aReport )
464 {
466 
467  for( auto net : m_nets )
468  {
469  if( net )
470  {
471  for( const auto& edge : net->GetEdges() )
472  {
474  ent.net = edge.GetSourceNode()->Parent()->GetNetCode();
475  ent.a = edge.GetSourceNode()->Parent();
476  ent.b = edge.GetTargetNode()->Parent();
477  ent.anchorA = edge.GetSourceNode()->Pos();
478  ent.anchorB = edge.GetTargetNode()->Pos();
479  aReport.push_back( ent );
480  }
481  }
482  }
483 
484  return aReport.empty();
485 }
486 
487 
488 const std::vector<PCB_TRACK*> CONNECTIVITY_DATA::GetConnectedTracks(
489  const BOARD_CONNECTED_ITEM* aItem ) const
490 {
491  auto& entry = m_connAlgo->ItemEntry( aItem );
492 
493  std::set<PCB_TRACK*> tracks;
494  std::vector<PCB_TRACK*> rv;
495 
496  for( CN_ITEM* citem : entry.GetItems() )
497  {
498  for( CN_ITEM* connected : citem->ConnectedItems() )
499  {
500  if( connected->Valid() &&
501  ( connected->Parent()->Type() == PCB_TRACE_T ||
502  connected->Parent()->Type() == PCB_VIA_T ||
503  connected->Parent()->Type() == PCB_ARC_T ) )
504  tracks.insert( static_cast<PCB_TRACK*> ( connected->Parent() ) );
505  }
506  }
507 
508  std::copy( tracks.begin(), tracks.end(), std::back_inserter( rv ) );
509  return rv;
510 }
511 
512 
514  std::set<PAD*>* pads ) const
515 {
516  for( CN_ITEM* citem : m_connAlgo->ItemEntry( aItem ).GetItems() )
517  {
518  for( CN_ITEM* connected : citem->ConnectedItems() )
519  {
520  if( connected->Valid() && connected->Parent()->Type() == PCB_PAD_T )
521  pads->insert( static_cast<PAD*> ( connected->Parent() ) );
522  }
523  }
524 }
525 
526 
527 const std::vector<PAD*> CONNECTIVITY_DATA::GetConnectedPads( const BOARD_CONNECTED_ITEM* aItem )
528 const
529 {
530  std::set<PAD*> pads;
531  std::vector<PAD*> rv;
532 
533  GetConnectedPads( aItem, &pads );
534 
535  std::copy( pads.begin(), pads.end(), std::back_inserter( rv ) );
536  return rv;
537 }
538 
539 
540 unsigned int CONNECTIVITY_DATA::GetNodeCount( int aNet ) const
541 {
542  int sum = 0;
543 
544  if( aNet < 0 ) // Node count for all nets
545  {
546  for( const RN_NET* net : m_nets )
547  sum += net->GetNodeCount();
548  }
549  else if( aNet < (int) m_nets.size() )
550  {
551  sum = m_nets[aNet]->GetNodeCount();
552  }
553 
554  return sum;
555 }
556 
557 
558 unsigned int CONNECTIVITY_DATA::GetPadCount( int aNet ) const
559 {
560  int n = 0;
561 
562  for( CN_ITEM* pad : m_connAlgo->ItemList() )
563  {
564  if( !pad->Valid() || pad->Parent()->Type() != PCB_PAD_T)
565  continue;
566 
567  PAD* dpad = static_cast<PAD*>( pad->Parent() );
568 
569  if( aNet < 0 || aNet == dpad->GetNetCode() )
570  n++;
571  }
572 
573  return n;
574 }
575 
576 
577 void CONNECTIVITY_DATA::GetUnconnectedEdges( std::vector<CN_EDGE>& aEdges) const
578 {
579  for( const RN_NET* rnNet : m_nets )
580  {
581  if( rnNet )
582  {
583  for( const CN_EDGE& edge : rnNet->GetEdges() )
584  aEdges.push_back( edge );
585  }
586  }
587 }
588 
589 
590 static int getMinDist( BOARD_CONNECTED_ITEM* aItem, const wxPoint& aPoint )
591 {
592  switch( aItem->Type() )
593  {
594  case PCB_TRACE_T:
595  case PCB_ARC_T:
596  {
597  PCB_TRACK* track = static_cast<PCB_TRACK*>( aItem );
598 
599  return std::min( GetLineLength( track->GetStart(), aPoint ),
600  GetLineLength( track->GetEnd(), aPoint ) );
601  }
602 
603  default:
604  return GetLineLength( aItem->GetPosition(), aPoint );
605  }
606 }
607 
608 
610 {
611  std::list<CN_ITEM*> items = GetConnectivityAlgo()->ItemEntry( aTrack ).GetItems();
612 
613  // Not in the connectivity system. This is a bug!
614  if( items.empty() )
615  {
616  wxFAIL_MSG( "track not in connectivity system" );
617  return false;
618  }
619 
620  CN_ITEM* citem = items.front();
621 
622  if( !citem->Valid() )
623  return false;
624 
625  if( aTrack->Type() == PCB_TRACE_T || aTrack->Type() == PCB_ARC_T )
626  {
627  // Test if a segment is connected on each end.
628  //
629  // NB: be wary of short segments which can be connected to the *same* other item on
630  // each end. If that's their only connection then they're still dangling.
631 
632  PCB_LAYER_ID layer = aTrack->GetLayer();
633  int accuracy = KiROUND( aTrack->GetWidth() / 2 );
634  int start_count = 0;
635  int end_count = 0;
636 
637  for( CN_ITEM* connected : citem->ConnectedItems() )
638  {
639  BOARD_CONNECTED_ITEM* item = connected->Parent();
640 
641  if( item->GetFlags() & IS_DELETED )
642  continue;
643 
644  std::shared_ptr<SHAPE> shape = item->GetEffectiveShape( layer );
645 
646  bool hitStart = shape->Collide( aTrack->GetStart(), accuracy );
647  bool hitEnd = shape->Collide( aTrack->GetEnd(), accuracy );
648 
649  if( hitStart && hitEnd )
650  {
651  if( getMinDist( item, aTrack->GetStart() ) < getMinDist( item, aTrack->GetEnd() ) )
652  start_count++;
653  else
654  end_count++;
655  }
656  else if( hitStart )
657  {
658  start_count++;
659  }
660  else if( hitEnd )
661  {
662  end_count++;
663  }
664 
665  if( start_count > 0 && end_count > 0 )
666  return false;
667  }
668 
669  if( aPos )
670  *aPos = (start_count == 0 ) ? aTrack->GetStart() : aTrack->GetEnd();
671 
672  return true;
673  }
674  else if( aTrack->Type() == PCB_VIA_T )
675  {
676  // Test if a via is only connected on one layer
677 
678  const std::vector<CN_ITEM*>& connected = citem->ConnectedItems();
679 
680  if( connected.empty() )
681  {
682  if( aPos )
683  *aPos = aTrack->GetPosition();
684 
685  return true;
686  }
687 
688  // Here, we check if the via is connected only to items on a single layer
689  int first_layer = UNDEFINED_LAYER;
690 
691  for( CN_ITEM* item : connected )
692  {
693  if( item->Parent()->GetFlags() & IS_DELETED )
694  continue;
695 
696  if( first_layer == UNDEFINED_LAYER )
697  first_layer = item->Layer();
698  else if( item->Layer() != first_layer )
699  return false;
700  }
701 
702  if( aPos )
703  *aPos = aTrack->GetPosition();
704 
705  return true;
706  }
707  else
708  {
709  wxFAIL_MSG( "CONNECTIVITY_DATA::TestTrackEndpointDangling: unknown track type" );
710  }
711 
712  return false;
713 }
714 
715 
716 const std::vector<BOARD_CONNECTED_ITEM*> CONNECTIVITY_DATA::GetConnectedItemsAtAnchor(
717  const BOARD_CONNECTED_ITEM* aItem,
718  const VECTOR2I& aAnchor,
719  const KICAD_T aTypes[],
720  const int& aMaxError ) const
721 {
722  auto& entry = m_connAlgo->ItemEntry( aItem );
723  std::vector<BOARD_CONNECTED_ITEM*> rv;
724  SEG::ecoord maxErrorSq = (SEG::ecoord) aMaxError * aMaxError;
725 
726  for( auto cnItem : entry.GetItems() )
727  {
728  for( auto connected : cnItem->ConnectedItems() )
729  {
730  for( auto anchor : connected->Anchors() )
731  {
732  if( ( anchor->Pos() - aAnchor ).SquaredEuclideanNorm() <= maxErrorSq )
733  {
734  for( int i = 0; aTypes[i] > 0; i++ )
735  {
736  if( connected->Valid() && connected->Parent()->Type() == aTypes[i] )
737  {
738  rv.push_back( connected->Parent() );
739  break;
740  }
741  }
742 
743  break;
744  }
745  }
746  }
747  }
748 
749  return rv;
750 }
751 
752 
754 {
755  if ( aNet < 0 || aNet >= (int) m_nets.size() )
756  {
757  return nullptr;
758  }
759 
760  return m_nets[ aNet ];
761 }
762 
763 
765 {
766  if ( aItem->Type() == PCB_FOOTPRINT_T)
767  {
768  for( PAD* pad : static_cast<FOOTPRINT*>( aItem )->Pads() )
769  m_connAlgo->MarkNetAsDirty( pad->GetNetCode() );
770  }
771  if (aItem->IsConnected() )
772  {
773  m_connAlgo->MarkNetAsDirty( static_cast<BOARD_CONNECTED_ITEM*>( aItem )->GetNetCode() );
774  }
775 }
776 
777 
779 {
780  m_progressReporter = aReporter;
781  m_connAlgo->SetProgressReporter( m_progressReporter );
782 }
783 
784 
785 const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForItems( std::vector<BOARD_ITEM*> aItems )
786 {
787  std::set<int> nets;
788  std::vector<CN_EDGE> edges;
789  std::set<BOARD_CONNECTED_ITEM*> item_set;
790 
791  for( BOARD_ITEM* item : aItems )
792  {
793  if( item->Type() == PCB_FOOTPRINT_T )
794  {
795  FOOTPRINT* footprint = static_cast<FOOTPRINT*>( item );
796 
797  for( PAD* pad : footprint->Pads() )
798  {
799  nets.insert( pad->GetNetCode() );
800  item_set.insert( pad );
801  }
802  }
803  else if( auto conn_item = dyn_cast<BOARD_CONNECTED_ITEM*>( item ) )
804  {
805  item_set.insert( conn_item );
806  nets.insert( conn_item->GetNetCode() );
807  }
808  }
809 
810  for( const auto& netcode : nets )
811  {
812  RN_NET* net = GetRatsnestForNet( netcode );
813 
814  for( const CN_EDGE& edge : net->GetEdges() )
815  {
816  std::shared_ptr<CN_ANCHOR> srcNode = edge.GetSourceNode();
817  std::shared_ptr<CN_ANCHOR> dstNode = edge.GetTargetNode();
818 
819  BOARD_CONNECTED_ITEM* srcParent = srcNode->Parent();
820  BOARD_CONNECTED_ITEM* dstParent = dstNode->Parent();
821 
822  bool srcFound = ( item_set.find( srcParent ) != item_set.end() );
823  bool dstFound = ( item_set.find( dstParent ) != item_set.end() );
824 
825  if ( srcFound && dstFound )
826  edges.push_back( edge );
827  }
828  }
829 
830  return edges;
831 }
832 
833 
834 const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForPad( const PAD* aPad )
835 {
836  std::vector<CN_EDGE> edges;
837  RN_NET* net = GetRatsnestForNet( aPad->GetNetCode() );
838 
839  for( const CN_EDGE& edge : net->GetEdges() )
840  {
841  if( edge.GetSourceNode()->Parent() == aPad || edge.GetTargetNode()->Parent() == aPad )
842  edges.push_back( edge );
843  }
844 
845  return edges;
846 }
847 
848 
849 const std::vector<CN_EDGE> CONNECTIVITY_DATA::GetRatsnestForComponent( FOOTPRINT* aComponent, bool aSkipInternalConnections )
850 {
851  std::set<int> nets;
852  std::set<const PAD*> pads;
853  std::vector<CN_EDGE> edges;
854 
855  for( auto pad : aComponent->Pads() )
856  {
857  nets.insert( pad->GetNetCode() );
858  pads.insert( pad );
859  }
860 
861  for( const auto& netcode : nets )
862  {
863  const auto& net = GetRatsnestForNet( netcode );
864 
865  for( const auto& edge : net->GetEdges() )
866  {
867  auto srcNode = edge.GetSourceNode();
868  auto dstNode = edge.GetTargetNode();
869 
870  const PAD* srcParent = static_cast<const PAD*>( srcNode->Parent() );
871  const PAD* dstParent = static_cast<const PAD*>( dstNode->Parent() );
872 
873  bool srcFound = ( pads.find(srcParent) != pads.end() );
874  bool dstFound = ( pads.find(dstParent) != pads.end() );
875 
876  if ( srcFound && dstFound && !aSkipInternalConnections )
877  {
878  edges.push_back( edge );
879  }
880  else if ( srcFound || dstFound )
881  {
882  edges.push_back( edge );
883  }
884  }
885  }
886 
887  return edges;
888 }
889 
890 
const CONNECTED_ITEMS & ConnectedItems() const
void Clear()
Function Clear() Erases the connectivity database.
const std::vector< CN_EDGE > GetRatsnestForComponent(FOOTPRINT *aComponent, bool aSkipInternalConnections=false)
bool IsConnectedOnLayer(const BOARD_CONNECTED_ITEM *aItem, int aLayer, std::vector< KICAD_T > aTypes={}) const
unsigned int GetNodeCount(int aNet=-1) const
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Return the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:222
PROPAGATE_MODE
Controls how nets are propagated through clusters.
const std::vector< PCB_TRACK * > GetConnectedTracks(const BOARD_CONNECTED_ITEM *aItem) const
wxPoint GetPosition() const override
Definition: pcb_track.h:98
const wxPoint & GetEnd() const
Definition: pcb_track.h:105
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:49
A progress reporter interface for use in multi-threaded environments.
std::shared_ptr< CN_CONNECTIVITY_ALGO > m_connAlgo
Class that computes missing connections on a PCB.
PROGRESS_REPORTER * m_progressReporter
const std::list< CN_ITEM * > GetItems() const
VECTOR2I::extended_type ecoord
Definition: seg.h:43
std::shared_ptr< CN_CONNECTIVITY_ALGO > GetConnectivityAlgo() const
bool Update(BOARD_ITEM *aItem)
Function Update() Updates the connectivity data for an item.
const std::vector< BOARD_CONNECTED_ITEM * > GetNetItems(int aNetCode, const KICAD_T aTypes[]) const
Function GetNetItems() Returns the list of items that belong to a certain net.
void RecalculateRatsnest(BOARD_COMMIT *aCommit=nullptr)
Function RecalculateRatsnest() Updates the ratsnest for the board.
std::shared_ptr< FROM_TO_CACHE > m_fromToCache
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
void PropagateNets(BOARD_COMMIT *aCommit=nullptr, PROPAGATE_MODE aMode=PROPAGATE_MODE::SKIP_CONFLICTS)
Propagates the net codes from the source pads to the tracks/vias.
const NETINFO_LIST & GetNetInfo() const
Definition: board.h:679
class PAD, a pad in a footprint
Definition: typeinfo.h:89
int GetWidth() const
Definition: pcb_track.h:102
BOARD_CONNECTED_ITEM * Parent() const
virtual wxPoint GetPosition() const
Definition: eda_item.h:252
A small class to help profiling.
Definition: profile.h:45
BOARD_CONNECTED_ITEM * b
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
std::vector< RN_DYNAMIC_LINE > m_dynamicRatsnest
int Net() const
allow parallel connection threads
VECTOR2I anchorB
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
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
PADS & Pads()
Definition: footprint.h:168
unsigned int GetPadCount(int aNet=-1) const
void Build(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr)
Function Build() Builds the connectivity database for the board aBoard.
#define IS_DELETED
VECTOR2I anchorA
const std::vector< BOARD_CONNECTED_ITEM * > GetConnectedItemsAtAnchor(const BOARD_CONNECTED_ITEM *aItem, const VECTOR2I &aAnchor, const KICAD_T aTypes[], const int &aMaxError=0) const
Function GetConnectedItemsAtAnchor() Returns a list of items connected to a source item aItem at posi...
static const char Default[]
the name of the default NETCLASS
Definition: netclass.h:49
const std::vector< BOARD_CONNECTED_ITEM * > GetConnectedItems(const BOARD_CONNECTED_ITEM *aItem, const KICAD_T aTypes[], bool aIgnoreNetcodes=false) const
Function GetConnectedItems() Returns a list of items connected to a source item aItem.
std::map< int, wxString > m_netclassMap
Map of netcode -> netclass the net is a member of; used for ratsnest painting.
unsigned int GetUnconnectedCount() const
Function GetUnconnectedCount() Returns the number of remaining edges in the ratsnest.
Handle a list of polygons defining a copper zone.
Definition: zone.h:56
void ClearDynamicRatsnest()
Function ClearDynamicRatsnest() Erases the temporary dynamic ratsnest (i.e.
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
bool Remove(BOARD_ITEM *aItem)
Function Remove() Removes an item from the connectivity data.
void MarkItemNetAsDirty(BOARD_ITEM *aItem)
const std::vector< CN_EDGE > & GetEdges() const
static int getMinDist(BOARD_CONNECTED_ITEM *aItem, const wxPoint &aPoint)
std::vector< RN_NET * > m_nets
EDA_ITEM_FLAGS GetFlags() const
Definition: eda_item.h:155
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
void GetUnconnectedEdges(std::vector< CN_EDGE > &aEdges) const
bool Add(BOARD_ITEM *aItem)
Function Add() Adds an item to the connectivity data.
void BlockRatsnestItems(const std::vector< BOARD_ITEM * > &aItems)
RN_NET * GetRatsnestForNet(int aNet)
Function GetRatsnestForNet() Returns the ratsnest, expressed as a set of graph edges for a given net.
BOARD_CONNECTED_ITEM * a
Handle the data for a net.
Definition: netinfo.h:66
const std::vector< CN_EDGE > GetRatsnestForPad(const PAD *aPad)
bool CheckConnectivity(std::vector< CN_DISJOINT_NET_ENTRY > &aReport)
void ComputeDynamicRatsnest(const std::vector< BOARD_ITEM * > &aItems, const CONNECTIVITY_DATA *aDynamicData)
Function ComputeDynamicRatsnest() Calculates the temporary dynamic ratsnest (i.e.
void FindIsolatedCopperIslands(ZONE *aZone, std::vector< int > &aIslands)
Function FindIsolatedCopperIslands() Searches for copper islands in zone aZone that are not connected...
Information pertinent to a Pcbnew printed circuit board.
Definition: board.h:190
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:65
std::shared_ptr< CN_ANCHOR > CN_ANCHOR_PTR
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:73
int net
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
Definition: board_item.cpp:167
int GetNetCount() const
Function GetNetCount() Returns the total number of nets in the connectivity database.
bool TestTrackEndpointDangling(PCB_TRACK *aTrack, wxPoint *aPos=nullptr)
virtual bool IsConnected() const
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
Definition: board_item.h:103
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
Describe ratsnest for a single net.
Definition: ratsnest_data.h:61
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
Definition: profile.h:102
const std::vector< PAD * > GetConnectedPads(const BOARD_CONNECTED_ITEM *aItem) const
Definition: pad.h:57
void HideDynamicRatsnest()
Hides the temporary dynamic ratsnest lines.
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition: board_item.h:140
void addRatsnestCluster(const std::shared_ptr< CN_CLUSTER > &aCluster)
void Move(const VECTOR2I &aDelta)
Moves the connectivity list anchors.
const wxPoint & GetStart() const
Definition: pcb_track.h:108
const std::vector< CN_EDGE > GetRatsnestForItems(const std::vector< BOARD_ITEM * > aItems)
bool Valid() const
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113