KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_netchain.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) 2026 KiCad Developers
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 along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <sch_netchain.h>
21
22#include <algorithm>
23#include <map>
24#include <queue>
25#include <set>
26#include <vector>
27
28#include <connection_graph.h>
29#include <sch_pin.h>
30#include <sch_symbol.h>
31#include <schematic.h>
32
33
34namespace
35{
36
37// Resolve a terminal-pin KIID to the SCH_PIN it names. Terminals may live on
38// pins that are not bridge symbols (RebuildNetChains picks them by physical
39// distance across every chain-net pin), so a chain-local symbol scan is not
40// sufficient — fall through to the schematic-wide resolver.
41SCH_PIN* findPinByUuid( CONNECTION_GRAPH* aGraph, const KIID& aUuid )
42{
43 if( !aGraph || aUuid == niluuid )
44 return nullptr;
45
46 SCHEMATIC* sch = aGraph->GetSchematic();
47
48 if( !sch )
49 return nullptr;
50
51 SCH_ITEM* item = sch->ResolveItem( aUuid, /*aPathOut=*/nullptr,
52 /*aAllowNullptrReturn=*/true );
53
54 return dynamic_cast<SCH_PIN*>( item );
55}
56
57
58wxString netKeyForPin( CONNECTION_GRAPH* aGraph, SCH_PIN* aPin )
59{
60 if( !aGraph || !aPin )
61 return wxEmptyString;
62
64}
65
66} // namespace
67
68
69wxString SCH_NETCHAIN::GetTerminalNetName( int aIdx, CONNECTION_GRAPH* aGraph ) const
70{
71 wxASSERT( aIdx >= 0 && aIdx < 2 );
72
73 if( !aGraph )
74 return wxEmptyString;
75
76 SCH_PIN* pin = findPinByUuid( aGraph, m_terminalPins[aIdx] );
77
78 return netKeyForPin( aGraph, pin );
79}
80
81
82const std::vector<wxString>& SCH_NETCHAIN::GetOrderedNets( CONNECTION_GRAPH* aGraph ) const
83{
85 return m_orderedNets;
86
87 m_orderedNets.clear();
88
89 if( !aGraph || m_nets.size() < 2 )
90 return m_orderedNets;
91
92 SCH_PIN* pinA = findPinByUuid( aGraph, m_terminalPins[0] );
93 SCH_PIN* pinB = findPinByUuid( aGraph, m_terminalPins[1] );
94
95 if( !pinA || !pinB )
96 return m_orderedNets;
97
98 wxString startNet = netKeyForPin( aGraph, pinA );
99 wxString endNet = netKeyForPin( aGraph, pinB );
100
101 if( startNet.IsEmpty() || endNet.IsEmpty() )
102 return m_orderedNets;
103
104 if( !m_nets.count( startNet ) || !m_nets.count( endNet ) )
105 return m_orderedNets;
106
107 // Build a chain-local adjacency map: for every passthrough symbol, connect the
108 // nets on its two pins. We rely on the chain's m_symbols rather than rebuilding
109 // the schematic-wide bridge graph because the chain already names its symbols.
110 std::map<wxString, std::set<wxString>> adjacency;
111
112 for( SCH_SYMBOL* sym : m_symbols )
113 {
114 if( !sym )
115 continue;
116
117 std::vector<SCH_PIN*> pins = sym->GetPins();
118 wxString last;
119
120 for( SCH_PIN* p : pins )
121 {
122 wxString net = netKeyForPin( aGraph, p );
123
124 if( net.IsEmpty() || !m_nets.count( net ) )
125 continue;
126
127 if( !last.IsEmpty() && last != net )
128 {
129 adjacency[last].insert( net );
130 adjacency[net].insert( last );
131 }
132
133 last = net;
134 }
135 }
136
137 // BFS shortest path from startNet to endNet, recording predecessors for reconstruction.
138 std::map<wxString, wxString> predecessor;
139 std::set<wxString> visited;
140 std::queue<wxString> frontier;
141
142 frontier.push( startNet );
143 visited.insert( startNet );
144
145 bool foundEnd = false;
146
147 while( !frontier.empty() && !foundEnd )
148 {
149 wxString cur = frontier.front();
150 frontier.pop();
151
152 if( cur == endNet )
153 {
154 foundEnd = true;
155 break;
156 }
157
158 auto it = adjacency.find( cur );
159
160 if( it == adjacency.end() )
161 continue;
162
163 for( const wxString& nbr : it->second )
164 {
165 if( visited.insert( nbr ).second )
166 {
167 predecessor[nbr] = cur;
168 frontier.push( nbr );
169 }
170 }
171 }
172
173 std::vector<wxString> path;
174
175 if( foundEnd )
176 {
177 // Reconstruct in reverse, then flip.
178 for( wxString cur = endNet; cur != startNet; cur = predecessor[cur] )
179 path.push_back( cur );
180
181 path.push_back( startNet );
182 std::reverse( path.begin(), path.end() );
183 }
184 else
185 {
186 // Defensive fallback: chain is internally disconnected. Place the two
187 // terminals at the bookends and the remaining ordering happens below.
188 path.push_back( startNet );
189
190 if( startNet != endNet )
191 path.push_back( endNet );
192 }
193
194 // Append any off-path members alphabetically (m_nets is already a sorted set).
195 std::set<wxString> onPath( path.begin(), path.end() );
196
197 m_orderedNets = std::move( path );
198
199 for( const wxString& net : m_nets )
200 {
201 if( !onPath.count( net ) )
202 m_orderedNets.push_back( net );
203 }
204
205 m_orderedNetsDirty = false;
206 return m_orderedNets;
207}
Calculate the connectivity of a schematic and generates netlists.
static wxString MakeNetChainKey(const wxString &aRawNetName, long aSubgraphCode)
Map a subgraph's raw net name and code to the stable key used as a SCH_NETCHAIN member.
SCHEMATIC * GetSchematic() const
CONNECTION_SUBGRAPH * GetSubgraphForItem(SCH_ITEM *aItem) const
Definition kiid.h:48
Holds all the data relating to one schematic.
Definition schematic.h:89
SCH_ITEM * ResolveItem(const KIID &aID, SCH_SHEET_PATH *aPathOut=nullptr, bool aAllowNullptrReturn=false) const
Definition schematic.h:127
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:166
std::set< wxString > m_nets
std::vector< wxString > m_orderedNets
const std::vector< wxString > & GetOrderedNets(CONNECTION_GRAPH *aGraph) const
Return the chain's member nets ordered from terminal pin A's net to terminal pin B's net along the sh...
KIID m_terminalPins[2]
std::set< class SCH_SYMBOL * > m_symbols
bool m_orderedNetsDirty
wxString GetTerminalNetName(int aIdx, CONNECTION_GRAPH *aGraph) const
Resolve terminal pin aIdx (0 or 1) to the net-chain key of its owning subgraph via aGraph.
Schematic symbol object.
Definition sch_symbol.h:73
KIID niluuid(0)
std::string path
KIBIS_PIN * pin
KIBIS_PIN * pinA