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
57bool ItemsTouchOnLayer( const BOARD_CONNECTED_ITEM* aItemA, const BOARD_CONNECTED_ITEM* aItemB, PCB_LAYER_ID aLayer );
58
59
65{
66public:
68 m_weight( 0 ),
69 m_visible( true )
70 {}
71
72 CN_EDGE( const std::shared_ptr<CN_ANCHOR>& aSource, const std::shared_ptr<CN_ANCHOR>& aTarget,
73 unsigned aWeight = 0 ) :
74 m_source( aSource ),
75 m_target( aTarget ),
76 m_weight( aWeight ),
77 m_visible( true )
78 {}
79
86 bool operator<( CN_EDGE aOther ) const
87 {
88 return m_weight < aOther.m_weight;
89 }
90
103 bool StableSortCompare( const CN_EDGE& aOther ) const
104 {
105 const VECTOR2I& thisPos = GetSourcePos();
106 const VECTOR2I& otherPos = aOther.GetSourcePos();
107
108 // First compare by source node position
109 if( thisPos.x != otherPos.x )
110 return thisPos.x < otherPos.x;
111
112 if( thisPos.y != otherPos.y )
113 return thisPos.y < otherPos.y;
114
115 // Then compare by weight
116 if( m_weight != aOther.m_weight )
117 return m_weight < aOther.m_weight;
118
119 // Then by visibility
120 if( m_visible != aOther.m_visible )
121 return m_visible && !aOther.m_visible;
122
123 // If everything is equal, return false for stable ordering
124 return false;
125 }
126
127 std::shared_ptr<const CN_ANCHOR> GetSourceNode() const { return m_source; }
128 std::shared_ptr<const CN_ANCHOR> GetTargetNode() const { return m_target; }
129
130 void SetSourceNode( const std::shared_ptr<const CN_ANCHOR>& aNode ) { m_source = aNode; }
131 void SetTargetNode( const std::shared_ptr<const CN_ANCHOR>& aNode ) { m_target = aNode; }
132
134 {
135 if( m_source && !m_source->Valid() )
136 m_source.reset();
137
138 if( m_target && !m_target->Valid() )
139 m_target.reset();
140 }
141
142 void SetWeight( unsigned weight ) { m_weight = weight; }
143 unsigned GetWeight() const { return m_weight; }
144
145 void SetVisible( bool aVisible ) { m_visible = aVisible; }
146 bool IsVisible() const { return m_visible; }
147
148 const VECTOR2I GetSourcePos() const { return m_source->Pos(); }
149 const VECTOR2I GetTargetPos() const { return m_target->Pos(); }
150 unsigned GetLength() const
151 {
152 return ( m_target->Pos() - m_source->Pos() ).EuclideanNorm();
153 }
154
155private:
156 std::shared_ptr<const CN_ANCHOR> m_source;
157 std::shared_ptr<const CN_ANCHOR> m_target;
158 unsigned m_weight;
160};
161
162
164{
165public:
172
173 using CLUSTERS = std::vector<std::shared_ptr<CN_CLUSTER>>;
174
175 /*
176 * Holds a list of CN_ITEMs for a given BOARD_CONNECTED_ITEM. For most items (pads, tracks,
177 * etc.) the list will have a single CN_ITEM, but for ZONEs it will have one item for each
178 * distinct outline on each layer.
179 */
181 {
182 public:
183 ITEM_MAP_ENTRY( CN_ITEM* aItem = nullptr )
184 {
185 if( aItem )
186 m_items.push_back( aItem );
187 }
188
190 {
191 for( CN_ITEM* item : m_items )
192 item->SetValid( false );
193 }
194
195 void Link( CN_ITEM* aItem )
196 {
197 m_items.push_back( aItem );
198 }
199
200 const std::list<CN_ITEM*>& GetItems() const
201 {
202 return m_items;
203 }
204
205 std::list<CN_ITEM*> m_items;
206 };
207
208 CN_CONNECTIVITY_ALGO( CONNECTIVITY_DATA* aParentConnectivityData ) :
209 m_parentConnectivityData( aParentConnectivityData ),
210 m_isLocal( false )
211 {}
212
214 {
215 Clear();
216 }
217
218 bool ItemExists( const BOARD_CONNECTED_ITEM* aItem ) const
219 {
220 return m_itemMap.find( aItem ) != m_itemMap.end();
221 }
222
224 {
225 return m_itemMap[ aItem ];
226 }
227
228 bool IsNetDirty( int aNet ) const
229 {
230 if( aNet < 0 )
231 return false;
232
233 return m_dirtyNets[ aNet ];
234 }
235
237 {
238 for( size_t ii = 0; ii < m_dirtyNets.size(); ii++ )
239 m_dirtyNets[ii] = false;
240 }
241
242 void GetDirtyClusters( CLUSTERS& aClusters ) const
243 {
244 for( const std::shared_ptr<CN_CLUSTER>& cl : m_ratsnestClusters )
245 {
246 int net = cl->OriginNet();
247
248 if( net >= 0 && m_dirtyNets[net] )
249 aClusters.push_back( cl );
250 }
251 }
252
253 int NetCount() const
254 {
255 return m_dirtyNets.size();
256 }
257
258 void Build( BOARD* aBoard, PROGRESS_REPORTER* aReporter = nullptr );
259 void LocalBuild( const std::shared_ptr<CONNECTIVITY_DATA>& aGlobalConnectivity,
260 const std::vector<BOARD_ITEM*>& aLocalItems );
261
262 void Clear();
263
264 bool Remove( BOARD_ITEM* aItem );
265 bool Add( BOARD_ITEM* aItem );
266
267 const CLUSTERS SearchClusters( CLUSTER_SEARCH_MODE aMode, bool aExcludeZones, int aSingleNet );
269
274 void PropagateNets( BOARD_COMMIT* aCommit = nullptr );
275
279 void FillIsolatedIslandsMap( std::map<ZONE*, std::map<PCB_LAYER_ID, ISOLATED_ISLANDS>>& aMap,
280 bool aConnectivityAlreadyRebuilt );
281
282 const CLUSTERS& GetClusters();
283
284 const CN_LIST& ItemList() const
285 {
286 return m_itemList;
287 }
288
289 template <typename Func>
290 void ForEachAnchor( Func&& aFunc ) const
291 {
292 for( CN_ITEM* item : m_itemList )
293 {
294 for( std::shared_ptr<CN_ANCHOR>& anchor : item->Anchors() )
295 aFunc( *anchor );
296 }
297 }
298
299 template <typename Func>
300 void ForEachItem( Func&& aFunc ) const
301 {
302 for( CN_ITEM* item : m_itemList )
303 aFunc( *item );
304 }
305
306 void MarkNetAsDirty( int aNet );
307 void RemoveInvalidRefs();
308
309 void SetProgressReporter( PROGRESS_REPORTER* aReporter );
310
311private:
312 void searchConnections();
313
314 void propagateConnections( BOARD_COMMIT* aCommit = nullptr );
315
316 template <class Container, class BItem>
317 void add( Container& c, BItem brditem )
318 {
319 CN_ITEM* item = c.Add( brditem );
320
321 m_itemMap[ brditem ] = ITEM_MAP_ENTRY( item );
322 }
323
324 void markItemNetAsDirty( const BOARD_ITEM* aItem );
325
326 void updateJumperPads();
327
328private:
331 std::unordered_map<const BOARD_ITEM*, ITEM_MAP_ENTRY> m_itemMap;
332
333 std::vector<std::shared_ptr<CN_CLUSTER>> m_connClusters;
334 std::vector<std::shared_ptr<CN_CLUSTER>> m_ratsnestClusters;
335 std::vector<bool> m_dirtyNets;
336
338 std::shared_ptr<CONNECTIVITY_DATA> m_globalConnectivityData;
339
340 std::mutex m_mutex;
341
343};
344
345
347{
348public:
349 CN_VISITOR( CN_ITEM* aItem, std::vector<std::pair<CN_ITEM*, int>>* aDeferredNetCodes,
350 std::mutex* aDeferredNetCodesMutex ) :
351 m_item( aItem ),
352 m_deferredNetCodes( aDeferredNetCodes ),
353 m_deferredNetCodesMutex( aDeferredNetCodesMutex )
354 {}
355
356 bool operator()( CN_ITEM* aCandidate );
357
358protected:
359 void checkZoneItemConnection( CN_ZONE_LAYER* aZoneLayer, CN_ITEM* aItem );
360
361 void checkZoneZoneConnection( CN_ZONE_LAYER* aZoneLayerA, CN_ZONE_LAYER* aZoneLayerB );
362
363protected:
365
368 std::vector<std::pair<CN_ITEM*, int>>* m_deferredNetCodes;
370};
371
372#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:84
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:410
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_CONNECTED_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)
Represents a single outline of a zone fill on a particular layer.
A progress reporter interface for use in multi-threaded environments.
Handle a list of polygons defining a copper zone.
Definition zone.h:70
bool ItemsTouchOnLayer(const BOARD_CONNECTED_ITEM *aItemA, const BOARD_CONNECTED_ITEM *aItemB, PCB_LAYER_ID aLayer)
Test whether two items have copper in contact on aLayer.
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708