KiCad PCB EDA Suite
Loading...
Searching...
No Matches
from_to_cache.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.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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 <cstdio>
21#include <memory>
22
23#include <reporter.h>
24#include <board.h>
25#include <footprint.h>
26#include <pad.h>
27#include <string_utils.h>
28
29#include <pcbexpr_evaluator.h>
30
33
35
36
38{
39 m_ftEndpoints.clear();
40
41 for( FOOTPRINT* footprint : m_board->Footprints() )
42 {
43 for( PAD* pad : footprint->Pads() )
44 {
45 FT_ENDPOINT ent;
46 ent.name = footprint->GetReference() + wxT( "-" ) + pad->GetNumber();
47 ent.parent = pad;
48 m_ftEndpoints.push_back( ent );
49 ent.name = footprint->GetReference();
50 ent.parent = pad;
51 m_ftEndpoints.push_back( std::move( ent ) );
52 }
53 }
54}
55
56
62
63
64static bool isVertexVisited( CN_ITEM* v, const std::vector<CN_ITEM*>& path )
65{
66 for( CN_ITEM* u : path )
67 {
68 if ( u == v )
69 return true;
70 }
71
72 return false;
73}
74
75
76static PATH_STATUS uniquePathBetweenNodes( CN_ITEM* u, CN_ITEM* v, std::vector<CN_ITEM*>& outPath )
77{
78 using Path = std::vector<CN_ITEM*>;
79 std::deque<Path> Q;
80
81 Path pInit;
82 bool pathFound = false;
83 pInit.push_back( u );
84 Q.push_back( std::move( pInit ) );
85
86 while( Q.size() )
87 {
88 Path path = Q.front();
89 Q.pop_front();
90 CN_ITEM* last = path.back();
91
92 if( last == v )
93 {
94 outPath = path;
95
96 if( pathFound )
97 return PS_MULTIPLE_PATHS;
98
99 pathFound = true;
100 }
101
102 for( CN_ITEM* ci : last->ConnectedItems() )
103 {
104 bool vertexVisited = isVertexVisited( ci, path );
105
106 for( std::vector<CN_ITEM*>& p : Q )
107 {
108 if( isVertexVisited( ci, p ) )
109 {
110 vertexVisited = true;
111 break;
112 }
113 }
114
115 if( !vertexVisited )
116 {
117 Path newpath( path );
118 newpath.push_back( ci );
119 Q.push_back( std::move( newpath ) );
120 }
121 }
122 }
123
124 return pathFound ? PS_OK : PS_NO_PATH;
125};
126
127
128int FROM_TO_CACHE::cacheFromToPaths( const wxString& aFrom, const wxString& aTo )
129{
130 std::vector<FT_PATH> paths;
131 std::shared_ptr<CONNECTIVITY_DATA> connectivity = m_board->GetConnectivity();
132 std::shared_ptr<CN_CONNECTIVITY_ALGO> cnAlgo = connectivity->GetConnectivityAlgo();
133
134 for( FT_ENDPOINT& endpoint : m_ftEndpoints )
135 {
136 if( WildCompareString( aFrom, endpoint.name, false ) )
137 {
138 FT_PATH p;
139 p.net = endpoint.parent->GetNetCode();
140 p.from = endpoint.parent;
141 p.to = nullptr;
142 paths.push_back( std::move( p ) );
143 }
144 }
145
146 for( FT_PATH& path : paths )
147 {
148 int count = 0;
149
150 wxString fromName = path.from->GetParentFootprint()->GetReference()
151 + wxT( "-" ) + path.from->GetNumber();
152
153 auto padCandidates = connectivity->GetConnectedItems( path.from, EXCLUDE_ZONES );
154 PAD* toPad = nullptr;
155
156 for( BOARD_CONNECTED_ITEM* pitem : padCandidates )
157 {
158 if( pitem == path.from )
159 continue;
160
161 if( pitem->Type() != PCB_PAD_T )
162 continue;
163
164 const PAD *pad = static_cast<const PAD*>( pitem );
165
166 wxString toName = pad->GetParentFootprint()->GetReference()
167 + wxT( "-" ) + pad->GetNumber();
168
169 for( const FT_ENDPOINT& endpoint : m_ftEndpoints )
170 {
171 if( pad == endpoint.parent )
172 {
173 if( WildCompareString( aTo, endpoint.name, false ) )
174 {
175 count++;
176 toPad = endpoint.parent;
177
178 path.to = toPad;
179 path.fromName = fromName;
180 path.toName = toName;
181 path.fromWildcard = aFrom;
182 path.toWildcard = aTo;
183
184 if( count >= 2 )
185 {
186 // fixme: report this somewhere?
187 path.to = nullptr;
188 }
189 }
190 }
191 }
192 }
193 }
194
195 int newPaths = 0;
196
197 for( FT_PATH& path : paths )
198 {
199 if( !path.from || !path.to )
200 continue;
201
202 CN_ITEM* cnFrom = cnAlgo->ItemEntry( path.from ).GetItems().front();
203 CN_ITEM* cnTo = cnAlgo->ItemEntry( path.to ).GetItems().front();
204 std::vector<CN_ITEM*> upath;
205
206 auto result = uniquePathBetweenNodes( cnFrom, cnTo, upath );
207
208 if( result == PS_OK )
209 path.isUnique = true;
210 else
211 path.isUnique = false;
212
213 if( result == PS_NO_PATH )
214 continue;
215
216 for( const CN_ITEM* item : upath )
217 path.pathItems.insert( item->Parent() );
218
219 m_ftPaths.push_back( path );
220 newPaths++;
221 }
222
223 return newPaths;
224}
225
226bool FROM_TO_CACHE::IsOnFromToPath( BOARD_CONNECTED_ITEM* aItem, const wxString& aFrom, const wxString& aTo )
227{
228 int nFromTosFound = 0;
229
230 if( !m_board )
231 return false;
232
233 for( int attempt = 0; attempt < 2; attempt++ )
234 {
235 // item already belongs to path
236 for( FT_PATH& ftPath : m_ftPaths )
237 {
238 if( aFrom == ftPath.fromWildcard && aTo == ftPath.toWildcard )
239 {
240 nFromTosFound++;
241
242 if( ftPath.pathItems.count( aItem ) )
243 return true;
244 }
245 }
246
247 if( !nFromTosFound )
248 cacheFromToPaths( aFrom, aTo );
249 else
250 return false;
251 }
252
253 return false;
254}
255
256
258{
259 m_board = aBoard;
261 m_ftPaths.clear();
262}
263
264
265FROM_TO_CACHE::FT_PATH* FROM_TO_CACHE::QueryFromToPath( const std::set<BOARD_CONNECTED_ITEM*>& aItems )
266{
267 for( FT_PATH& ftPath : m_ftPaths )
268 {
269 if ( ftPath.pathItems == aItems )
270 return &ftPath;
271 }
272
273 return nullptr;
274}
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:322
CN_ITEM represents a BOARD_CONNETED_ITEM in the connectivity system (ie: a pad, track/arc/via,...
const std::vector< CN_ITEM * > & ConnectedItems() const
int cacheFromToPaths(const wxString &aFrom, const wxString &aTo)
std::vector< FT_PATH > m_ftPaths
FT_PATH * QueryFromToPath(const std::set< BOARD_CONNECTED_ITEM * > &aItems)
bool IsOnFromToPath(BOARD_CONNECTED_ITEM *aItem, const wxString &aFrom, const wxString &aTo)
std::vector< FT_ENDPOINT > m_ftEndpoints
void buildEndpointList()
void Rebuild(BOARD *aBoard)
Definition pad.h:55
#define EXCLUDE_ZONES
PATH_STATUS
@ PS_OK
@ PS_MULTIPLE_PATHS
@ PS_NO_PATH
static bool isVertexVisited(CN_ITEM *v, const std::vector< CN_ITEM * > &path)
static PATH_STATUS uniquePathBetweenNodes(CN_ITEM *u, CN_ITEM *v, std::vector< CN_ITEM * > &outPath)
bool WildCompareString(const wxString &pattern, const wxString &string_to_tst, bool case_sensitive)
Compare a string against wild card (* and ?) pattern using the usual rules.
std::string path
wxString result
Test unit parsing edge cases and error handling.
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:87