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 (C) 2020-2022 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 <pad.h>
30#include <pcb_text.h>
31#include <memory>
32#include <unordered_set>
33#include <set>
34#include <vector>
35
36#include <geometry/rtree.h>
37#include <geometry/shape.h>
39#include <math/vector2d.h>
40#include "geometry/shape_null.h"
41#include "board.h"
42
48{
49
50public:
51
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:
77
78 using drc_rtree = RTree<ITEM_WITH_SHAPE*, int, 2, double>;
79
80public:
81
83 {
84 for( int layer : LSET::AllLayersMask().Seq() )
85 m_tree[layer] = new drc_rtree();
86
87 m_count = 0;
88 }
89
91 {
92 for( auto& [_, tree] : m_tree )
93 {
94 for( DRC_RTREE::ITEM_WITH_SHAPE* el : *tree )
95 delete el;
96
97 delete tree;
98 }
99 }
100
104 void Insert( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aWorstClearance = 0 )
105 {
106 Insert( aItem, aLayer, aLayer, aWorstClearance );
107 }
108
113 void Insert( BOARD_ITEM* aItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer,
114 int aWorstClearance )
115 {
116 wxCHECK( aTargetLayer != UNDEFINED_LAYER, /* void */ );
117
118 if( ( aItem->Type() == PCB_FIELD_T || aItem->Type() == PCB_TEXT_T )
119 && !static_cast<PCB_TEXT*>( aItem )->IsVisible() )
120 {
121 return;
122 }
123
124 std::vector<const SHAPE*> subshapes;
125 std::shared_ptr<SHAPE> shape = aItem->GetEffectiveShape( aRefLayer );
126
127 wxCHECK2_MSG( shape, return, wxT( "Item does not have a valid shape for this layer" ) );
128
129 if( shape->HasIndexableSubshapes() )
130 shape->GetIndexableSubshapes( subshapes );
131 else
132 subshapes.push_back( shape.get() );
133
134 for( const SHAPE* subshape : subshapes )
135 {
136 if( dynamic_cast<const SHAPE_NULL*>( subshape ) )
137 continue;
138
139 BOX2I bbox = subshape->BBox();
140
141 bbox.Inflate( aWorstClearance );
142
143 const int mmin[2] = { bbox.GetX(), bbox.GetY() };
144 const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
145 ITEM_WITH_SHAPE* itemShape = new ITEM_WITH_SHAPE( aItem, subshape, shape );
146
147 m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape );
148 m_count++;
149 }
150
151 if( aItem->Type() == PCB_PAD_T && aItem->HasHole() )
152 {
153 std::shared_ptr<SHAPE_SEGMENT> hole = aItem->GetEffectiveHoleShape();
154 BOX2I bbox = hole->BBox();
155
156 bbox.Inflate( aWorstClearance );
157
158 const int mmin[2] = { bbox.GetX(), bbox.GetY() };
159 const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
160 ITEM_WITH_SHAPE* itemShape = new ITEM_WITH_SHAPE( aItem, hole, shape );
161
162 m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape );
163 m_count++;
164 }
165 }
166
170 void clear()
171 {
172 for( auto& [_, tree] : m_tree )
173 tree->RemoveAll();
174
175 m_count = 0;
176 }
177
178 bool CheckColliding( SHAPE* aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance = 0,
179 std::function<bool( BOARD_ITEM*)> aFilter = nullptr ) const
180 {
181 BOX2I box = aRefShape->BBox();
182 box.Inflate( aClearance );
183
184 int min[2] = { box.GetX(), box.GetY() };
185 int max[2] = { box.GetRight(), box.GetBottom() };
186
187 int count = 0;
188
189 auto visit =
190 [&] ( ITEM_WITH_SHAPE* aItem ) -> bool
191 {
192 if( !aFilter || aFilter( aItem->parent ) )
193 {
194 int actual;
195
196 if( aRefShape->Collide( aItem->shape, aClearance, &actual ) )
197 {
198 count++;
199 return false;
200 }
201 }
202
203 return true;
204 };
205
206 if( auto it = m_tree.find( aTargetLayer ); it != m_tree.end() )
207 it->second->Search( min, max, visit );
208
209 return count > 0;
210 }
211
217 int QueryColliding( BOARD_ITEM* aRefItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer,
218 std::function<bool( BOARD_ITEM* )> aFilter = nullptr,
219 std::function<bool( BOARD_ITEM* )> aVisitor = nullptr,
220 int aClearance = 0 ) const
221 {
222 // keep track of BOARD_ITEMs that have already been found to collide (some items might
223 // be built of COMPOUND/triangulated shapes and a single subshape collision means we have
224 // a hit)
225 std::unordered_set<BOARD_ITEM*> collidingCompounds;
226
227 // keep track of results of client filter so we don't ask more than once for compound
228 // shapes
229 std::unordered_map<BOARD_ITEM*, bool> filterResults;
230
231 BOX2I box = aRefItem->GetBoundingBox();
232 box.Inflate( aClearance );
233
234 int min[2] = { box.GetX(), box.GetY() };
235 int max[2] = { box.GetRight(), box.GetBottom() };
236
237 std::shared_ptr<SHAPE> refShape = aRefItem->GetEffectiveShape( aRefLayer );
238
239 int count = 0;
240
241 auto visit =
242 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
243 {
244 if( aItem->parent == aRefItem )
245 return true;
246
247 if( collidingCompounds.find( aItem->parent ) != collidingCompounds.end() )
248 return true;
249
250 bool filtered;
251 auto it = filterResults.find( aItem->parent );
252
253 if( it == filterResults.end() )
254 {
255 filtered = aFilter && !aFilter( aItem->parent );
256 filterResults[ aItem->parent ] = filtered;
257 }
258 else
259 {
260 filtered = it->second;
261 }
262
263 if( filtered )
264 return true;
265
266 wxCHECK( aItem->shape, false );
267
268 if( refShape->Collide( aItem->shape, aClearance ) )
269 {
270 collidingCompounds.insert( aItem->parent );
271 count++;
272
273 if( aVisitor )
274 return aVisitor( aItem->parent );
275 }
276
277 return true;
278 };
279
280 if( auto it = m_tree.find( aTargetLayer ); it != m_tree.end() )
281 it->second->Search( min, max, visit );
282
283 return count;
284 }
285
292 bool QueryColliding( const BOX2I& aBox, SHAPE* aRefShape, PCB_LAYER_ID aLayer, int aClearance,
293 int* aActual, VECTOR2I* aPos ) const
294 {
295 BOX2I bbox = aBox;
296 bbox.Inflate( aClearance );
297
298 int min[2] = { bbox.GetX(), bbox.GetY() };
299 int max[2] = { bbox.GetRight(), bbox.GetBottom() };
300
301 bool collision = false;
302 int actual = INT_MAX;
303 VECTOR2I pos;
304
305 auto visit =
306 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
307 {
308 int curActual;
309 VECTOR2I curPos;
310
311 if( aRefShape->Collide( aItem->shape, aClearance, &curActual, &curPos ) )
312 {
313 collision = true;
314
315 if( curActual < actual )
316 {
317 actual = curActual;
318 pos = curPos;
319 }
320
321 // Stop looking after we have a true collision
322 if( actual <= 0 )
323 return false;
324 }
325
326 return true;
327 };
328
329 if( auto it = m_tree.find( aLayer ); it != m_tree.end() )
330 it->second->Search( min, max, visit );
331
332 if( collision )
333 {
334 if( aActual )
335 *aActual = std::max( 0, actual );
336
337 if( aPos )
338 *aPos = pos;
339
340 return true;
341 }
342
343 return false;
344 }
345
349 bool QueryColliding( const BOX2I& aBox, SHAPE* aRefShape, PCB_LAYER_ID aLayer ) const
350 {
351 SHAPE_POLY_SET* poly = dynamic_cast<SHAPE_POLY_SET*>( aRefShape );
352
353 int min[2] = { aBox.GetX(), aBox.GetY() };
354 int max[2] = { aBox.GetRight(), aBox.GetBottom() };
355 bool collision = false;
356
357 // Special case the polygon case. Otherwise we'll call its Collide() method which will
358 // triangulate it as well and then do triangle/triangle collisions. This ends up being
359 // *much* slower than 3 segment Collide()s and a PointInside().
360 auto polyVisitor =
361 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
362 {
363 const SHAPE* shape = aItem->shape;
364
365 // There are certain degenerate cases that result in empty zone fills, which
366 // will be represented in the rtree with only a root (and no triangles).
367 // https://gitlab.com/kicad/code/kicad/-/issues/18600
368 if( shape->Type() != SH_POLY_SET_TRIANGLE )
369 return true;
370
371 auto tri = static_cast<const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI*>( shape );
372
373 const SHAPE_LINE_CHAIN& outline = poly->Outline( 0 );
374
375 for( int ii = 0; ii < (int) tri->GetSegmentCount(); ++ii )
376 {
377 if( outline.Collide( tri->GetSegment( ii ) ) )
378 {
379 collision = true;
380 return false;
381 }
382 }
383
384 // Also must check for poly being completely inside the triangle
385 if( tri->PointInside( outline.CPoint( 0 ) ) )
386 {
387 collision = true;
388 return false;
389 }
390
391 return true;
392 };
393
394 auto visitor =
395 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
396 {
397 if( aRefShape->Collide( aItem->shape, 0 ) )
398 {
399 collision = true;
400 return false;
401 }
402
403 return true;
404 };
405 auto it = m_tree.find( aLayer );
406
407 if( it == m_tree.end() )
408 return false;
409
410 if( poly && poly->OutlineCount() == 1 && poly->HoleCount( 0 ) == 0 )
411 it->second->Search( min, max, polyVisitor );
412 else
413 it->second->Search( min, max, visitor );
414
415 return collision;
416 }
417
424 std::unordered_set<BOARD_ITEM*> GetObjectsAt( const VECTOR2I& aPt, PCB_LAYER_ID aLayer,
425 int aClearance = 0 )
426 {
427 std::unordered_set<BOARD_ITEM*> retval;
428 int min[2] = { aPt.x - aClearance, aPt.y - aClearance };
429 int max[2] = { aPt.x + aClearance, aPt.y + aClearance };
430
431 auto visitor =
432 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
433 {
434 retval.insert( aItem->parent );
435 return true;
436 };
437
438 m_tree[aLayer]->Search( min, max, visitor );
439
440 return retval;
441 }
442
443 typedef std::pair<PCB_LAYER_ID, PCB_LAYER_ID> LAYER_PAIR;
444
446 {
448 layerPair( aPair ),
449 refItem( aRef ),
450 testItem( aTest )
451 { };
452
456 };
457
458 int QueryCollidingPairs( DRC_RTREE* aRefTree, std::vector<LAYER_PAIR> aLayerPairs,
459 std::function<bool( const LAYER_PAIR&, ITEM_WITH_SHAPE*,
460 ITEM_WITH_SHAPE*, bool* aCollision )> aVisitor,
461 int aMaxClearance,
462 std::function<bool(int, int )> aProgressReporter ) const
463 {
464 std::vector<PAIR_INFO> pairsToVisit;
465
466 for( LAYER_PAIR& layerPair : aLayerPairs )
467 {
468 const PCB_LAYER_ID refLayer = layerPair.first;
469 const PCB_LAYER_ID targetLayer = layerPair.second;
470
471 for( ITEM_WITH_SHAPE* refItem : aRefTree->OnLayer( refLayer ) )
472 {
473 BOX2I box = refItem->shape->BBox();
474 box.Inflate( aMaxClearance );
475
476 int min[2] = { box.GetX(), box.GetY() };
477 int max[2] = { box.GetRight(), box.GetBottom() };
478
479 auto visit =
480 [&]( ITEM_WITH_SHAPE* aItemToTest ) -> bool
481 {
482 // don't collide items against themselves
483 if( aItemToTest->parent == refItem->parent )
484 return true;
485
486 pairsToVisit.emplace_back( layerPair, refItem, aItemToTest );
487 return true;
488 };
489
490 auto it = m_tree.find( targetLayer );
491
492 if( it != m_tree.end() )
493 it->second->Search( min, max, visit );
494 };
495 }
496
497 // keep track of BOARD_ITEMs pairs that have been already found to collide (some items
498 // might be build of COMPOUND/triangulated shapes and a single subshape collision
499 // means we have a hit)
500 std::unordered_map<PTR_PTR_CACHE_KEY, int> collidingCompounds;
501
502 int progress = 0;
503 int count = pairsToVisit.size();
504
505 for( const PAIR_INFO& pair : pairsToVisit )
506 {
507 if( !aProgressReporter( progress++, count ) )
508 break;
509
510 BOARD_ITEM* a = pair.refItem->parent;
511 BOARD_ITEM* b = pair.testItem->parent;
512
513 // store canonical order so we don't collide in both directions (a:b and b:a)
514 if( static_cast<void*>( a ) > static_cast<void*>( b ) )
515 std::swap( a, b );
516
517 // don't report multiple collisions for compound or triangulated shapes
518 if( collidingCompounds.count( { a, b } ) )
519 continue;
520
521 bool collisionDetected = false;
522
523 if( !aVisitor( pair.layerPair, pair.refItem, pair.testItem, &collisionDetected ) )
524 break;
525
526 if( collisionDetected )
527 collidingCompounds[ { a, b } ] = 1;
528 }
529
530 return 0;
531 }
532
538 size_t size() const
539 {
540 return m_count;
541 }
542
543 bool empty() const
544 {
545 return m_count == 0;
546 }
547
548 using iterator = typename drc_rtree::Iterator;
549
559 {
560 DRC_LAYER( drc_rtree* aTree ) : layer_tree( aTree )
561 {
562 m_rect = { { INT_MIN, INT_MIN }, { INT_MAX, INT_MAX } };
563 };
564
565 DRC_LAYER( drc_rtree* aTree, const BOX2I& aRect ) : layer_tree( aTree )
566 {
567 m_rect = { { aRect.GetX(), aRect.GetY() },
568 { aRect.GetRight(), aRect.GetBottom() } };
569 };
570
571 drc_rtree::Rect m_rect;
573
575 {
576 return layer_tree->begin( m_rect );
577 }
578
580 {
581 return layer_tree->end( m_rect );
582 }
583 };
584
586 {
587 auto it = m_tree.find( int( aLayer ) );
588 return it == m_tree.end() ? DRC_LAYER( nullptr ) : DRC_LAYER( it->second );
589 }
590
591 DRC_LAYER Overlapping( PCB_LAYER_ID aLayer, const VECTOR2I& aPoint, int aAccuracy = 0 ) const
592 {
593 BOX2I rect( aPoint, VECTOR2I( 0, 0 ) );
594 rect.Inflate( aAccuracy );
595 auto it = m_tree.find( int( aLayer ) );
596 return it == m_tree.end() ? DRC_LAYER( nullptr ) : DRC_LAYER( it->second, rect );
597 }
598
599 DRC_LAYER Overlapping( PCB_LAYER_ID aLayer, const BOX2I& aRect ) const
600 {
601 auto it = m_tree.find( int( aLayer ) );
602 return it == m_tree.end() ? DRC_LAYER( nullptr ) : DRC_LAYER( it->second, aRect );
603 }
604
605
606private:
607 std::map<int, drc_rtree*> m_tree;
608 size_t m_count;
609};
610
611
612#endif /* DRC_RTREE_H_ */
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
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.
Definition: board_item.cpp:278
virtual std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const
Definition: board_item.cpp:288
virtual bool HasHole() const
Definition: board_item.h:155
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
Implement an R-tree for fast spatial and layer indexing of connectable items.
Definition: drc_rtree.h:48
DRC_LAYER OnLayer(PCB_LAYER_ID aLayer) const
Definition: drc_rtree.h:585
void Insert(BOARD_ITEM *aItem, PCB_LAYER_ID aLayer, int aWorstClearance=0)
Insert an item into the tree on a particular layer with an optional worst clearance.
Definition: drc_rtree.h:104
void Insert(BOARD_ITEM *aItem, PCB_LAYER_ID aRefLayer, PCB_LAYER_ID aTargetLayer, int aWorstClearance)
Insert an item into the tree on a particular layer with a worst clearance.
Definition: drc_rtree.h:113
RTree< ITEM_WITH_SHAPE *, int, 2, double > drc_rtree
Definition: drc_rtree.h:78
size_t size() const
Return the number of items in the tree.
Definition: drc_rtree.h:538
typename drc_rtree::Iterator iterator
Definition: drc_rtree.h:548
bool empty() const
Definition: drc_rtree.h:543
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:217
DRC_RTREE()
Definition: drc_rtree.h:82
bool CheckColliding(SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
Definition: drc_rtree.h:178
~DRC_RTREE()
Definition: drc_rtree.h:90
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const BOX2I &aRect) const
Definition: drc_rtree.h:599
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:424
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:349
void clear()
Remove all items from the RTree.
Definition: drc_rtree.h:170
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > LAYER_PAIR
Definition: drc_rtree.h:443
std::map< int, drc_rtree * > m_tree
Definition: drc_rtree.h:607
size_t m_count
Definition: drc_rtree.h:608
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const VECTOR2I &aPoint, int aAccuracy=0) const
Definition: drc_rtree.h:591
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:458
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:292
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:77
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
virtual bool IsVisible() const
Definition: eda_text.h:174
static LSET AllLayersMask()
Definition: lset.cpp:711
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.
#define _(s)
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:559
iterator begin()
Definition: drc_rtree.h:574
drc_rtree::Rect m_rect
Definition: drc_rtree.h:571
drc_rtree * layer_tree
Definition: drc_rtree.h:572
DRC_LAYER(drc_rtree *aTree)
Definition: drc_rtree.h:560
DRC_LAYER(drc_rtree *aTree, const BOX2I &aRect)
Definition: drc_rtree.h:565
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:454
PAIR_INFO(LAYER_PAIR aPair, ITEM_WITH_SHAPE *aRef, ITEM_WITH_SHAPE *aTest)
Definition: drc_rtree.h:447
ITEM_WITH_SHAPE * testItem
Definition: drc_rtree.h:455
LAYER_PAIR layerPair
Definition: drc_rtree.h:453
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:691