KiCad PCB EDA Suite
Loading...
Searching...
No Matches
variant_symbol_utils.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
25
26#include <lib_symbol.h>
27#include <pin_type.h>
28#include <sch_pin.h>
29
30#include <algorithm>
31
32
33bool VariantSymbolPinsMatch( const SCH_PIN& aBase, const SCH_PIN& aCandidate )
34{
35 return aBase.GetNumber() == aCandidate.GetNumber()
36 && aBase.GetUnit() == aCandidate.GetUnit()
37 && aBase.GetBodyStyle() == aCandidate.GetBodyStyle()
38 && aBase.GetPosition() == aCandidate.GetPosition();
39}
40
41
42std::vector<VARIANT_COMPAT_RESULT> ValidateVariantSymbolCompatibility( const LIB_SYMBOL& aBase,
43 const LIB_SYMBOL& aCandidate )
44{
45 std::vector<VARIANT_COMPAT_RESULT> results;
46
47 int baseUnits = std::max( aBase.GetUnitCount(), 1 );
48 int candUnits = std::max( aCandidate.GetUnitCount(), 1 );
49
50 if( candUnits < baseUnits )
51 {
54 result.detail = wxString::Format( _( "Candidate has %d unit(s), base requires %d" ),
55 candUnits, baseUnits );
56 results.push_back( result );
57 }
58
59 int baseBodyStyles = aBase.GetBodyStyleCount();
60
61 if( baseBodyStyles > 1 && aCandidate.GetBodyStyleCount() < baseBodyStyles )
62 {
65 result.detail = wxString::Format( _( "Candidate has %d body style(s), base requires %d" ),
66 aCandidate.GetBodyStyleCount(), baseBodyStyles );
67 results.push_back( result );
68 }
69
70 std::vector<const SCH_PIN*> basePins = aBase.GetGraphicalPins();
71 std::vector<const SCH_PIN*> candidatePins = aCandidate.GetGraphicalPins();
72 std::vector<bool> matched( candidatePins.size(), false );
73
74 for( const SCH_PIN* basePin : basePins )
75 {
76 auto sameSlot = [&]( const SCH_PIN* aCandidatePin )
77 {
78 return basePin->GetNumber() == aCandidatePin->GetNumber()
79 && basePin->GetUnit() == aCandidatePin->GetUnit()
80 && basePin->GetBodyStyle() == aCandidatePin->GetBodyStyle();
81 };
82
83 auto findCandidate = [&]( bool aRequirePosition, bool aRequireType )
84 {
85 for( size_t i = 0; i < candidatePins.size(); ++i )
86 {
87 if( matched[i] || !sameSlot( candidatePins[i] ) )
88 continue;
89
90 if( aRequirePosition && candidatePins[i]->GetPosition() != basePin->GetPosition() )
91 continue;
92
93 if( aRequireType && candidatePins[i]->GetType() != basePin->GetType() )
94 continue;
95
96 return i;
97 }
98
99 return candidatePins.size();
100 };
101
102 size_t candidateIndex = findCandidate( true, true );
103
104 if( candidateIndex == candidatePins.size() )
105 candidateIndex = findCandidate( true, false );
106
107 if( candidateIndex == candidatePins.size() )
108 candidateIndex = findCandidate( false, false );
109
110 if( candidateIndex == candidatePins.size() )
111 {
114 result.pinNumber = basePin->GetNumber();
115 result.unit = basePin->GetUnit();
116 result.bodyStyle = basePin->GetBodyStyle();
117 result.detail = wxString::Format(
118 _( "Unit %d, body style %d: pin '%s' not found in candidate" ),
119 result.unit, result.bodyStyle, result.pinNumber );
120 results.push_back( result );
121 continue;
122 }
123
124 matched[candidateIndex] = true;
125 const SCH_PIN* candidatePin = candidatePins[candidateIndex];
126
127 if( candidatePin->GetPosition() != basePin->GetPosition() )
128 {
131 result.pinNumber = basePin->GetNumber();
132 result.unit = basePin->GetUnit();
133 result.bodyStyle = basePin->GetBodyStyle();
134 result.detail = wxString::Format(
135 _( "Unit %d, body style %d: pin '%s' position mismatch "
136 "(%d,%d) vs (%d,%d)" ),
137 result.unit, result.bodyStyle, result.pinNumber,
138 basePin->GetPosition().x, basePin->GetPosition().y,
139 candidatePin->GetPosition().x, candidatePin->GetPosition().y );
140 results.push_back( result );
141 }
142
143 if( candidatePin->GetType() != basePin->GetType() )
144 {
147 result.pinNumber = basePin->GetNumber();
148 result.unit = basePin->GetUnit();
149 result.bodyStyle = basePin->GetBodyStyle();
150 result.detail = wxString::Format(
151 _( "Unit %d, body style %d: pin '%s' type mismatch ('%s' vs '%s')" ),
152 result.unit, result.bodyStyle, result.pinNumber,
153 GetCanonicalElectricalTypeName( basePin->GetType() ),
154 GetCanonicalElectricalTypeName( candidatePin->GetType() ) );
155 results.push_back( result );
156 }
157 }
158
159 for( size_t i = 0; i < candidatePins.size(); ++i )
160 {
161 if( !matched[i] )
162 {
163 const SCH_PIN* candidatePin = candidatePins[i];
166 result.pinNumber = candidatePin->GetNumber();
167 result.unit = candidatePin->GetUnit();
168 result.bodyStyle = candidatePin->GetBodyStyle();
169 result.detail = wxString::Format(
170 _( "Unit %d, body style %d: candidate has extra pin '%s'" ),
171 result.unit, result.bodyStyle, result.pinNumber );
172 results.push_back( result );
173 }
174 }
175
176 return results;
177}
Define a library symbol object.
Definition lib_symbol.h:114
std::vector< const SCH_PIN * > GetGraphicalPins(int aUnit=0, int aBodyStyle=0) const
Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body.
int GetBodyStyleCount() const override
Definition lib_symbol.h:873
int GetUnitCount() const override
int GetBodyStyle() const
Definition sch_item.h:242
int GetUnit() const
Definition sch_item.h:233
VECTOR2I GetPosition() const override
Definition sch_pin.cpp:350
const wxString & GetNumber() const
Definition sch_pin.h:130
ELECTRICAL_PINTYPE GetType() const
Definition sch_pin.cpp:407
#define _(s)
wxString GetCanonicalElectricalTypeName(ELECTRICAL_PINTYPE aType)
Definition pin_type.h:54
wxString result
Test unit parsing edge cases and error handling.
std::vector< VARIANT_COMPAT_RESULT > ValidateVariantSymbolCompatibility(const LIB_SYMBOL &aBase, const LIB_SYMBOL &aCandidate)
Check whether aCandidate can be used as a variant symbol override for aBase.
bool VariantSymbolPinsMatch(const SCH_PIN &aBase, const SCH_PIN &aCandidate)
Check whether two graphical pins occupy the same variant-symbol connection slot.
@ PIN_POSITION_MISMATCH
A matching pin number has a different position in library coordinates.
@ PIN_TYPE_MISMATCH
A matching pin number has a different electrical type.
@ EXTRA_PIN_NUMBER
Candidate has a pin occurrence that is absent from the base.
@ MISSING_BODY_STYLE
Base uses alternate body styles but candidate does not.
@ MISSING_PIN_NUMBER
A base pin number is absent from the candidate for a given unit/body style.
@ INSUFFICIENT_UNITS
Candidate has fewer units than the base.