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 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
25#ifndef PCBNEW_CONNECTIVITY_ITEMS_H
26#define PCBNEW_CONNECTIVITY_ITEMS_H
27
30
31#include <algorithm>
32#include <atomic>
33#include <deque>
34#include <functional>
35#include <memory>
36#include <vector>
37
40
41class CN_ITEM;
42class CN_CLUSTER;
43class PCB_SHAPE;
44
45
51{
52public:
53 CN_ANCHOR( const VECTOR2I& aPos, CN_ITEM* aItem ) :
54 m_pos( aPos ),
55 m_item( aItem ),
56 m_tag( -1 ),
57 m_noline( false )
58 { }
59
60 bool Valid() const;
61
62 bool Dirty() const;
63
64 CN_ITEM* Item() const { return m_item; }
65 void SetItem( CN_ITEM* aItem ) { m_item = aItem; }
66
68
69 const VECTOR2I& Pos() const { return m_pos; }
70
71 void Move( const VECTOR2I& aPos )
72 {
73 m_pos += aPos;
74 }
75
76 unsigned int Dist( const CN_ANCHOR& aSecond )
77 {
78 return ( m_pos - aSecond.Pos() ).EuclideanNorm();
79 }
80
82 int GetTag() const { return m_tag; }
83 void SetTag( int aTag ) { m_tag = aTag; }
84
86 const bool& GetNoLine() const { return m_noline; }
87 void SetNoLine( bool aEnable ) { m_noline = aEnable; }
88
89 const std::shared_ptr<CN_CLUSTER>& GetCluster() const { return m_cluster; }
90 void SetCluster( std::shared_ptr<CN_CLUSTER>& aCluster ) { m_cluster = aCluster; }
91
99 bool IsDangling() const;
100
104 int ConnectedItemsCount() const;
105
106 // Tag used for unconnected items.
107 static const int TAG_UNCONNECTED = -1;
108
109private:
112 int m_tag;
113 bool m_noline;
114
115 std::shared_ptr<CN_CLUSTER> m_cluster;
116};
117
118
119
125{
126public:
127 void Dump();
128
129 CN_ITEM( BOARD_CONNECTED_ITEM* aParent, bool aCanChangeNet, int aAnchorCount = 2 )
130 {
131 m_parent = aParent;
132 m_canChangeNet = aCanChangeNet;
133 m_valid = true;
134 m_dirty = true;
135 m_anchors.reserve( std::max( 6, aAnchorCount ) );
136 m_start_layer = 0;
137 m_end_layer = std::numeric_limits<int>::max();
138 m_connected.reserve( 8 );
139 }
140
141 virtual ~CN_ITEM()
142 {
143 for( const std::shared_ptr<CN_ANCHOR>& anchor : m_anchors )
144 anchor->SetItem( nullptr );
145 };
146
147 std::shared_ptr<CN_ANCHOR> AddAnchor( const VECTOR2I& aPos )
148 {
149 m_anchors.emplace_back( std::make_shared<CN_ANCHOR>( aPos, this ) );
150 return m_anchors.at( m_anchors.size() - 1 );
151 }
152
153 std::vector<std::shared_ptr<CN_ANCHOR>>& Anchors() { return m_anchors; }
154
155 void SetValid( bool aValid ) { m_valid = aValid; }
156 bool Valid() const { return m_valid; }
157
158 void SetDirty( bool aDirty ) { m_dirty.store( aDirty, std::memory_order_release ); }
159 bool Dirty() const { return m_dirty.load( std::memory_order_acquire ); }
160
164 void SetLayers( int aStartLayer, int aEndLayer )
165 {
166 // Copper layer ids do not run in stack order, so store the ordinal. The R-tree keys
167 // on this, and an ordinal keeps a through item's span 31 wide rather than INT_MAX
168 // wide. A span that large overflows the int64 volume the tree splits on, which
169 // wrecks the split and leaves queries walking most of the tree.
170 m_start_layer = static_cast<int>( CopperLayerToOrdinal( ToLAYER_ID( aStartLayer ) ) );
171 m_end_layer = static_cast<int>( CopperLayerToOrdinal( ToLAYER_ID( aEndLayer ) ) );
172 }
173
177 void SetLayer( int aLayer ) { SetLayers( aLayer, aLayer ); }
178
182 int StartLayer() const { return m_start_layer; }
183 int EndLayer() const { return m_end_layer; }
184
189 virtual int Layer() const
190 {
191 return StartLayer();
192 }
193
195 static PCB_LAYER_ID BoardLayerFromOrdinal( int aOrdinal )
196 {
197 if( aOrdinal <= 0 )
198 return F_Cu;
199
200 if( aOrdinal >= MAX_CU_LAYERS - 1 )
201 return B_Cu;
202
203 return ToLAYER_ID( B_Cu + 2 * aOrdinal );
204 }
205
208
209 const BOX2I& BBox()
210 {
211 if( m_dirty.load( std::memory_order_acquire ) && m_valid )
212 {
213 std::lock_guard<std::mutex> lock( m_listLock );
214
215 if( m_dirty.load( std::memory_order_relaxed ) && m_valid )
216 {
217 m_bbox = m_parent->GetBoundingBox();
218 m_dirty.store( false, std::memory_order_release );
219 }
220 }
221
222 return m_bbox;
223 }
224
226
227 const std::vector<CN_ITEM*>& ConnectedItems() const { return m_connected; }
228 void ClearConnections() { m_connected.clear(); }
229
230 bool CanChangeNet() const { return m_canChangeNet; }
231
232 void Connect( CN_ITEM* b )
233 {
234 std::lock_guard<std::mutex> lock( m_listLock );
235
236 auto i = std::lower_bound( m_connected.begin(), m_connected.end(), b );
237
238 if( i != m_connected.end() && *i == b )
239 return;
240
241 m_connected.insert( i, b );
242 }
243
244 void RemoveInvalidRefs();
245
246 virtual int AnchorCount() const;
247 virtual const VECTOR2I GetAnchor( int n ) const;
248
249 int Net() const
250 {
251 return ( !m_parent || !m_valid ) ? -1 : m_parent->GetNetCode();
252 }
253
259 void SetListIndex( int aIndex ) { m_listIndex = aIndex; }
260 int ListIndex() const { return m_listIndex; }
261
262protected:
263 std::atomic<bool> m_dirty;
268
269private:
271
272 std::vector<CN_ITEM*> m_connected;
273 std::vector<std::shared_ptr<CN_ANCHOR>> m_anchors;
274
276
277 bool m_valid;
278
279 int m_listIndex = -1;
280
281 std::mutex m_listLock;
282};
283
284
285/*
286 * Represents a single outline of a zone fill on a particular layer. \a aSubpolyIndex indicates
287 * which outline in the fill's SHAPE_POLY_SET.
288 */
289class CN_ZONE_LAYER : public CN_ITEM
290{
292
293public:
294 CN_ZONE_LAYER( ZONE* aParent, PCB_LAYER_ID aLayer, int aSubpolyIndex ) :
295 CN_ITEM( aParent, false ),
296 m_zone( aParent ),
297 m_subpolyIndex( aSubpolyIndex ),
298 m_layer( aLayer )
299 {
300 std::shared_ptr<SHAPE_POLY_SET> fillPoly = aParent->GetFilledPolysList( aLayer );
301
302 if( fillPoly && aSubpolyIndex < fillPoly->OutlineCount() )
303 m_outline = fillPoly->Outline( aSubpolyIndex );
304
305 SetLayers( aLayer, aLayer );
306 }
307
309 {
310 if( m_zone->IsTeardropArea() )
311 return;
312
313 m_triangulatedPolys.clear();
314 m_rTree = TRI_RTREE();
315
316 std::shared_ptr<SHAPE_POLY_SET> fillPoly = m_zone->GetFilledPolysList( m_layer );
317
318 if( !fillPoly )
319 return;
320
321 size_t triangleCount = 0;
322
323 for( unsigned int ii = 0; ii < fillPoly->TriangulatedPolyCount(); ++ii )
324 {
325 const auto* triangleSet = fillPoly->TriangulatedPolygon( ii );
326
327 if( triangleSet->GetSourceOutlineIndex() != m_subpolyIndex )
328 continue;
329
330 // Deep copy the triangulated polygon. The copy constructor copies the vertex storage
331 // and updates all TRI parent pointers to reference our owned copy. This ensures the
332 // triangles remain valid even if the zone is refilled on another thread.
333 m_triangulatedPolys.push_back(
334 std::make_unique<SHAPE_POLY_SET::TRIANGULATED_POLYGON>( *triangleSet ) );
335
336 triangleCount += m_triangulatedPolys.back()->GetTriangleCount();
337 }
338
339 // A fill is triangulated once and then only queried, so pack the index in one pass
340 // rather than run the R*-tree subtree choice once per triangle
341 TRI_RTREE::Builder builder;
342 builder.Reserve( triangleCount );
343
344 for( const auto& triPoly : m_triangulatedPolys )
345 {
346 const std::deque<VECTOR2I>& verts = triPoly->Vertices();
347
348 for( const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI& tri : triPoly->Triangles() )
349 {
350 const VECTOR2I& va = verts[tri.a];
351 const VECTOR2I& vb = verts[tri.b];
352 const VECTOR2I& vc = verts[tri.c];
353
354 // The box TRI::BBox() returns, without its out-of-line virtual call
355 const int mmin[2] = { std::min( { va.x, vb.x, vc.x } ),
356 std::min( { va.y, vb.y, vc.y } ) };
357 const int mmax[2] = { std::max( { va.x, vb.x, vc.x } ),
358 std::max( { va.y, vb.y, vc.y } ) };
359
360 builder.Add( mmin, mmax, &tri );
361 }
362 }
363
364 m_rTree = builder.Build();
365 }
366
367 int SubpolyIndex() const { return m_subpolyIndex; }
368
369 PCB_LAYER_ID GetLayer() const { return m_layer; }
370
371 bool ContainsPoint( const VECTOR2I& p ) const
372 {
373 if( m_outline.PointCount() == 0 )
374 return false;
375
376 if( m_zone->IsTeardropArea() )
377 return m_outline.Collide( p );
378
379 int min[2] = { p.x, p.y };
380 int max[2] = { p.x, p.y };
381 bool collision = false;
382
383 auto visitor =
384 [&]( const SHAPE* aShape ) -> bool
385 {
386 if( aShape->Collide( p ) )
387 {
388 collision = true;
389 return false;
390 }
391
392 return true;
393 };
394
395 m_rTree.Search( min, max, visitor );
396
397 return collision;
398 }
399
401
402 virtual int AnchorCount() const override;
403 virtual const VECTOR2I GetAnchor( int n ) const override;
404
405 bool HasValidOutline() const
406 {
407 return m_outline.PointCount() > 0;
408 }
409
411 {
412 return m_outline;
413 }
414
416 {
417 return m_outline.PointCount();
418 }
419
420 const VECTOR2I& OutlinePoint( int aIndex ) const
421 {
422 return m_outline.CPoint( aIndex );
423 }
424
425 bool Collide( SHAPE* aRefShape ) const
426 {
427 if( m_outline.PointCount() == 0 )
428 return false;
429
430 if( m_zone->IsTeardropArea() )
431 return aRefShape->Collide( &m_outline, 0 );
432
433 BOX2I bbox = aRefShape->BBox();
434 int min[2] = { bbox.GetX(), bbox.GetY() };
435 int max[2] = { bbox.GetRight(), bbox.GetBottom() };
436 bool collision = false;
437
438 auto visitor =
439 [&]( const SHAPE* aShape ) -> bool
440 {
441 if( aRefShape->Collide( aShape ) )
442 {
443 collision = true;
444 return false;
445 }
446
447 return true;
448 };
449
450 m_rTree.Search( min, max, visitor );
451
452 return collision;
453 }
454
455 bool HasSingleConnection();
456
457private:
463 std::vector<std::unique_ptr<SHAPE_POLY_SET::TRIANGULATED_POLYGON>> m_triangulatedPolys;
465};
466
467
468
469
471{
472public:
474 {
475 m_dirty = false;
476 m_hasInvalid = false;
477 }
478
479 void Clear()
480 {
481 for( CN_ITEM* item : m_items )
482 delete item;
483
484 m_items.clear();
485 m_index.RemoveAll();
486 m_bulkAdd = false;
487 }
488
498 {
499 if( !m_items.empty() || m_hasInvalid )
500 return false;
501
502 m_bulkAdd = true;
503 return true;
504 }
505
508 {
509 if( !m_bulkAdd )
510 return;
511
512 m_bulkAdd = false;
513
514 std::vector<CN_RTREE<CN_ITEM*>::BULK_ENTRY> entries;
515 entries.reserve( m_items.size() );
516
517 for( CN_ITEM* item : m_items )
518 {
519 // BBox() clears the dirty flag that Add() deliberately leaves set
520 bool dirty = item->Dirty();
521 const BOX2I& bbox = item->BBox();
522
523 entries.push_back( { { item->StartLayer(), bbox.GetX(), bbox.GetY() },
524 { item->EndLayer(), bbox.GetRight(), bbox.GetBottom() },
525 item } );
526
527 item->SetDirty( dirty );
528 }
529
530 m_index.BulkLoad( entries );
531 }
532
540 {
541 public:
542 explicit BULK_ADD_SCOPE( CN_LIST& aList ) : m_list( aList ) { m_list.StartBulkAdd(); }
543 ~BULK_ADD_SCOPE() { m_list.FinishBulkAdd(); }
544
545 BULK_ADD_SCOPE( const BULK_ADD_SCOPE& ) = delete;
547
548 private:
550 };
551
552 std::vector<CN_ITEM*>::iterator begin() { return m_items.begin(); };
553 std::vector<CN_ITEM*>::iterator end() { return m_items.end(); };
554
555 std::vector<CN_ITEM*>::const_iterator begin() const { return m_items.begin(); }
556 std::vector<CN_ITEM*>::const_iterator end() const { return m_items.end(); }
557
558 CN_ITEM* operator[] ( int aIndex ) { return m_items[aIndex]; }
559
560 template <class T>
561 void FindNearby( CN_ITEM* aItem, T aFunc )
562 {
563 m_index.Query( aItem->BBox(), aItem->StartLayer(), aItem->EndLayer(), aFunc );
564 }
565
566 void SetHasInvalid( bool aInvalid = true ) { m_hasInvalid = aInvalid; }
567
568 void SetDirty( bool aDirty = true ) { m_dirty = aDirty; }
569 bool IsDirty() const { return m_dirty; }
570
571 void RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage );
572
574 {
575 for( CN_ITEM* item : m_items )
576 item->SetDirty( false );
577
578 SetDirty( false );
579 }
580
581 int Size() const { return m_items.size(); }
582
583 CN_ITEM* Add( PAD* pad );
584 CN_ITEM* Add( PCB_TRACK* track );
585 CN_ITEM* Add( PCB_ARC* track );
586 CN_ITEM* Add( PCB_VIA* via );
587 CN_ITEM* Add( CN_ZONE_LAYER* zitem );
588 CN_ITEM* Add( PCB_SHAPE* shape );
589
590 const std::vector<CN_ITEM*> Add( ZONE* zone, PCB_LAYER_ID aLayer );
591
592protected:
593 void addItemtoTree( CN_ITEM* item )
594 {
595 if( !m_bulkAdd )
596 m_index.Insert( item );
597 }
598
600 void appendItem( CN_ITEM* aItem )
601 {
602 aItem->SetListIndex( static_cast<int>( m_items.size() ) );
603 m_items.push_back( aItem );
604 }
605
606protected:
607 std::vector<CN_ITEM*> m_items;
608
609private:
612 bool m_bulkAdd = false;
614};
615
616
618{
619public:
620 CN_CLUSTER();
621 ~CN_CLUSTER();
622
623 bool HasValidNet() const { return m_originNet > 0; }
624 int OriginNet() const { return m_originNet; }
625
626 wxString OriginNetName() const;
627
628 bool Contains( const CN_ITEM* aItem );
629 bool Contains( const BOARD_CONNECTED_ITEM* aItem );
630 void Dump();
631
632 int Size() const { return m_items.size(); }
633
634 bool IsOrphaned() const
635 {
636 return m_originPad == nullptr;
637 }
638
639 bool IsConflicting() const { return m_conflicting; }
640
641 void Add( CN_ITEM* item );
642
643 std::vector<CN_ITEM*>::iterator begin() { return m_items.begin(); };
644 std::vector<CN_ITEM*>::iterator end() { return m_items.end(); };
645
646private:
650 std::vector<CN_ITEM*> m_items;
651 std::unordered_map<int, int> m_netRanks;
652};
653
654
655
656#endif /* PCBNEW_CONNECTIVITY_ITEMS_H */
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
constexpr coord_type GetY() const
Definition box2.h:205
constexpr coord_type GetX() const
Definition box2.h:204
constexpr coord_type GetRight() const
Definition box2.h:214
constexpr coord_type GetBottom() const
Definition box2.h:219
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 Connect(CN_ITEM *b)
virtual ~CN_ITEM()
const BOX2I & BBox()
virtual int AnchorCount() const
void RemoveInvalidRefs()
std::vector< CN_ITEM * > m_connected
list of physically touching items
int ListIndex() const
const std::vector< CN_ITEM * > & ConnectedItems() const
int m_listIndex
position in the owning CN_LIST, see SetListIndex()
int Net() const
int m_start_layer
start layer of the item N.B. B_Cu is set to INT_MAX
void SetValid(bool aValid)
std::atomic< bool > m_dirty
used to identify recently added item not yet scanned into the connectivity search
BOARD_CONNECTED_ITEM * m_parent
int m_end_layer
end layer of the item N.B. B_Cu is set to INT_MAX
bool Valid() const
int StartLayer() const
Return the contiguous set of layers spanned by the item.
static PCB_LAYER_ID BoardLayerFromOrdinal(int aOrdinal)
std::shared_ptr< CN_ANCHOR > AddAnchor(const VECTOR2I &aPos)
void SetLayers(int aStartLayer, int aEndLayer)
Set the layers spanned by the item to aStartLayer and aEndLayer.
void ClearConnections()
BOX2I m_bbox
bounding box for the item
virtual const VECTOR2I GetAnchor(int n) const
PCB_LAYER_ID GetBoardLayer() const
bool m_canChangeNet
can the net propagator modify the netcode?
void SetDirty(bool aDirty)
bool CanChangeNet() const
void SetListIndex(int aIndex)
Position of this item in its owning CN_LIST.
CN_ITEM(BOARD_CONNECTED_ITEM *aParent, bool aCanChangeNet, int aAnchorCount=2)
int EndLayer() const
void SetLayer(int aLayer)
Set the layers spanned by the item to a single layer aLayer.
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
std::mutex m_listLock
mutex protecting this item's connected_items set to
BULK_ADD_SCOPE(const BULK_ADD_SCOPE &)=delete
BULK_ADD_SCOPE & operator=(const BULK_ADD_SCOPE &)=delete
CN_RTREE< CN_ITEM * > m_index
void appendItem(CN_ITEM *aItem)
void FinishBulkAdd()
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)
bool StartBulkAdd()
Defer spatial indexing until FinishBulkAdd(), which packs the index in one pass.
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)
The sole place CN_ITEM list numbering is assigned.
void SetHasInvalid(bool aInvalid=true)
bool m_bulkAdd
see StartBulkAdd()
void RemoveInvalidItems(std::vector< CN_ITEM * > &aGarbage)
CN_RTREE - Implements an R-tree for fast spatial indexing of connectivity items.
virtual int AnchorCount() const override
const SHAPE_LINE_CHAIN & GetOutline() const
CN_ZONE_LAYER(ZONE *aParent, PCB_LAYER_ID aLayer, int aSubpolyIndex)
std::vector< std::unique_ptr< SHAPE_POLY_SET::TRIANGULATED_POLYGON > > m_triangulatedPolys
virtual const VECTOR2I GetAnchor(int n) const override
const VECTOR2I & OutlinePoint(int aIndex) const
PCB_LAYER_ID GetLayer() const
bool Collide(SHAPE *aRefShape) const
int SubpolyIndex() const
int OutlinePointCount() const
PCB_LAYER_ID m_layer
SHAPE_LINE_CHAIN m_outline
Cached copy of the zone outline.
KIRTREE::PACKED_RTREE< const SHAPE *, int, 2 > TRI_RTREE
PCB_LAYER_ID GetLayer()
bool ContainsPoint(const VECTOR2I &p) const
bool HasValidOutline() const
Static (immutable) packed R-tree built via Hilbert-curve bulk loading.
Definition pad.h:61
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:124
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:179
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:70
std::shared_ptr< SHAPE_POLY_SET > GetFilledPolysList(PCB_LAYER_ID aLayer) const
Definition zone.h:692
#define MAX_CU_LAYERS
Definition layer_ids.h:172
size_t CopperLayerToOrdinal(PCB_LAYER_ID aLayer)
Converts KiCad copper layer enum to an ordinal between the front and back layers.
Definition layer_ids.h:945
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ B_Cu
Definition layer_ids.h:61
@ F_Cu
Definition layer_ids.h:60
PCB_LAYER_ID ToLAYER_ID(int aLayer)
Definition lset.cpp:750
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683