KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_rtree.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 * Copyright (C) 2020 CERN
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-3.0.html
20 * or you may search the http://www.gnu.org website for the version 3 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#ifndef DRC_RTREE_H_
26#define DRC_RTREE_H_
27
28#include <board_item.h>
29#include <pcb_field.h>
30#include <cassert>
31#include <memory>
32#include <unordered_set>
33#include <set>
34#include <vector>
35
37#include <geometry/shape.h>
39#include <math/vector2d.h>
40#include "geometry/shape_null.h"
41#include "board.h"
42
43#define ATOMIC_TABLES true
44
50{
51public:
53 {
54 ITEM_WITH_SHAPE( BOARD_ITEM *aParent, const SHAPE* aShape,
55 std::shared_ptr<SHAPE> aParentShape = nullptr ) :
56 parent( aParent ),
57 shape( aShape ),
58 shapeStorage( nullptr ),
59 parentShape( std::move( aParentShape ) )
60 {};
61
62 ITEM_WITH_SHAPE( BOARD_ITEM *aParent, const std::shared_ptr<SHAPE>& aShape,
63 std::shared_ptr<SHAPE> aParentShape = nullptr ) :
64 parent( aParent ),
65 shape( aShape.get() ),
66 shapeStorage( aShape ),
67 parentShape( std::move( aParentShape ) )
68 {};
69
71 const SHAPE* shape;
72 std::shared_ptr<SHAPE> shapeStorage;
73 std::shared_ptr<SHAPE> parentShape;
74 };
75
76private:
78 using drc_rtree_builder = typename drc_rtree::Builder;
79
80public:
82 {
83 m_count = 0;
84 }
85
87 {
88 for( ITEM_WITH_SHAPE* p : m_owned )
89 delete p;
90 }
91
96 void Insert( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aWorstClearance = 0, bool aAtomicTables = false )
97 {
98 Insert( aItem, aLayer, aLayer, aWorstClearance, aAtomicTables );
99 }
100
105 void Insert( BOARD_ITEM* aItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer,
106 int aWorstClearance, bool aAtomicTables = false )
107 {
108 wxCHECK( aTargetLayer != UNDEFINED_LAYER, /* void */ );
109 assert( !m_tree.count( aTargetLayer ) && "Insert after Build() is silently wrong" );
110
111 if( aItem->Type() == PCB_FIELD_T && !static_cast<PCB_FIELD*>( aItem )->IsVisible() )
112 return;
113
114 BOARD_ITEM* parent = aItem;
115
116 if( aAtomicTables && aItem->Type() == PCB_TABLECELL_T )
117 parent = aItem->GetParent();
118
119 std::vector<const SHAPE*> subshapes;
120 std::shared_ptr<SHAPE> shape = aItem->GetEffectiveShape( aRefLayer );
121
122 wxCHECK2_MSG( shape, return, wxT( "Item does not have a valid shape for this layer" ) );
123
124 if( shape->HasIndexableSubshapes() )
125 shape->GetIndexableSubshapes( subshapes );
126 else
127 subshapes.push_back( shape.get() );
128
129 for( const SHAPE* subshape : subshapes )
130 {
131 if( dynamic_cast<const SHAPE_NULL*>( subshape ) )
132 continue;
133
134 BOX2I bbox = subshape->BBox();
135
136 bbox.Inflate( aWorstClearance );
137
138 const int mmin[2] = { bbox.GetX(), bbox.GetY() };
139 const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
140 ITEM_WITH_SHAPE* itemShape = new ITEM_WITH_SHAPE( parent, subshape, shape );
141
142 m_owned.push_back( itemShape );
143 m_builders[aTargetLayer].Add( mmin, mmax, itemShape );
144 m_count++;
145 }
146
147 if( aItem->Type() == PCB_PAD_T && aItem->HasHole() )
148 {
149 std::shared_ptr<SHAPE_SEGMENT> hole = aItem->GetEffectiveHoleShape();
150 BOX2I bbox = hole->BBox();
151
152 bbox.Inflate( aWorstClearance );
153
154 const int mmin[2] = { bbox.GetX(), bbox.GetY() };
155 const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
156 ITEM_WITH_SHAPE* itemShape = new ITEM_WITH_SHAPE( parent, hole, shape );
157
158 m_owned.push_back( itemShape );
159 m_builders[aTargetLayer].Add( mmin, mmax, itemShape );
160 m_count++;
161 }
162 }
163
168 void Build()
169 {
170 for( auto& [layer, builder] : m_builders )
171 m_tree[layer] = builder.Build();
172
173 m_builders.clear();
174 }
175
179 void clear()
180 {
181 for( ITEM_WITH_SHAPE* p : m_owned )
182 delete p;
183
184 m_owned.clear();
185 m_tree.clear();
186 m_builders.clear();
187 m_count = 0;
188 }
189
190 bool CheckColliding( SHAPE* aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance = 0,
191 std::function<bool( BOARD_ITEM*)> aFilter = nullptr ) const
192 {
193 BOX2I box = aRefShape->BBox();
194 box.Inflate( aClearance );
195
196 int min[2] = { box.GetX(), box.GetY() };
197 int max[2] = { box.GetRight(), box.GetBottom() };
198
199 int count = 0;
200
201 auto visit =
202 [&] ( ITEM_WITH_SHAPE* aItem ) -> bool
203 {
204 if( !aFilter || aFilter( aItem->parent ) )
205 {
206 int actual;
207
208 if( aRefShape->Collide( aItem->shape, aClearance, &actual ) )
209 {
210 count++;
211 return false;
212 }
213 }
214
215 return true;
216 };
217
218 if( auto it = m_tree.find( aTargetLayer ); it != m_tree.end() )
219 it->second.Search( min, max, visit );
220
221 return count > 0;
222 }
223
229 int QueryColliding( BOARD_ITEM* aRefItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer,
230 std::function<bool( BOARD_ITEM* )> aFilter = nullptr,
231 std::function<bool( BOARD_ITEM* )> aVisitor = nullptr,
232 int aClearance = 0 ) const
233 {
234 // keep track of BOARD_ITEMs that have already been found to collide (some items might
235 // be built of COMPOUND/triangulated shapes and a single subshape collision means we have
236 // a hit)
237 std::unordered_set<BOARD_ITEM*> collidingCompounds;
238
239 // keep track of results of client filter so we don't ask more than once for compound
240 // shapes
241 std::unordered_map<BOARD_ITEM*, bool> filterResults;
242
243 BOX2I box = aRefItem->GetBoundingBox();
244 box.Inflate( aClearance );
245
246 int min[2] = { box.GetX(), box.GetY() };
247 int max[2] = { box.GetRight(), box.GetBottom() };
248
249 std::shared_ptr<SHAPE> refShape = aRefItem->GetEffectiveShape( aRefLayer );
250
251 int count = 0;
252
253 auto visit =
254 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
255 {
256 if( aItem->parent == aRefItem )
257 return true;
258
259 if( collidingCompounds.find( aItem->parent ) != collidingCompounds.end() )
260 return true;
261
262 bool filtered;
263 auto it = filterResults.find( aItem->parent );
264
265 if( it == filterResults.end() )
266 {
267 filtered = aFilter && !aFilter( aItem->parent );
268 filterResults[ aItem->parent ] = filtered;
269 }
270 else
271 {
272 filtered = it->second;
273 }
274
275 if( filtered )
276 return true;
277
278 wxCHECK( aItem->shape, false );
279
280 if( refShape->Collide( aItem->shape, aClearance ) )
281 {
282 collidingCompounds.insert( aItem->parent );
283 count++;
284
285 if( aVisitor )
286 return aVisitor( aItem->parent );
287 }
288
289 return true;
290 };
291
292 if( auto it = m_tree.find( aTargetLayer ); it != m_tree.end() )
293 it->second.Search( min, max, visit );
294
295 return count;
296 }
297
304 bool QueryColliding( const BOX2I& aBox, SHAPE* aRefShape, PCB_LAYER_ID aLayer, int aClearance,
305 int* aActual, VECTOR2I* aPos ) const
306 {
307 BOX2I bbox = aBox;
308 bbox.Inflate( aClearance );
309
310 int min[2] = { bbox.GetX(), bbox.GetY() };
311 int max[2] = { bbox.GetRight(), bbox.GetBottom() };
312
313 bool collision = false;
314 int actual = INT_MAX;
315 VECTOR2I pos;
316
317 auto visit =
318 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
319 {
320 int curActual;
321 VECTOR2I curPos;
322
323 if( aRefShape->Collide( aItem->shape, aClearance, &curActual, &curPos ) )
324 {
325 collision = true;
326
327 if( curActual < actual )
328 {
329 actual = curActual;
330 pos = curPos;
331 }
332
333 // Stop looking after we have a true collision
334 if( actual <= 0 )
335 return false;
336 }
337
338 return true;
339 };
340
341 if( auto it = m_tree.find( aLayer ); it != m_tree.end() )
342 it->second.Search( min, max, visit );
343
344 if( collision )
345 {
346 if( aActual )
347 *aActual = std::max( 0, actual );
348
349 if( aPos )
350 *aPos = pos;
351
352 return true;
353 }
354
355 return false;
356 }
357
361 bool QueryColliding( const BOX2I& aBox, SHAPE* aRefShape, PCB_LAYER_ID aLayer ) const
362 {
363 SHAPE_POLY_SET* poly = dynamic_cast<SHAPE_POLY_SET*>( aRefShape );
364
365 int min[2] = { aBox.GetX(), aBox.GetY() };
366 int max[2] = { aBox.GetRight(), aBox.GetBottom() };
367 bool collision = false;
368
369 // Special case the polygon case. Otherwise we'll call its Collide() method which will
370 // triangulate it as well and then do triangle/triangle collisions. This ends up being
371 // *much* slower than 3 segment Collide()s and a PointInside().
372 auto polyVisitor =
373 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
374 {
375 const SHAPE* shape = aItem->shape;
376
377 // There are certain degenerate cases that result in empty zone fills, which
378 // will be represented in the rtree with only a root (and no triangles).
379 // https://gitlab.com/kicad/code/kicad/-/issues/18600
380 if( shape->Type() != SH_POLY_SET_TRIANGLE )
381 return true;
382
383 auto tri = static_cast<const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI*>( shape );
384
385 const SHAPE_LINE_CHAIN& outline = poly->Outline( 0 );
386
387 for( int ii = 0; ii < (int) tri->GetSegmentCount(); ++ii )
388 {
389 if( outline.Collide( tri->GetSegment( ii ) ) )
390 {
391 collision = true;
392 return false;
393 }
394 }
395
396 // Also must check for poly being completely inside the triangle
397 if( tri->PointInside( outline.CPoint( 0 ) ) )
398 {
399 collision = true;
400 return false;
401 }
402
403 return true;
404 };
405
406 auto visitor =
407 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
408 {
409 if( aRefShape->Collide( aItem->shape, 0 ) )
410 {
411 collision = true;
412 return false;
413 }
414
415 return true;
416 };
417
418 auto it = m_tree.find( aLayer );
419
420 if( it == m_tree.end() )
421 return false;
422
423 if( poly && poly->OutlineCount() == 1 && poly->HoleCount( 0 ) == 0 )
424 it->second.Search( min, max, polyVisitor );
425 else
426 it->second.Search( min, max, visitor );
427
428 return collision;
429 }
430
437 std::unordered_set<BOARD_ITEM*> GetObjectsAt( const VECTOR2I& aPt, PCB_LAYER_ID aLayer,
438 int aClearance = 0 )
439 {
440 std::unordered_set<BOARD_ITEM*> retval;
441 int min[2] = { aPt.x - aClearance, aPt.y - aClearance };
442 int max[2] = { aPt.x + aClearance, aPt.y + aClearance };
443
444 auto visitor =
445 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
446 {
447 retval.insert( aItem->parent );
448 return true;
449 };
450
451 auto it = m_tree.find( aLayer );
452
453 if( it != m_tree.end() )
454 it->second.Search( min, max, visitor );
455
456 return retval;
457 }
458
459 typedef std::pair<PCB_LAYER_ID, PCB_LAYER_ID> LAYER_PAIR;
460
462 {
464 layerPair( aPair ),
465 refItem( aRef ),
466 testItem( aTest )
467 { };
468
472 };
473
474 int QueryCollidingPairs( DRC_RTREE* aRefTree, std::vector<LAYER_PAIR> aLayerPairs,
475 std::function<bool( const LAYER_PAIR&, ITEM_WITH_SHAPE*,
476 ITEM_WITH_SHAPE*, bool* aCollision )> aVisitor,
477 int aMaxClearance,
478 std::function<bool(int, int )> aProgressReporter ) const
479 {
480 std::vector<PAIR_INFO> pairsToVisit;
481
482 for( LAYER_PAIR& layerPair : aLayerPairs )
483 {
484 const PCB_LAYER_ID refLayer = layerPair.first;
485 const PCB_LAYER_ID targetLayer = layerPair.second;
486
487 for( ITEM_WITH_SHAPE* refItem : aRefTree->OnLayer( refLayer ) )
488 {
489 BOX2I box = refItem->shape->BBox();
490 box.Inflate( aMaxClearance );
491
492 int min[2] = { box.GetX(), box.GetY() };
493 int max[2] = { box.GetRight(), box.GetBottom() };
494
495 auto visit =
496 [&]( ITEM_WITH_SHAPE* aItemToTest ) -> bool
497 {
498 // don't collide items against themselves
499 if( aItemToTest->parent == refItem->parent )
500 return true;
501
502 pairsToVisit.emplace_back( layerPair, refItem, aItemToTest );
503 return true;
504 };
505
506 auto it = m_tree.find( targetLayer );
507
508 if( it != m_tree.end() )
509 it->second.Search( min, max, visit );
510 };
511 }
512
513 // keep track of BOARD_ITEMs pairs that have been already found to collide (some items
514 // might be build of COMPOUND/triangulated shapes and a single subshape collision
515 // means we have a hit)
516 std::unordered_map<PTR_PTR_CACHE_KEY, int> collidingCompounds;
517
518 int progress = 0;
519 int count = pairsToVisit.size();
520
521 for( const PAIR_INFO& pair : pairsToVisit )
522 {
523 if( !aProgressReporter( progress++, count ) )
524 break;
525
526 BOARD_ITEM* a = pair.refItem->parent;
527 BOARD_ITEM* b = pair.testItem->parent;
528
529 // store canonical order so we don't collide in both directions (a:b and b:a)
530 if( static_cast<void*>( a ) > static_cast<void*>( b ) )
531 std::swap( a, b );
532
533 // don't report multiple collisions for compound or triangulated shapes
534 if( collidingCompounds.count( { a, b } ) )
535 continue;
536
537 bool collisionDetected = false;
538
539 if( !aVisitor( pair.layerPair, pair.refItem, pair.testItem, &collisionDetected ) )
540 break;
541
542 if( collisionDetected )
543 collidingCompounds[ { a, b } ] = 1;
544 }
545
546 return 0;
547 }
548
554 size_t size() const
555 {
556 return m_count;
557 }
558
559 bool empty() const
560 {
561 return m_count == 0;
562 }
563
573 {
574 DRC_LAYER() = default;
575
576 DRC_LAYER( const drc_rtree& aTree )
577 {
578 for( ITEM_WITH_SHAPE* item : aTree )
579 m_items.push_back( item );
580 }
581
582 DRC_LAYER( const drc_rtree& aTree, const BOX2I& aRect )
583 {
584 int min[2] = { aRect.GetX(), aRect.GetY() };
585 int max[2] = { aRect.GetRight(), aRect.GetBottom() };
586
587 auto collector = [this]( ITEM_WITH_SHAPE* aItem ) -> bool
588 {
589 m_items.push_back( aItem );
590 return true;
591 };
592
593 aTree.Search( min, max, collector );
594 }
595
596 std::vector<ITEM_WITH_SHAPE*> m_items;
597
598 std::vector<ITEM_WITH_SHAPE*>::iterator begin() { return m_items.begin(); }
599 std::vector<ITEM_WITH_SHAPE*>::iterator end() { return m_items.end(); }
600 };
601
603 {
604 auto it = m_tree.find( aLayer );
605 return it == m_tree.end() ? DRC_LAYER() : DRC_LAYER( it->second );
606 }
607
608 DRC_LAYER Overlapping( PCB_LAYER_ID aLayer, const VECTOR2I& aPoint, int aAccuracy = 0 ) const
609 {
610 BOX2I rect( aPoint, VECTOR2I( 0, 0 ) );
611 rect.Inflate( aAccuracy );
612 auto it = m_tree.find( aLayer );
613 return it == m_tree.end() ? DRC_LAYER() : DRC_LAYER( it->second, rect );
614 }
615
616 DRC_LAYER Overlapping( PCB_LAYER_ID aLayer, const BOX2I& aRect ) const
617 {
618 auto it = m_tree.find( aLayer );
619 return it == m_tree.end() ? DRC_LAYER() : DRC_LAYER( it->second, aRect );
620 }
621
622
623private:
624 std::map<int, drc_rtree> m_tree;
625 std::map<int, drc_rtree_builder> m_builders;
626 std::vector<ITEM_WITH_SHAPE*> m_owned;
627 size_t m_count = 0;
628};
629
630
631#endif /* DRC_RTREE_H_ */
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:234
virtual std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const
virtual bool HasHole() const
Definition board_item.h:180
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr coord_type GetY() const
Definition box2.h:208
constexpr coord_type GetX() const
Definition box2.h:207
constexpr coord_type GetRight() const
Definition box2.h:217
constexpr coord_type GetBottom() const
Definition box2.h:222
DRC_LAYER OnLayer(PCB_LAYER_ID aLayer) const
Definition drc_rtree.h:602
size_t size() const
Return the number of items in the tree.
Definition drc_rtree.h:554
bool empty() const
Definition drc_rtree.h:559
int QueryColliding(BOARD_ITEM *aRefItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer, std::function< bool(BOARD_ITEM *)> aFilter=nullptr, std::function< bool(BOARD_ITEM *)> aVisitor=nullptr, int aClearance=0) const
This is a fast test which essentially does bounding-box overlap given a worst-case clearance.
Definition drc_rtree.h:229
typename drc_rtree::Builder drc_rtree_builder
Definition drc_rtree.h:78
void Insert(BOARD_ITEM *aItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer, int aWorstClearance, bool aAtomicTables=false)
Insert an item into the tree on a particular layer with a worst clearance.
Definition drc_rtree.h:105
bool CheckColliding(SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
Definition drc_rtree.h:190
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const BOX2I &aRect) const
Definition drc_rtree.h:616
KIRTREE::PACKED_RTREE< ITEM_WITH_SHAPE *, int, 2 > drc_rtree
Definition drc_rtree.h:77
std::unordered_set< BOARD_ITEM * > GetObjectsAt(const VECTOR2I &aPt, PCB_LAYER_ID aLayer, int aClearance=0)
Gets the BOARD_ITEMs that overlap the specified point/layer.
Definition drc_rtree.h:437
bool QueryColliding(const BOX2I &aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer) const
Quicker version of above that just reports a raw yes/no.
Definition drc_rtree.h:361
void clear()
Remove all items from the RTree.
Definition drc_rtree.h:179
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > LAYER_PAIR
Definition drc_rtree.h:459
size_t m_count
Definition drc_rtree.h:627
std::map< int, drc_rtree_builder > m_builders
Definition drc_rtree.h:625
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const VECTOR2I &aPoint, int aAccuracy=0) const
Definition drc_rtree.h:608
int QueryCollidingPairs(DRC_RTREE *aRefTree, std::vector< LAYER_PAIR > aLayerPairs, std::function< bool(const LAYER_PAIR &, ITEM_WITH_SHAPE *, ITEM_WITH_SHAPE *, bool *aCollision)> aVisitor, int aMaxClearance, std::function< bool(int, int)> aProgressReporter) const
Definition drc_rtree.h:474
std::vector< ITEM_WITH_SHAPE * > m_owned
Definition drc_rtree.h:626
void Build()
Finalize all pending inserts by bulk-building packed R-trees from the staged items.
Definition drc_rtree.h:168
bool QueryColliding(const BOX2I &aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer, int aClearance, int *aActual, VECTOR2I *aPos) const
This one is for tessellated items.
Definition drc_rtree.h:304
std::map< int, drc_rtree > m_tree
Definition drc_rtree.h:624
void Insert(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer, int aWorstClearance=0, bool aAtomicTables=false)
Insert an item into the tree on a particular layer with an optional worst clearance.
Definition drc_rtree.h:96
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:120
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:112
virtual bool IsVisible() const
Definition eda_text.h:198
Static (immutable) packed R-tree built via Hilbert-curve bulk loading.
int Search(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS], VISITOR &aVisitor) const
Search for all items whose bounding boxes overlap the query rectangle.
SHAPE_TYPE Type() const
Return the type of the shape.
Definition shape.h:98
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int OutlineCount() const
Return the number of outlines in the set.
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.
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ UNDEFINED_LAYER
Definition layer_ids.h:61
STL namespace.
@ SH_POLY_SET_TRIANGLE
a single triangle belonging to a POLY_SET triangulation
Definition shape.h:56
The DRC_LAYER struct provides a layer-specific auto-range iterator to the RTree.
Definition drc_rtree.h:573
DRC_LAYER(const drc_rtree &aTree, const BOX2I &aRect)
Definition drc_rtree.h:582
DRC_LAYER(const drc_rtree &aTree)
Definition drc_rtree.h:576
std::vector< ITEM_WITH_SHAPE * >::iterator begin()
Definition drc_rtree.h:598
std::vector< ITEM_WITH_SHAPE * > m_items
Definition drc_rtree.h:596
std::vector< ITEM_WITH_SHAPE * >::iterator end()
Definition drc_rtree.h:599
ITEM_WITH_SHAPE(BOARD_ITEM *aParent, const SHAPE *aShape, std::shared_ptr< SHAPE > aParentShape=nullptr)
Definition drc_rtree.h:54
std::shared_ptr< SHAPE > parentShape
Definition drc_rtree.h:73
ITEM_WITH_SHAPE(BOARD_ITEM *aParent, const std::shared_ptr< SHAPE > &aShape, std::shared_ptr< SHAPE > aParentShape=nullptr)
Definition drc_rtree.h:62
std::shared_ptr< SHAPE > shapeStorage
Definition drc_rtree.h:72
ITEM_WITH_SHAPE * refItem
Definition drc_rtree.h:470
PAIR_INFO(LAYER_PAIR aPair, ITEM_WITH_SHAPE *aRef, ITEM_WITH_SHAPE *aTest)
Definition drc_rtree.h:463
ITEM_WITH_SHAPE * testItem
Definition drc_rtree.h:471
LAYER_PAIR layerPair
Definition drc_rtree.h:469
int actual
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:87
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:92
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:84
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687