KiCad PCB EDA Suite
Loading...
Searching...
No Matches
connectivity_algo.h
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) 2013-2017 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Maciej Suminski <[email protected]>
8 * @author Tomasz Wlostowski <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24// #define CONNECTIVITY_DEBUG
25
26#ifndef __CONNECTIVITY_ALGO_H
27#define __CONNECTIVITY_ALGO_H
28
30
31#include <algorithm>
32#include <deque>
33#include <functional>
34#include <list>
35#include <memory>
36#include <vector>
37
41
42class CN_RATSNEST_NODES;
43class BOARD;
45class BOARD_ITEM;
46class FOOTPRINT;
47class ZONE;
49
50
56{
57public:
59 m_weight( 0 ),
60 m_visible( true )
61 {}
62
63 CN_EDGE( const std::shared_ptr<CN_ANCHOR>& aSource, const std::shared_ptr<CN_ANCHOR>& aTarget,
64 unsigned aWeight = 0 ) :
65 m_source( aSource ),
66 m_target( aTarget ),
67 m_weight( aWeight ),
68 m_visible( true )
69 {}
70
77 bool operator<( CN_EDGE aOther ) const
78 {
79 return m_weight < aOther.m_weight;
80 }
81
94 bool StableSortCompare( const CN_EDGE& aOther ) const
95 {
96 const VECTOR2I& thisPos = GetSourcePos();
97 const VECTOR2I& otherPos = aOther.GetSourcePos();
98
99 // First compare by source node position
100 if( thisPos.x != otherPos.x )
101 return thisPos.x < otherPos.x;
102
103 if( thisPos.y != otherPos.y )
104 return thisPos.y < otherPos.y;
105
106 // Then compare by weight
107 if( m_weight != aOther.m_weight )
108 return m_weight < aOther.m_weight;
109
110 // Then by visibility
111 if( m_visible != aOther.m_visible )
112 return m_visible && !aOther.m_visible;
113
114 // If everything is equal, return false for stable ordering
115 return false;
116 }
117
118 std::shared_ptr<const CN_ANCHOR> GetSourceNode() const { return m_source; }
119 std::shared_ptr<const CN_ANCHOR> GetTargetNode() const { return m_target; }
120
121 void SetSourceNode( const std::shared_ptr<const CN_ANCHOR>& aNode ) { m_source = aNode; }
122 void SetTargetNode( const std::shared_ptr<const CN_ANCHOR>& aNode ) { m_target = aNode; }
123
125 {
126 if( m_source && !m_source->Valid() )
127 m_source.reset();
128
129 if( m_target && !m_target->Valid() )
130 m_target.reset();
131 }
132
133 void SetWeight( unsigned weight ) { m_weight = weight; }
134 unsigned GetWeight() const { return m_weight; }
135
136 void SetVisible( bool aVisible ) { m_visible = aVisible; }
137 bool IsVisible() const { return m_visible; }
138
139 const VECTOR2I GetSourcePos() const { return m_source->Pos(); }
140 const VECTOR2I GetTargetPos() const { return m_target->Pos(); }
141 unsigned GetLength() const
142 {
143 return ( m_target->Pos() - m_source->Pos() ).EuclideanNorm();
144 }
145
146private:
147 std::shared_ptr<const CN_ANCHOR> m_source;
148 std::shared_ptr<const CN_ANCHOR> m_target;
149 unsigned m_weight;
151};
152
153
155{
156public:
163
164 using CLUSTERS = std::vector<std::shared_ptr<CN_CLUSTER>>;
165
166 /*
167 * Holds a list of CN_ITEMs for a given BOARD_CONNECTED_ITEM. For most items (pads, tracks,
168 * etc.) the list will have a single CN_ITEM, but for ZONEs it will have one item for each
169 * distinct outline on each layer.
170 */
172 {
173 public:
174 ITEM_MAP_ENTRY( CN_ITEM* aItem = nullptr )
175 {
176 if( aItem )
177 m_items.push_back( aItem );
178 }
179
181 {
182 for( CN_ITEM* item : m_items )
183 item->SetValid( false );
184 }
185
186 void Link( CN_ITEM* aItem )
187 {
188 m_items.push_back( aItem );
189 }
190
191 const std::list<CN_ITEM*>& GetItems() const
192 {
193 return m_items;
194 }
195
196 std::list<CN_ITEM*> m_items;
197 };
198
199 CN_CONNECTIVITY_ALGO( CONNECTIVITY_DATA* aParentConnectivityData ) :
200 m_parentConnectivityData( aParentConnectivityData ),
201 m_isLocal( false )
202 {}
203
205 {
206 Clear();
207 }
208
209 bool ItemExists( const BOARD_CONNECTED_ITEM* aItem ) const
210 {
211 return m_itemMap.find( aItem ) != m_itemMap.end();
212 }
213
215 {
216 return m_itemMap[ aItem ];
217 }
218
219 bool IsNetDirty( int aNet ) const
220 {
221 if( aNet < 0 )
222 return false;
223
224 return m_dirtyNets[ aNet ];
225 }
226
228 {
229 for( size_t ii = 0; ii < m_dirtyNets.size(); ii++ )
230 m_dirtyNets[ii] = false;
231 }
232
233 void GetDirtyClusters( CLUSTERS& aClusters ) const
234 {
235 for( const std::shared_ptr<CN_CLUSTER>& cl : m_ratsnestClusters )
236 {
237 int net = cl->OriginNet();
238
239 if( net >= 0 && m_dirtyNets[net] )
240 aClusters.push_back( cl );
241 }
242 }
243
244 int NetCount() const
245 {
246 return m_dirtyNets.size();
247 }
248
249 void Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter = nullptr );
250 void LocalBuild( const std::shared_ptr<CONNECTIVITY_DATA>& aGlobalConnectivity,
251 const std::vector<BOARD_ITEM*>& aLocalItems );
252
253 void Clear();
254
255 bool Remove( BOARD_ITEM* aItem );
256 bool Add( BOARD_ITEM* aItem );
257
258 const CLUSTERS SearchClusters( CLUSTER_SEARCH_MODE aMode, bool aExcludeZones, int aSingleNet );
260
265 void PropagateNets( BOARD_COMMIT* aCommit = nullptr );
266
270 void FillIsolatedIslandsMap( std::map<ZONE*, std::map<PCB_LAYER_ID, ISOLATED_ISLANDS>>& aMap,
271 bool aConnectivityAlreadyRebuilt );
272
273 const CLUSTERS& GetClusters();
274
275 const CN_LIST& ItemList() const
276 {
277 return m_itemList;
278 }
279
280 template <typename Func>
281 void ForEachAnchor( Func&& aFunc ) const
282 {
283 for( CN_ITEM* item : m_itemList )
284 {
285 for( std::shared_ptr<CN_ANCHOR>& anchor : item->Anchors() )
286 aFunc( *anchor );
287 }
288 }
289
290 template <typename Func>
291 void ForEachItem( Func&& aFunc ) const
292 {
293 for( CN_ITEM* item : m_itemList )
294 aFunc( *item );
295 }
296
297 void MarkNetAsDirty( int aNet );
298 void RemoveInvalidRefs();
299
300 void SetProgressReporter( PROGRESS_REPORTER* aReporter );
301
302private:
303 void searchConnections();
304
305 void propagateConnections( BOARD_COMMIT* aCommit = nullptr );
306
307 template <class Container, class BItem>
308 void add( Container& c, BItem brditem )
309 {
310 CN_ITEM* item = c.Add( brditem );
311
312 m_itemMap[ brditem ] = ITEM_MAP_ENTRY( item );
313 }
314
315 void markItemNetAsDirty( const BOARD_ITEM* aItem );
316
317 void updateJumperPads();
318
319private:
322 std::unordered_map<const BOARD_ITEM*, ITEM_MAP_ENTRY> m_itemMap;
323
324 std::vector<std::shared_ptr<CN_CLUSTER>> m_connClusters;
325 std::vector<std::shared_ptr<CN_CLUSTER>> m_ratsnestClusters;
326 std::vector<bool> m_dirtyNets;
327
329 std::shared_ptr<CONNECTIVITY_DATA> m_globalConnectivityData;
330
331 std::mutex m_mutex;
332
334};
335
336
338{
339public:
340 CN_VISITOR( CN_ITEM* aItem, std::vector<std::pair<CN_ITEM*, int>>* aDeferredNetCodes,
341 std::mutex* aDeferredNetCodesMutex ) :
342 m_item( aItem ),
343 m_deferredNetCodes( aDeferredNetCodes ),
344 m_deferredNetCodesMutex( aDeferredNetCodesMutex )
345 {}
346
347 bool operator()( CN_ITEM* aCandidate );
348
349protected:
350 void checkZoneItemConnection( CN_ZONE_LAYER* aZoneLayer, CN_ITEM* aItem );
351
352 void checkZoneZoneConnection( CN_ZONE_LAYER* aZoneLayerA, CN_ZONE_LAYER* aZoneLayerB );
353
354protected:
356
359 std::vector<std::pair<CN_ITEM*, int>>* m_deferredNetCodes;
361};
362
363#endif
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:81
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:372
ITEM_MAP_ENTRY(CN_ITEM *aItem=nullptr)
const std::list< CN_ITEM * > & GetItems() const
void MarkItemsAsInvalid()
std::list< CN_ITEM * > m_items
void Link(CN_ITEM *aItem)
void FillIsolatedIslandsMap(std::map< ZONE *, std::map< PCB_LAYER_ID, ISOLATED_ISLANDS > > &aMap, bool aConnectivityAlreadyRebuilt)
Fill in the isolated islands map with copper islands that are not connected to a net.
bool Remove(BOARD_ITEM *aItem)
bool ItemExists(const BOARD_CONNECTED_ITEM *aItem) const
void ForEachItem(Func &&aFunc) const
CN_CONNECTIVITY_ALGO(CONNECTIVITY_DATA *aParentConnectivityData)
CONNECTIVITY_DATA * m_parentConnectivityData
void add(Container &c, BItem brditem)
PROGRESS_REPORTER * m_progressReporter
std::vector< std::shared_ptr< CN_CLUSTER > > m_connClusters
ITEM_MAP_ENTRY & ItemEntry(const BOARD_CONNECTED_ITEM *aItem)
void GetDirtyClusters(CLUSTERS &aClusters) const
void propagateConnections(BOARD_COMMIT *aCommit=nullptr)
const CLUSTERS & GetClusters()
void LocalBuild(const std::shared_ptr< CONNECTIVITY_DATA > &aGlobalConnectivity, const std::vector< BOARD_ITEM * > &aLocalItems)
const CLUSTERS SearchClusters(CLUSTER_SEARCH_MODE aMode, bool aExcludeZones, int aSingleNet)
void markItemNetAsDirty(const BOARD_ITEM *aItem)
std::vector< std::shared_ptr< CN_CLUSTER > > m_ratsnestClusters
void ForEachAnchor(Func &&aFunc) const
void PropagateNets(BOARD_COMMIT *aCommit=nullptr)
Propagate nets from pads to other items in clusters.
std::shared_ptr< CONNECTIVITY_DATA > m_globalConnectivityData
const CN_LIST & ItemList() const
bool IsNetDirty(int aNet) const
std::vector< bool > m_dirtyNets
std::unordered_map< const BOARD_ITEM *, ITEM_MAP_ENTRY > m_itemMap
void SetProgressReporter(PROGRESS_REPORTER *aReporter)
std::vector< std::shared_ptr< CN_CLUSTER > > CLUSTERS
void Build(BOARD *aBoard, PROGRESS_REPORTER *aReporter=nullptr)
bool Add(BOARD_ITEM *aItem)
std::shared_ptr< const CN_ANCHOR > GetSourceNode() const
std::shared_ptr< const CN_ANCHOR > m_target
bool StableSortCompare(const CN_EDGE &aOther) const
Comparison operator for std::stable_sort.
void SetTargetNode(const std::shared_ptr< const CN_ANCHOR > &aNode)
void SetWeight(unsigned weight)
void RemoveInvalidRefs()
void SetSourceNode(const std::shared_ptr< const CN_ANCHOR > &aNode)
void SetVisible(bool aVisible)
unsigned GetWeight() const
std::shared_ptr< const CN_ANCHOR > GetTargetNode() const
unsigned m_weight
const VECTOR2I GetTargetPos() const
unsigned GetLength() const
std::shared_ptr< const CN_ANCHOR > m_source
CN_EDGE(const std::shared_ptr< CN_ANCHOR > &aSource, const std::shared_ptr< CN_ANCHOR > &aTarget, unsigned aWeight=0)
const VECTOR2I GetSourcePos() const
bool IsVisible() const
bool operator<(CN_EDGE aOther) const
This sort operator provides a sort-by-weight for the ratsnest operation.
CN_ITEM represents a BOARD_CONNETED_ITEM in the connectivity system (ie: a pad, track/arc/via,...
void checkZoneItemConnection(CN_ZONE_LAYER *aZoneLayer, CN_ITEM *aItem)
CN_ITEM * m_item
The item we are looking for connections to.
CN_VISITOR(CN_ITEM *aItem, std::vector< std::pair< CN_ITEM *, int > > *aDeferredNetCodes, std::mutex *aDeferredNetCodesMutex)
void checkZoneZoneConnection(CN_ZONE_LAYER *aZoneLayerA, CN_ZONE_LAYER *aZoneLayerB)
std::vector< std::pair< CN_ITEM *, int > > * m_deferredNetCodes
Deferred net code changes collected during parallel connectivity search.
std::mutex * m_deferredNetCodesMutex
bool operator()(CN_ITEM *aCandidate)
A progress reporter interface for use in multi-threaded environments.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683