KiCad PCB EDA Suite
Loading...
Searching...
No Matches
topo_match.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#include <cstdio>
25#include <cstdlib>
26#include <cmath>
27#include <string>
28#include <vector>
29#include <algorithm>
30#include <cassert>
31#include <map>
32#include <set>
33#include <cctype>
34
35#include <pad.h>
36#include <footprint.h>
37#include <refdes_utils.h>
38#include <board.h>
39#include <wx/string.h>
40#include <wx/log.h>
41
42#include "topo_match.h"
43
44
45static const wxString traceTopoMatch = wxT( "TOPO_MATCH" );
46
47namespace TMATCH
48{
49
50bool PIN::IsIsomorphic( const PIN& b, TOPOLOGY_MISMATCH_REASON& aReason ) const
51{
52 if( m_conns.size() != b.m_conns.size() )
53 {
54 wxLogTrace( traceTopoMatch,
55 wxT( "[conns mismatch n1 %d n2 %d c-ref %d c-other %d thispin %s-%s "
56 "otherpin %s-%s" ),
58 b.m_netcode,
59 (int) m_conns.size(),
60 (int) b.m_conns.size(),
61 m_parent->m_reference,
62 m_ref,
64 b.m_ref );
65
66 aReason.m_reference = m_parent->GetParent()->GetReferenceAsString();
68 aReason.m_reason = wxString::Format(
69 _( "Pad %s of %s connects to %lu pads, but candidate pad %s of %s connects to %lu." ), m_ref,
70 aReason.m_reference, static_cast<unsigned long>( m_conns.size() ), b.m_ref, aReason.m_candidate,
71 static_cast<unsigned long>( b.m_conns.size() ) );
72
73 for( auto c : m_conns )
74 {
75 wxLogTrace( traceTopoMatch, wxT( "%s-%s " ), c->m_parent->m_reference, c->m_ref );
76 }
77
78 wxLogTrace( traceTopoMatch, wxT( "||" ) );
79
80 for( auto c : b.m_conns )
81 {
82 wxLogTrace( traceTopoMatch, wxT( "%s-%s " ), c->m_parent->m_reference, c->m_ref );
83 }
84
85
86 wxLogTrace( traceTopoMatch, wxT( "] " ) );
87 return false;
88 }
89
90 if( m_conns.empty() )
91 {
92 wxLogTrace( traceTopoMatch, wxT( "[conns empty]" ) );
93 return true;
94 }
95
96 std::vector<bool> matches( m_conns.size() );
97
98 for( int i = 0; i < m_conns.size(); i++ )
99 matches[i] = false;
100
101 int nref = 0;
102
103 for( auto& cref : m_conns )
104 {
105 for( int i = 0; i < m_conns.size(); i++ )
106 {
107 if( b.m_conns[i]->IsTopologicallySimilar( *cref ) )
108 {
109 matches[nref] = true;
110 break;
111 }
112 }
113
114 nref++;
115 }
116
117 for( int i = 0; i < m_conns.size(); i++ )
118 {
119 if( !matches[i] )
120 {
121 aReason.m_reference = m_parent->GetParent()->GetReferenceAsString();
123 aReason.m_reason = wxString::Format(
124 _( "Pad %s of %s cannot match candidate pad %s of %s due to differing connectivity." ), m_ref,
125 aReason.m_reference, b.m_ref, aReason.m_candidate );
126
127 return false;
128 }
129 }
130
131 return true;
132}
133
134
135// fixme: terrible performance, but computers are fast these days, ain't they? :D
136bool checkIfPadNetsMatch( const BACKTRACK_STAGE& aMatches, CONNECTION_GRAPH* aRefGraph, COMPONENT* aRef,
137 COMPONENT* aTgt, TOPOLOGY_MISMATCH_REASON& aReason )
138{
139 std::map<PIN*, PIN*> pairs;
140 std::vector<PIN*> pref, ptgt;
141
142 // GetMatchingComponentPairs() returns target->reference map
143 for( auto& m : aMatches.GetMatchingComponentPairs() )
144 {
145 for( PIN* p : m.second->Pins() )
146 {
147 pref.push_back( p );
148 }
149
150 for( PIN* p : m.first->Pins() )
151 {
152 ptgt.push_back( p );
153 }
154 }
155
156 for( PIN* p : aRef->Pins() )
157 {
158 pref.push_back( p );
159 }
160
161 for( PIN* p : aTgt->Pins() )
162 {
163 ptgt.push_back( p );
164 }
165
166 if( pref.size() != ptgt.size() )
167 {
168 aReason.m_reference = aRef->GetParent()->GetReferenceAsString();
169 aReason.m_candidate = aTgt->GetParent()->GetReferenceAsString();
170 aReason.m_reason =
171 wxString::Format( _( "Component %s expects %lu matching pads but candidate %s provides %lu." ),
172 aReason.m_reference, static_cast<unsigned long>( pref.size() ),
173 aReason.m_candidate, static_cast<unsigned long>( ptgt.size() ) );
174 return false;
175 }
176
177 for( unsigned int i = 0; i < pref.size(); i++ )
178 {
179 pairs[pref[i]] = ptgt[i];
180 }
181
182 for( PIN* refPin : aRef->Pins() )
183 {
184 wxLogTrace( traceTopoMatch, wxT( "pad %s-%s: " ),
185 aRef->GetParent()->GetReferenceAsString(), refPin->GetReference() );
186
187 std::optional<int> prevNet;
188
189 for( COMPONENT* refCmp : aRefGraph->Components() )
190 {
191 for( PIN* ppin : refCmp->Pins() )
192 {
193 if ( ppin->GetNetCode() != refPin->GetNetCode() )
194 continue;
195
196 wxLogTrace( traceTopoMatch, wxT( "{ref %s-%s:%d} " ),
197 ppin->GetParent()->GetParent()->GetReferenceAsString(),
198 ppin->GetReference(), ppin->GetNetCode() );
199
200 auto tpin = pairs.find( ppin );
201
202 if( tpin != pairs.end() )
203 {
204 int nc = tpin->second->GetNetCode();
205
206 if( prevNet && ( *prevNet != nc ) )
207 {
208 wxLogTrace( traceTopoMatch, wxT( "nets inconsistent\n" ) );
209
210 aReason.m_reference = aRef->GetParent()->GetReferenceAsString();
211 aReason.m_candidate = aTgt->GetParent()->GetReferenceAsString();
212
213 wxString refNetName;
214 wxString tgtNetName;
215
216 if( const BOARD* refBoard = aRef->GetParent()->GetBoard() )
217 {
218 if( const NETINFO_ITEM* net = refBoard->FindNet( refPin->GetNetCode() ) )
219 refNetName = net->GetNetname();
220 }
221
222 if( const BOARD* tgtBoard = aTgt->GetParent()->GetBoard() )
223 {
224 if( const NETINFO_ITEM* net = tgtBoard->FindNet( nc ) )
225 tgtNetName = net->GetNetname();
226 }
227
228 if( refNetName.IsEmpty() )
229 refNetName = wxString::Format( _( "net %d" ), refPin->GetNetCode() );
230
231 if( tgtNetName.IsEmpty() )
232 tgtNetName = wxString::Format( _( "net %d" ), nc );
233
234 aReason.m_reason = wxString::Format(
235 _( "Pad %s of %s is on net %s but its match in candidate %s is on net %s." ),
236 refPin->GetReference(), aReason.m_reference, refNetName, aReason.m_candidate,
237 tgtNetName );
238
239 return false;
240 }
241
242 prevNet = nc;
243 }
244 }
245 }
246 }
247
248 return true;
249}
250
251
252std::vector<COMPONENT*>
254 const BACKTRACK_STAGE& partialMatches,
255 std::vector<TOPOLOGY_MISMATCH_REASON>& aMismatchReasons )
256{
257 aMismatchReasons.clear();
258 std::vector<COMPONENT*> matches;
259 for( auto cmpTarget : m_components )
260 {
261 // already matched to sth? move on.
262 if( partialMatches.m_locked.find( cmpTarget ) != partialMatches.m_locked.end() )
263 {
264 continue;
265 }
266
267 wxLogTrace( traceTopoMatch, wxT( "Check '%s'/'%s' " ), aRef->m_reference,
268 cmpTarget->m_reference );
269
270 // first, a basic heuristic (reference prefix, pin count & footprint) followed by a pin
271 // connection topology check
272 TOPOLOGY_MISMATCH_REASON localReason;
273 localReason.m_reference = aRef->GetParent()->GetReferenceAsString();
274 localReason.m_candidate = cmpTarget->GetParent()->GetReferenceAsString();
275
276 if( aRef->MatchesWith( cmpTarget, localReason ) )
277 {
278 // then a net integrity check (expensive because of poor optimization)
279 if( checkIfPadNetsMatch( partialMatches, aRefGraph, aRef, cmpTarget, localReason ) )
280 {
281 wxLogTrace( traceTopoMatch, wxT("match!\n") );
282 matches.push_back( cmpTarget );
283 }
284 else
285 {
286 wxLogTrace( traceTopoMatch, wxT("Reject [net topo mismatch]\n") );
287 aMismatchReasons.push_back( localReason );
288 }
289 }
290 else
291 {
292 wxLogTrace( traceTopoMatch, wxT("reject\n") );
293 aMismatchReasons.push_back( localReason );
294 }
295 }
296
297 auto padSimilarity = []( COMPONENT* a, COMPONENT* b ) -> double
298 {
299 int n = 0;
300
301 for( size_t i = 0; i < a->m_pins.size(); i++ )
302 {
303 PIN* pa = a->m_pins[i];
304 PIN* pb = b->m_pins[i];
305
306 if( pa->GetNetCode() == pb->GetNetCode() )
307 n++;
308 }
309
310 return (double) n / (double) a->m_pins.size();
311 };
312
313 std::sort( matches.begin(), matches.end(),
314 [&]( COMPONENT* a, COMPONENT* b ) -> bool
315 {
316 double simA = padSimilarity( aRef, a );
317 double simB = padSimilarity( aRef, b );
318
319 if( simA != simB )
320 return simA > simB;
321
322 return a->GetParent()->GetReferenceAsString()
323 < b->GetParent()->GetReferenceAsString();
324 } );
325
326 if( matches.empty() )
327 {
329 reason.m_reference = aRef->GetParent()->GetReferenceAsString();
330 reason.m_reason = _( "No compatible component found in the target area." );
331
332 if( aMismatchReasons.empty() )
333 aMismatchReasons.push_back( reason );
334 }
335
336 return matches;
337}
338
339
341{
342 std::sort( m_pins.begin(), m_pins.end(),
343 []( PIN* a, PIN* b )
344 {
345 return a->GetReference() < b->GetReference();
346 } );
347}
348
349
351{
352 std::sort( m_components.begin(), m_components.end(),
353 []( COMPONENT* a, COMPONENT* b )
354 {
355 if( a->GetPinCount() != b->GetPinCount() )
356 return a->GetPinCount() > b->GetPinCount();
357
358 return a->GetParent()->GetReferenceAsString() < b->GetParent()->GetReferenceAsString();
359 } );
360}
361
362
364{
365 std::map<int, std::vector<PIN*>> nets;
366
368
369 for( auto c : m_components )
370 {
371 c->sortPinsByName();
372
373 for( auto p : c->Pins() )
374 {
375 if( p->GetNetCode() > 0 )
376 nets[p->GetNetCode()].push_back( p );
377 }
378 }
379
380 for( auto iter : nets )
381 {
382 wxLogTrace( traceTopoMatch, wxT( "net %d: %d connections\n" ), iter.first,
383 (int) iter.second.size() );
384
385 for( auto p : iter.second )
386 {
387 for( auto p2 : iter.second )
388 {
389 if( p != p2 && !alg::contains( p->m_conns, p2 ) )
390 {
391 p->m_conns.push_back( p2 );
392 }
393 }
394 }
395 }
396
397/* for( auto c : m_components )
398 for( auto p : c->Pins() )
399 {
400 printf("pin %s: \n", p->m_ref.c_str().AsChar() );
401
402 for( auto c : p->m_conns )
403 printf( "%s ", c->m_ref.c_str().AsChar() );
404 printf("\n");
405 }
406 */
407}
408
409
411 std::vector<TOPOLOGY_MISMATCH_REASON>& aMismatchReasons )
412{
413 std::vector<BACKTRACK_STAGE> stack;
415
416 aMismatchReasons.clear();
417
418 std::vector<TOPOLOGY_MISMATCH_REASON> localReasons;
419
420 if( m_components.empty()|| aTarget->m_components.empty() )
421 {
423 reason.m_reason = _( "One or both of the areas has no components assigned." );
424 aMismatchReasons.push_back( reason );
425 return false;
426 }
427
428 if( m_components.size() != aTarget->m_components.size() )
429 {
431 reason.m_reason = _( "Component count mismatch" );
432 aMismatchReasons.push_back( reason );
433 return false;
434 }
435
436 top.m_ref = m_components.front();
437 top.m_refIndex = 0;
438
439 stack.push_back( top );
440
441 bool matchFound = false;
442 int nloops = 0;
443
444 while( !stack.empty() )
445 {
446 nloops++;
447 auto& current = stack.back();
448
449 for( auto it = current.m_locked.begin(); it != current.m_locked.end(); it++ )
450 {
451 if (it->second == current.m_ref)
452 {
453 wxLogTrace( traceTopoMatch, wxT( "stk: Remove %s from locked\n" ),
454 current.m_ref->m_reference );
455 current.m_locked.erase( it );
456 break;
457 }
458 }
459
460 if( nloops >= c_ITER_LIMIT )
461 {
462 wxLogTrace( traceTopoMatch, wxT( "stk: Iter cnt exceeded\n" ) );
463
465 reason.m_reason = _( "Iteration count exceeded (timeout)" );
466
467 if( aMismatchReasons.empty() )
468 aMismatchReasons.push_back( reason );
469 else
470 aMismatchReasons.insert( aMismatchReasons.begin(), reason );
471
472 return false;
473 }
474
475 if( current.m_currentMatch < 0 )
476 {
477 localReasons.clear();
478 current.m_matches = aTarget->findMatchingComponents( this, current.m_ref, current, localReasons );
479
480 if( current.m_matches.empty() && aMismatchReasons.empty() && !localReasons.empty() )
481 aMismatchReasons = localReasons;
482
483 current.m_currentMatch = 0;
484 }
485
486 wxLogTrace( traceTopoMatch, wxT( "stk: Current '%s' stack %d cm %d/%d locked %d/%d\n" ),
487 current.m_ref->m_reference, (int) stack.size(), current.m_currentMatch,
488 (int) current.m_matches.size(), (int) current.m_locked.size(),
489 (int) m_components.size() );
490
491 if ( current.m_matches.empty() )
492 {
493 wxLogTrace( traceTopoMatch, wxT( "stk: No matches at all, going up [level=%d]\n" ),
494 (int) stack.size() );
495 stack.pop_back();
496 continue;
497 }
498
499 if( current.m_currentMatch >= 0 && current.m_currentMatch >= current.m_matches.size() )
500 {
501 wxLogTrace( traceTopoMatch, wxT( "stk: No more matches, going up [level=%d]\n" ),
502 (int) stack.size() );
503 stack.pop_back();
504 continue;
505 }
506
507 auto& match = current.m_matches[current.m_currentMatch];
508
509 wxLogTrace( traceTopoMatch, wxT( "stk: candidate '%s', match list : ( " ),
510 current.m_matches[current.m_currentMatch]->m_reference, current.m_refIndex );
511
512 for( auto m : current.m_matches )
513 wxLogTrace( traceTopoMatch, wxT( "%s " ), m->GetParent()->GetReferenceAsString() );
514
515 wxLogTrace( traceTopoMatch, wxT( "\n" ) );
516
517 current.m_currentMatch++;
518 current.m_locked[match] = current.m_ref;
519
520 if( current.m_locked.size() == m_components.size() )
521 {
522 current.m_nloops = nloops;
523
524 aResult.clear();
525 aMismatchReasons.clear();
526
527 for( auto iter : current.m_locked )
528 aResult[ iter.second->GetParent() ] = iter.first->GetParent();
529
530 return true;
531 }
532
533
534 int minMatches = std::numeric_limits<int>::max();
535 COMPONENT* altNextRef = nullptr;
536 COMPONENT* bestNextRef = nullptr;
537 int bestRefIndex = 0;
538 int altRefIndex = 0;
539
540 for( size_t i = 0; i < m_components.size(); i++ )
541 {
542 COMPONENT* cmp = m_components[i];
543
544 if( cmp == current.m_ref )
545 continue;
546
547 bool found = false;
548
549 for( auto it = current.m_locked.begin(); it != current.m_locked.end(); it++ )
550 {
551 if( it->second == cmp )
552 {
553 found = true;
554 break;
555 }
556 }
557
558 if( found )
559 continue;
560
561 localReasons.clear();
562 auto matches = aTarget->findMatchingComponents( this, cmp, current, localReasons );
563
564 int nMatches = matches.size();
565
566 if( nMatches == 1 )
567 {
568 bestNextRef = cmp;
569 bestRefIndex = i;
570 break;
571 }
572 else if( nMatches == 0 )
573 {
574 altNextRef = cmp;
575 altRefIndex = i;
576
577 if( aMismatchReasons.empty() && !localReasons.empty() )
578 aMismatchReasons = localReasons;
579 }
580 else if( nMatches < minMatches )
581 {
582 minMatches = nMatches;
583 bestNextRef = cmp;
584 bestRefIndex = i;
585 }
586 }
587
588 BACKTRACK_STAGE next( current );
589 next.m_currentMatch = -1;
590
591 if( bestNextRef )
592 {
593 next.m_ref = bestNextRef;
594 next.m_refIndex = bestRefIndex;
595 }
596 else
597 {
598 next.m_ref = altNextRef;
599 next.m_refIndex = altRefIndex;
600 }
601
602 stack.push_back( next );
603 };
604
605 return false;
606}
607
608
609#if 0
610int main()
611{
612 FILE * f = fopen("connectivity.dump","rb" );
613 auto cgRef = loadCGraph(f);
614 auto cgTarget = loadCGraph(f);
615
616 cgRef->buildConnectivity();
617 cgTarget->buildConnectivity();
618
619 int attempts = 0;
620 int max_loops = 0;
621
622 for( ;; )
623 {
624 cgRef->shuffle();
625 cgTarget->shuffle();
626
627 const BacktrackStage latest = cgRef->matchCGraphs( cgTarget );
628
629 if( !latest.locked.size() )
630 {
631 printf("MATCH FAIL\n");
632 break;
633 }
634
635 //printf("loops: %d\n", latest.nloops );
636 //printf("Locked: %d\n", latest.locked.size() );
637
638 //if (matchFound)
639 //{
640 // for( auto& iter : latest.locked )
641 //{
642 // printf("%-10s : %-10s\n", iter.first->reference.c_str(), iter.second->reference.c_str() );
643 //}
644
645 //}
646
647 if( latest.nloops > max_loops )
648 {
649 max_loops = latest.nloops;
650 }
651
652 if (attempts % 10000 == 0)
653 {
654 printf("attempts: %d maxloops: %d\n", attempts, max_loops );
655 }
656
657 attempts++;
658
659 }
660
661 fclose(f);
662
663 return 0;
664}
665
666#endif
667
668
669COMPONENT::COMPONENT( const wxString& aRef, FOOTPRINT* aParentFp,
670 std::optional<VECTOR2I> aRaOffset ) :
671 m_reference( aRef ),
672 m_parentFootprint( aParentFp ), m_raOffset( aRaOffset )
673{
675}
676
677
678bool COMPONENT::IsSameKind( const COMPONENT& b ) const
679{
680 return m_prefix == b.m_prefix
681 && ( ( m_parentFootprint->GetFPID() == b.m_parentFootprint->GetFPID() )
682 || ( m_parentFootprint->GetFPID().empty()
683 && b.m_parentFootprint->GetFPID().empty() ) );
684}
685
686
688{
689 m_pins.push_back( aPin );
690 aPin->SetParent( this );
691}
692
693
695{
696 if( GetPinCount() != b->GetPinCount() )
697 {
700 aReason.m_reason =
701 wxString::Format( _( "Component %s has %d pads but candidate %s has %d." ), aReason.m_reference,
702 GetPinCount(), aReason.m_candidate, b->GetPinCount() );
703 return false;
704 }
705
706 if( !IsSameKind( *b ) )
707 {
710
711 if( m_prefix != b->m_prefix )
712 {
713 aReason.m_reason = wxString::Format(
714 _( "Reference prefix mismatch: %s uses prefix '%s' but candidate %s uses '%s'." ),
715 aReason.m_reference, m_prefix, aReason.m_candidate, b->m_prefix );
716 }
717 else
718 {
719 wxString refFootprint = GetParent()->GetFPIDAsString();
720 wxString candFootprint = b->GetParent()->GetFPIDAsString();
721
722 if( refFootprint.IsEmpty() )
723 refFootprint = _( "(no library ID)" );
724
725 if( candFootprint.IsEmpty() )
726 candFootprint = _( "(no library ID)" );
727
728 aReason.m_reason =
729 wxString::Format( _( "Library link mismatch: %s expects '%s' but candidate %s is '%s'." ),
730 aReason.m_reference, refFootprint, aReason.m_candidate, candFootprint );
731 }
732
733 return false;
734 }
735
736 for( int pin = 0; pin < b->GetPinCount(); pin++ )
737 {
738 if( !b->m_pins[pin]->IsIsomorphic( *m_pins[pin], aReason ) )
739 {
740 if( aReason.m_reason.IsEmpty() )
741 {
744 aReason.m_reason = wxString::Format( _( "Component pads differ between %s and %s." ),
745 aReason.m_reference, aReason.m_candidate );
746 }
747
748 return false;
749 }
750
751 }
752
753 return true;
754}
755
756
758{
759 auto cmp = new COMPONENT( aFp->GetReference(), aFp );
760
761 for( auto pad : aFp->Pads() )
762 {
763 auto pin = new PIN( );
764 pin->m_netcode = pad->GetNetCode();
765 pin->m_ref = pad->GetNumber();
766 cmp->AddPin( pin );
767 }
768
769 m_components.push_back( cmp );
770}
771
772
773std::unique_ptr<CONNECTION_GRAPH>
774CONNECTION_GRAPH::BuildFromFootprintSet( const std::set<FOOTPRINT*>& aFps )
775{
776 auto cgraph = std::make_unique<CONNECTION_GRAPH>();
777 VECTOR2I ref(0, 0);
778
779 if( aFps.size() > 0 )
780 ref = (*aFps.begin())->GetPosition();
781
782 for( auto fp : aFps )
783 {
784 cgraph->AddFootprint( fp, fp->GetPosition() - ref );
785 }
786
787 cgraph->BuildConnectivity();
788
789 return std::move(cgraph);
790}
791
792
797
798
800{
801 for( COMPONENT* fp : m_components )
802 {
803 delete fp;
804 }
805}
806
807
809{
810 for( PIN* p : m_pins )
811 {
812 delete p;
813 }
814}
815
816
817}; // namespace TMATCH
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
std::deque< PAD * > & Pads()
Definition footprint.h:304
wxString GetFPIDAsString() const
Definition footprint.h:355
const LIB_ID & GetFPID() const
Definition footprint.h:349
wxString GetReferenceAsString() const
Definition footprint.h:750
const wxString & GetReference() const
Definition footprint.h:741
bool empty() const
Definition lib_id.h:193
Handle the data for a net.
Definition netinfo.h:54
const std::map< COMPONENT *, COMPONENT * > & GetMatchingComponentPairs() const
Definition topo_match.h:145
std::map< COMPONENT *, COMPONENT * > m_locked
Definition topo_match.h:152
bool IsSameKind(const COMPONENT &b) const
int GetPinCount() const
Definition topo_match.h:63
COMPONENT(const wxString &aRef, FOOTPRINT *aParentFp, std::optional< VECTOR2I > aRaOffset=std::optional< VECTOR2I >())
FOOTPRINT * m_parentFootprint
Definition topo_match.h:78
std::optional< VECTOR2I > m_raOffset
Definition topo_match.h:75
bool MatchesWith(COMPONENT *b, TOPOLOGY_MISMATCH_REASON &aDetail)
wxString m_prefix
Definition topo_match.h:77
void AddPin(PIN *p)
std::vector< PIN * > & Pins()
Definition topo_match.h:65
friend class PIN
Definition topo_match.h:54
wxString m_reference
Definition topo_match.h:76
std::vector< PIN * > m_pins
Definition topo_match.h:79
FOOTPRINT * GetParent() const
Definition topo_match.h:66
std::vector< COMPONENT * > & Components()
Definition topo_match.h:171
std::vector< COMPONENT * > m_components
Definition topo_match.h:182
void AddFootprint(FOOTPRINT *aFp, const VECTOR2I &aOffset)
static std::unique_ptr< CONNECTION_GRAPH > BuildFromFootprintSet(const std::set< FOOTPRINT * > &aFps)
bool FindIsomorphism(CONNECTION_GRAPH *target, COMPONENT_MATCHES &result, std::vector< TOPOLOGY_MISMATCH_REASON > &aFailureDetails)
std::vector< COMPONENT * > findMatchingComponents(CONNECTION_GRAPH *aRefGraph, COMPONENT *ref, const BACKTRACK_STAGE &partialMatches, std::vector< TOPOLOGY_MISMATCH_REASON > &aFailureDetails)
std::vector< PIN * > m_conns
Definition topo_match.h:119
void SetParent(COMPONENT *parent)
Definition topo_match.h:90
COMPONENT * m_parent
Definition topo_match.h:118
bool IsIsomorphic(const PIN &b, TOPOLOGY_MISMATCH_REASON &aDetail) const
int GetNetCode() const
Definition topo_match.h:108
wxString m_ref
Definition topo_match.h:116
#define _(s)
std::map< FOOTPRINT *, FOOTPRINT * > COMPONENT_MATCHES
Definition topo_match.h:156
bool checkIfPadNetsMatch(const BACKTRACK_STAGE &aMatches, CONNECTION_GRAPH *aRefGraph, COMPONENT *aRef, COMPONENT *aTgt, TOPOLOGY_MISMATCH_REASON &aReason)
wxString GetRefDesPrefix(const wxString &aRefDes)
Get the (non-numeric) prefix from a refdes - e.g.
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
Definition kicad_algo.h:100
CITER next(CITER it)
Definition ptree.cpp:124
Collection of utility functions for component reference designators (refdes)
KIBIS top(path, &reporter)
KIBIS_PIN * pin
static const wxString traceTopoMatch
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695