KiCad PCB EDA Suite
Loading...
Searching...
No Matches
connectivity_items.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 (C) 2018-2023 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, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
28
29#ifndef PCBNEW_CONNECTIVITY_ITEMS_H
30#define PCBNEW_CONNECTIVITY_ITEMS_H
31
32#include <board.h>
33#include <pad.h>
34#include <footprint.h>
35#include <pcb_track.h>
36#include <pcb_shape.h>
37#include <zone.h>
38
40
41#include <memory>
42#include <algorithm>
43#include <functional>
44#include <vector>
45#include <deque>
46
49
50class CN_ITEM;
51class CN_CLUSTER;
52
53
59{
60public:
61 CN_ANCHOR( const VECTOR2I& aPos, CN_ITEM* aItem ) :
62 m_pos( aPos ),
63 m_item( aItem ),
64 m_tag( -1 ),
65 m_noline( false )
66 { }
67
68 bool Valid() const;
69
70 bool Dirty() const;
71
72 CN_ITEM* Item() const { return m_item; }
73 void SetItem( CN_ITEM* aItem ) { m_item = aItem; }
74
76
77 const VECTOR2I& Pos() const { return m_pos; }
78
79 void Move( const VECTOR2I& aPos )
80 {
81 m_pos += aPos;
82 }
83
84 unsigned int Dist( const CN_ANCHOR& aSecond )
85 {
86 return ( m_pos - aSecond.Pos() ).EuclideanNorm();
87 }
88
90 int GetTag() const { return m_tag; }
91 void SetTag( int aTag ) { m_tag = aTag; }
92
94 const bool& GetNoLine() const { return m_noline; }
95 void SetNoLine( bool aEnable ) { m_noline = aEnable; }
96
97 const std::shared_ptr<CN_CLUSTER>& GetCluster() const { return m_cluster; }
98 void SetCluster( std::shared_ptr<CN_CLUSTER>& aCluster ) { m_cluster = aCluster; }
99
107 bool IsDangling() const;
108
112 int ConnectedItemsCount() const;
113
114 // Tag used for unconnected items.
115 static const int TAG_UNCONNECTED = -1;
116
117private:
120 int m_tag;
121 bool m_noline;
122
123 std::shared_ptr<CN_CLUSTER> m_cluster;
124};
125
126
127
133{
134public:
135 void Dump();
136
137 CN_ITEM( BOARD_CONNECTED_ITEM* aParent, bool aCanChangeNet, int aAnchorCount = 2 )
138 {
139 m_parent = aParent;
140 m_canChangeNet = aCanChangeNet;
141 m_visited = false;
142 m_valid = true;
143 m_dirty = true;
144 m_anchors.reserve( std::max( 6, aAnchorCount ) );
146 m_connected.reserve( 8 );
147 }
148
149 virtual ~CN_ITEM()
150 {
151 for( const std::shared_ptr<CN_ANCHOR>& anchor : m_anchors )
152 anchor->SetItem( nullptr );
153 };
154
155 std::shared_ptr<CN_ANCHOR> AddAnchor( const VECTOR2I& aPos )
156 {
157 m_anchors.emplace_back( std::make_shared<CN_ANCHOR>( aPos, this ) );
158 return m_anchors.at( m_anchors.size() - 1 );
159 }
160
161 std::vector<std::shared_ptr<CN_ANCHOR>>& Anchors() { return m_anchors; }
162
163 void SetValid( bool aValid ) { m_valid = aValid; }
164 bool Valid() const { return m_valid; }
165
166 void SetDirty( bool aDirty ) { m_dirty = aDirty; }
167 bool Dirty() const { return m_dirty; }
168
172 void SetLayers( const LAYER_RANGE& aLayers ) { m_layers = aLayers; }
173
177 void SetLayer( int aLayer ) { m_layers = LAYER_RANGE( aLayer, aLayer ); }
178
182 const LAYER_RANGE& Layers() const { return m_layers; }
183
187 virtual int Layer() const
188 {
189 return Layers().Start();
190 }
191
192 const BOX2I& BBox()
193 {
194 if( m_dirty && m_valid )
196
197 return m_bbox;
198 }
199
201
202 const std::vector<CN_ITEM*>& ConnectedItems() const { return m_connected; }
203 void ClearConnections() { m_connected.clear(); }
204
205 void SetVisited( bool aVisited ) { m_visited = aVisited; }
206 bool Visited() const { return m_visited; }
207
208 bool CanChangeNet() const { return m_canChangeNet; }
209
210 void Connect( CN_ITEM* b )
211 {
212 std::lock_guard<std::mutex> lock( m_listLock );
213
214 auto i = std::lower_bound( m_connected.begin(), m_connected.end(), b );
215
216 if( i != m_connected.end() && *i == b )
217 return;
218
219 m_connected.insert( i, b );
220 }
221
222 void RemoveInvalidRefs();
223
224 virtual int AnchorCount() const;
225 virtual const VECTOR2I GetAnchor( int n ) const;
226
227 int Net() const
228 {
229 return ( !m_parent || !m_valid ) ? -1 : m_parent->GetNetCode();
230 }
231
232protected:
233 bool m_dirty;
237
238private:
240
241 std::vector<CN_ITEM*> m_connected;
242 std::vector<std::shared_ptr<CN_ANCHOR>> m_anchors;
243
245
247 bool m_valid;
248
249 std::mutex m_listLock;
250};
251
252
253/*
254 * Represents a single outline of a zone fill on a particular layer. \a aSubpolyIndex indicates
255 * which outline in the fill's SHAPE_POLY_SET.
256 */
257class CN_ZONE_LAYER : public CN_ITEM
258{
259public:
260 CN_ZONE_LAYER( ZONE* aParent, PCB_LAYER_ID aLayer, int aSubpolyIndex ) :
261 CN_ITEM( aParent, false ),
262 m_zone( aParent ),
263 m_subpolyIndex( aSubpolyIndex ),
264 m_layer( aLayer )
265 {
266 m_fillPoly = aParent->GetFilledPolysList( aLayer );
267 SetLayers( aLayer );
268 }
269
271 {
272 if( m_zone->IsTeardropArea() )
273 return;
274
275 for( unsigned int ii = 0; ii < m_fillPoly->TriangulatedPolyCount(); ++ii )
276 {
277 const auto* triangleSet = m_fillPoly->TriangulatedPolygon( ii );
278
279 if( triangleSet->GetSourceOutlineIndex() != m_subpolyIndex )
280 continue;
281
282 for( const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI& tri : triangleSet->Triangles() )
283 {
284 BOX2I bbox = tri.BBox();
285 const int mmin[2] = { bbox.GetX(), bbox.GetY() };
286 const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
287
288 m_rTree.Insert( mmin, mmax, &tri );
289 }
290 }
291 }
292
293 int SubpolyIndex() const { return m_subpolyIndex; }
294
295 PCB_LAYER_ID GetLayer() const { return m_layer; }
296
297 bool ContainsPoint( const VECTOR2I& p ) const
298 {
299 if( m_zone->IsTeardropArea() )
300 return m_fillPoly->Outline( m_subpolyIndex ).Collide( p ) ;
301
302 int min[2] = { p.x, p.y };
303 int max[2] = { p.x, p.y };
304 bool collision = false;
305
306 auto visitor =
307 [&]( const SHAPE* aShape ) -> bool
308 {
309 if( aShape->Collide( p ) )
310 {
311 collision = true;
312 return false;
313 }
314
315 return true;
316 };
317
318 m_rTree.Search( min, max, visitor );
319
320 return collision;
321 }
322
324
325 virtual int AnchorCount() const override;
326 virtual const VECTOR2I GetAnchor( int n ) const override;
327
329 {
330 return m_fillPoly->Outline( m_subpolyIndex );
331 }
332
333 bool Collide( SHAPE* aRefShape ) const
334 {
335 if( m_zone->IsTeardropArea() )
336 return m_fillPoly->Collide( aRefShape );
337
338 BOX2I bbox = aRefShape->BBox();
339 int min[2] = { bbox.GetX(), bbox.GetY() };
340 int max[2] = { bbox.GetRight(), bbox.GetBottom() };
341 bool collision = false;
342
343 auto visitor =
344 [&]( const SHAPE* aShape ) -> bool
345 {
346 if( aRefShape->Collide( aShape ) )
347 {
348 collision = true;
349 return false;
350 }
351
352 return true;
353 };
354
355 m_rTree.Search( min, max, visitor );
356
357 return collision;
358 }
359
360 bool HasSingleConnection();
361
362private:
366 std::shared_ptr<SHAPE_POLY_SET> m_fillPoly;
367 RTree<const SHAPE*, int, 2, double> m_rTree;
368};
369
370
371
372
374{
375public:
377 {
378 m_dirty = false;
379 m_hasInvalid = false;
380 }
381
382 void Clear()
383 {
384 for( CN_ITEM* item : m_items )
385 delete item;
386
387 m_items.clear();
389 }
390
391 std::vector<CN_ITEM*>::iterator begin() { return m_items.begin(); };
392 std::vector<CN_ITEM*>::iterator end() { return m_items.end(); };
393
394 std::vector<CN_ITEM*>::const_iterator begin() const { return m_items.begin(); }
395 std::vector<CN_ITEM*>::const_iterator end() const { return m_items.end(); }
396
397 CN_ITEM* operator[] ( int aIndex ) { return m_items[aIndex]; }
398
399 template <class T>
400 void FindNearby( CN_ITEM* aItem, T aFunc )
401 {
402 m_index.Query( aItem->BBox(), aItem->Layers(), aFunc );
403 }
404
405 void SetHasInvalid( bool aInvalid = true ) { m_hasInvalid = aInvalid; }
406
407 void SetDirty( bool aDirty = true ) { m_dirty = aDirty; }
408 bool IsDirty() const { return m_dirty; }
409
410 void RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage );
411
413 {
414 for( CN_ITEM* item : m_items )
415 item->SetDirty( false );
416
417 SetDirty( false );
418 }
419
420 int Size() const { return m_items.size(); }
421
422 CN_ITEM* Add( PAD* pad );
423 CN_ITEM* Add( PCB_TRACK* track );
424 CN_ITEM* Add( PCB_ARC* track );
425 CN_ITEM* Add( PCB_VIA* via );
426 CN_ITEM* Add( CN_ZONE_LAYER* zitem );
427 CN_ITEM* Add( PCB_SHAPE* shape );
428
429 const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer );
430
431protected:
432 void addItemtoTree( CN_ITEM* item )
433 {
434 m_index.Insert( item );
435 }
436
437protected:
438 std::vector<CN_ITEM*> m_items;
439
440private:
444};
445
446
448{
449public:
450 CN_CLUSTER();
451 ~CN_CLUSTER();
452
453 bool HasValidNet() const { return m_originNet > 0; }
454 int OriginNet() const { return m_originNet; }
455
456 wxString OriginNetName() const;
457
458 bool Contains( const CN_ITEM* aItem );
459 bool Contains( const BOARD_CONNECTED_ITEM* aItem );
460 void Dump();
461
462 int Size() const { return m_items.size(); }
463
464 bool IsOrphaned() const
465 {
466 return m_originPad == nullptr;
467 }
468
469 bool IsConflicting() const { return m_conflicting; }
470
471 void Add( CN_ITEM* item );
472
473 std::vector<CN_ITEM*>::iterator begin() { return m_items.begin(); };
474 std::vector<CN_ITEM*>::iterator end() { return m_items.end(); };
475
476private:
480 std::vector<CN_ITEM*> m_items;
481 std::unordered_map<int, int> m_netRanks;
482};
483
484
485
486#endif /* PCBNEW_CONNECTIVITY_ITEMS_H */
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
coord_type GetY() const
Definition: box2.h:198
coord_type GetX() const
Definition: box2.h:197
coord_type GetRight() const
Definition: box2.h:207
coord_type GetBottom() const
Definition: box2.h:212
CN_ANCHOR represents a physical location that can be connected: a pad or a track/arc/via endpoint.
void SetTag(int aTag)
CN_ITEM * m_item
Pad or track/arc/via owning the anchor.
static const int TAG_UNCONNECTED
VECTOR2I m_pos
Position of the anchor.
void Move(const VECTOR2I &aPos)
bool Valid() const
void SetNoLine(bool aEnable)
int ConnectedItemsCount() const
std::shared_ptr< CN_CLUSTER > m_cluster
Cluster to which the anchor belongs.
CN_ANCHOR(const VECTOR2I &aPos, CN_ITEM *aItem)
const bool & GetNoLine() const
int GetTag() const
const std::shared_ptr< CN_CLUSTER > & GetCluster() const
unsigned int Dist(const CN_ANCHOR &aSecond)
void SetCluster(std::shared_ptr< CN_CLUSTER > &aCluster)
const VECTOR2I & Pos() const
bool Dirty() const
CN_ITEM * Item() const
int m_tag
Tag for quick connection resolution.
bool m_noline
Whether it the node can be a target for ratsnest lines.
BOARD_CONNECTED_ITEM * Parent() const
bool IsDangling() const
The anchor point is dangling if the parent is a track and this anchor point is not connected to anoth...
void SetItem(CN_ITEM *aItem)
int Size() const
std::vector< CN_ITEM * >::iterator end()
std::vector< CN_ITEM * > m_items
bool IsConflicting() const
bool IsOrphaned() const
bool Contains(const CN_ITEM *aItem)
void Add(CN_ITEM *item)
CN_ITEM * m_originPad
std::vector< CN_ITEM * >::iterator begin()
wxString OriginNetName() const
std::unordered_map< int, int > m_netRanks
bool HasValidNet() const
int OriginNet() const
CN_ITEM represents a BOARD_CONNETED_ITEM in the connectivity system (ie: a pad, track/arc/via,...
virtual int Layer() const
Return the item's layer, for single-layered items only.
void SetLayers(const LAYER_RANGE &aLayers)
Set the layers spanned by the item to aLayers.
void Connect(CN_ITEM *b)
virtual ~CN_ITEM()
const BOX2I & BBox()
virtual int AnchorCount() const
void RemoveInvalidRefs()
bool m_visited
visited flag for the BFS scan
std::vector< CN_ITEM * > m_connected
list of physically touching items
const std::vector< CN_ITEM * > & ConnectedItems() const
int Net() const
void SetValid(bool aValid)
BOARD_CONNECTED_ITEM * m_parent
bool Valid() const
std::shared_ptr< CN_ANCHOR > AddAnchor(const VECTOR2I &aPos)
void ClearConnections()
BOX2I m_bbox
bounding box for the item
virtual const VECTOR2I GetAnchor(int n) const
LAYER_RANGE m_layers
layer range over which the item exists
bool m_canChangeNet
can the net propagator modify the netcode?
void SetDirty(bool aDirty)
bool CanChangeNet() const
bool m_dirty
used to identify recently added item not yet scanned into the connectivity search
CN_ITEM(BOARD_CONNECTED_ITEM *aParent, bool aCanChangeNet, int aAnchorCount=2)
void SetLayer(int aLayer)
Set the layers spanned by the item to a single layer aLayer.
void SetVisited(bool aVisited)
const LAYER_RANGE & Layers() const
Return the contiguous set of layers spanned by the item.
std::vector< std::shared_ptr< CN_ANCHOR > > m_anchors
bool m_valid
used to identify garbage items (we use lazy removal)
bool Dirty() const
std::vector< std::shared_ptr< CN_ANCHOR > > & Anchors()
BOARD_CONNECTED_ITEM * Parent() const
bool Visited() const
std::mutex m_listLock
mutex protecting this item's connected_items set to
CN_RTREE< CN_ITEM * > m_index
CN_ITEM * operator[](int aIndex)
CN_ITEM * Add(PAD *pad)
std::vector< CN_ITEM * >::iterator begin()
std::vector< CN_ITEM * >::const_iterator begin() const
void SetDirty(bool aDirty=true)
int Size() const
std::vector< CN_ITEM * >::const_iterator end() const
bool IsDirty() const
std::vector< CN_ITEM * >::iterator end()
std::vector< CN_ITEM * > m_items
void FindNearby(CN_ITEM *aItem, T aFunc)
void ClearDirtyFlags()
void addItemtoTree(CN_ITEM *item)
void SetHasInvalid(bool aInvalid=true)
void RemoveInvalidItems(std::vector< CN_ITEM * > &aGarbage)
CN_RTREE - Implements an R-tree for fast spatial indexing of connectivity items.
void Insert(T aItem)
Function Insert() Inserts an item into the tree.
void Query(const BOX2I &aBounds, const LAYER_RANGE &aRange, Visitor &aVisitor) const
Function Query() Executes a function object aVisitor for each item whose bounding box intersects with...
void RemoveAll()
Function RemoveAll() Removes all items from the RTree.
virtual int AnchorCount() const override
const SHAPE_LINE_CHAIN & GetOutline() const
CN_ZONE_LAYER(ZONE *aParent, PCB_LAYER_ID aLayer, int aSubpolyIndex)
virtual const VECTOR2I GetAnchor(int n) const override
PCB_LAYER_ID GetLayer() const
RTree< const SHAPE *, int, 2, double > m_rTree
bool Collide(SHAPE *aRefShape) const
int SubpolyIndex() const
PCB_LAYER_ID m_layer
PCB_LAYER_ID GetLayer()
std::shared_ptr< SHAPE_POLY_SET > m_fillPoly
bool ContainsPoint(const VECTOR2I &p) const
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74
Represent a contiguous set of PCB layers.
Definition: pns_layerset.h:32
int Start() const
Definition: pns_layerset.h:82
Definition: pad.h:59
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
An abstract shape on 2D plane.
Definition: shape.h:126
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Definition: shape.h:181
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
Handle a list of polygons defining a copper zone.
Definition: zone.h:72
const std::shared_ptr< SHAPE_POLY_SET > & GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition: zone.h:615
bool IsTeardropArea() const
Definition: zone.h:694
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
@ PCB_LAYER_ID_COUNT
Definition: layer_ids.h:137