KiCad PCB EDA Suite
DRC_RTREE Class Reference

Implement an R-tree for fast spatial and layer indexing of connectable items. More...

#include <drc_rtree.h>

Classes

struct  DRC_LAYER
 The DRC_LAYER struct provides a layer-specific auto-range iterator to the RTree. More...
 
struct  ITEM_WITH_SHAPE
 
struct  PAIR_INFO
 

Public Types

typedef std::pair< PCB_LAYER_ID, PCB_LAYER_IDLAYER_PAIR
 
using iterator = typename drc_rtree::Iterator
 

Public Member Functions

 DRC_RTREE ()
 
 ~DRC_RTREE ()
 
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. More...
 
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. More...
 
void clear ()
 Remove all items from the RTree. More...
 
bool CheckColliding (SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
 
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. More...
 
bool QueryColliding (const BOX2I &aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer, int aClearance, int *aActual, VECTOR2I *aPos) const
 This one is for tessellated items. More...
 
bool QueryColliding (const BOX2I &aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer) const
 Quicker version of above that just reports a raw yes/no. More...
 
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. More...
 
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
 
size_t size () const
 Return the number of items in the tree. More...
 
bool empty () const
 
DRC_LAYER OnLayer (PCB_LAYER_ID aLayer) const
 
DRC_LAYER Overlapping (PCB_LAYER_ID aLayer, const VECTOR2I &aPoint, int aAccuracy=0) const
 
DRC_LAYER Overlapping (PCB_LAYER_ID aLayer, const BOX2I &aRect) const
 

Private Types

using drc_rtree = RTree< ITEM_WITH_SHAPE *, int, 2, double >
 

Private Attributes

drc_rtreem_tree [PCB_LAYER_ID_COUNT]
 
size_t m_count
 

Detailed Description

Implement an R-tree for fast spatial and layer indexing of connectable items.

Non-owning.

Definition at line 47 of file drc_rtree.h.

Member Typedef Documentation

◆ drc_rtree

using DRC_RTREE::drc_rtree = RTree<ITEM_WITH_SHAPE*, int, 2, double>
private

Definition at line 78 of file drc_rtree.h.

◆ iterator

using DRC_RTREE::iterator = typename drc_rtree::Iterator

Definition at line 517 of file drc_rtree.h.

◆ LAYER_PAIR

Definition at line 415 of file drc_rtree.h.

Constructor & Destructor Documentation

◆ DRC_RTREE()

DRC_RTREE::DRC_RTREE ( )
inline

Definition at line 82 of file drc_rtree.h.

83 {
84 for( int layer : LSET::AllLayersMask().Seq() )
85 m_tree[layer] = new drc_rtree();
86
87 m_count = 0;
88 }
RTree< ITEM_WITH_SHAPE *, int, 2, double > drc_rtree
Definition: drc_rtree.h:78
drc_rtree * m_tree[PCB_LAYER_ID_COUNT]
Definition: drc_rtree.h:573
size_t m_count
Definition: drc_rtree.h:574
static LSET AllLayersMask()
Definition: lset.cpp:808

References LSET::AllLayersMask(), m_count, and m_tree.

◆ ~DRC_RTREE()

DRC_RTREE::~DRC_RTREE ( )
inline

Definition at line 90 of file drc_rtree.h.

91 {
92 for( drc_rtree* tree : m_tree )
93 {
94 for( DRC_RTREE::ITEM_WITH_SHAPE* el : *tree )
95 delete el;
96
97 delete tree;
98 }
99 }

References m_tree.

Member Function Documentation

◆ CheckColliding()

bool DRC_RTREE::CheckColliding ( SHAPE aRefShape,
PCB_LAYER_ID  aTargetLayer,
int  aClearance = 0,
std::function< bool(BOARD_ITEM *)>  aFilter = nullptr 
) const
inline

Definition at line 174 of file drc_rtree.h.

176 {
177 BOX2I box = aRefShape->BBox();
178 box.Inflate( aClearance );
179
180 int min[2] = { box.GetX(), box.GetY() };
181 int max[2] = { box.GetRight(), box.GetBottom() };
182
183 int count = 0;
184
185 auto visit =
186 [&] ( ITEM_WITH_SHAPE* aItem ) -> bool
187 {
188 if( !aFilter || aFilter( aItem->parent ) )
189 {
190 int actual;
191
192 if( aRefShape->Collide( aItem->shape, aClearance, &actual ) )
193 {
194 count++;
195 return false;
196 }
197 }
198
199 return true;
200 };
201
202 this->m_tree[aTargetLayer]->Search( min, max, visit );
203 return count > 0;
204 }
coord_type GetY() const
Definition: box2.h:181
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
coord_type GetX() const
Definition: box2.h:180
coord_type GetRight() const
Definition: box2.h:189
coord_type GetBottom() const
Definition: box2.h:190
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:178
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.

References SHAPE::BBox(), SHAPE::Collide(), BOX2< Vec >::GetBottom(), BOX2< Vec >::GetRight(), BOX2< Vec >::GetX(), BOX2< Vec >::GetY(), BOX2< Vec >::Inflate(), and m_tree.

Referenced by extractDiffPairCoupledItems().

◆ clear()

void DRC_RTREE::clear ( )
inline

Remove all items from the RTree.

Definition at line 166 of file drc_rtree.h.

167 {
168 for( auto tree : m_tree )
169 tree->RemoveAll();
170
171 m_count = 0;
172 }

References m_count, and m_tree.

Referenced by DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run(), and DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run().

◆ empty()

bool DRC_RTREE::empty ( ) const
inline

Definition at line 512 of file drc_rtree.h.

513 {
514 return m_count == 0;
515 }

References m_count.

◆ GetObjectsAt()

std::unordered_set< BOARD_ITEM * > DRC_RTREE::GetObjectsAt ( const VECTOR2I aPt,
PCB_LAYER_ID  aLayer,
int  aClearance = 0 
)
inline

Gets the BOARD_ITEMs that overlap the specified point/layer.

Parameters
aPtPosition on the tree
aLayerLayer to search
Returns
vector of overlapping BOARD_ITEMS*

Definition at line 396 of file drc_rtree.h.

398 {
399 std::unordered_set<BOARD_ITEM*> retval;
400 int min[2] = { aPt.x - aClearance, aPt.y - aClearance };
401 int max[2] = { aPt.x + aClearance, aPt.y + aClearance };
402
403 auto visitor =
404 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
405 {
406 retval.insert( aItem->parent );
407 return true;
408 };
409
410 m_tree[aLayer]->Search( min, max, visitor );
411
412 return retval;
413 }

References m_tree, VECTOR2< T >::x, and VECTOR2< T >::y.

◆ Insert() [1/2]

void DRC_RTREE::Insert ( BOARD_ITEM aItem,
PCB_LAYER_ID  aLayer,
int  aWorstClearance = 0 
)
inline

Insert an item into the tree on a particular layer with an optional worst clearance.

Definition at line 104 of file drc_rtree.h.

105 {
106 Insert( aItem, aLayer, aLayer, aWorstClearance );
107 }
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

References Insert().

Referenced by TRACKS_CLEANER::cleanup(), Insert(), DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run(), DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run(), DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::Run(), and DRC_TEST_PROVIDER_SILK_CLEARANCE::Run().

◆ Insert() [2/2]

void DRC_RTREE::Insert ( BOARD_ITEM aItem,
PCB_LAYER_ID  aRefLayer,
PCB_LAYER_ID  aTargetLayer,
int  aWorstClearance 
)
inline

Insert an item into the tree on a particular layer with a worst clearance.

Allows the source layer to be different from the tree layer.

Definition at line 113 of file drc_rtree.h.

115 {
116 wxCHECK( aTargetLayer != UNDEFINED_LAYER, /* void */ );
117
118 if( aItem->Type() == PCB_FP_TEXT_T && !static_cast<FP_TEXT*>( aItem )->IsVisible() )
119 return;
120
121 std::vector<const SHAPE*> subshapes;
122 std::shared_ptr<SHAPE> shape = aItem->GetEffectiveShape( aRefLayer );
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( aItem, subshape, shape );
141
142 m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape );
143 m_count++;
144 }
145
146 if( aItem->Type() == PCB_PAD_T && aItem->HasHole() )
147 {
148 std::shared_ptr<SHAPE_SEGMENT> hole = aItem->GetEffectiveHoleShape();
149 BOX2I bbox = hole->BBox();
150
151 bbox.Inflate( aWorstClearance );
152
153 const int mmin[2] = { bbox.GetX(), bbox.GetY() };
154 const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
155 ITEM_WITH_SHAPE* itemShape = new ITEM_WITH_SHAPE( aItem, hole, shape );
156
157 m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape );
158 m_count++;
159
160 }
161 }
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:197
virtual std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const
Definition: board_item.cpp:207
virtual bool HasHole() const
Definition: board_item.h:118
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
virtual bool IsVisible() const
Definition: eda_text.h:126
An abstract shape on 2D plane.
Definition: shape.h:123
@ UNDEFINED_LAYER
Definition: layer_ids.h:60
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_FP_TEXT_T
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92

References BOX2< Vec >::GetBottom(), BOARD_ITEM::GetEffectiveHoleShape(), BOARD_ITEM::GetEffectiveShape(), BOX2< Vec >::GetRight(), BOX2< Vec >::GetX(), BOX2< Vec >::GetY(), BOARD_ITEM::HasHole(), BOX2< Vec >::Inflate(), EDA_TEXT::IsVisible(), m_count, m_tree, PCB_FP_TEXT_T, PCB_PAD_T, EDA_ITEM::Type(), and UNDEFINED_LAYER.

◆ OnLayer()

DRC_LAYER DRC_RTREE::OnLayer ( PCB_LAYER_ID  aLayer) const
inline

Definition at line 554 of file drc_rtree.h.

555 {
556 return DRC_LAYER( m_tree[int( aLayer )] );
557 }

References m_tree.

Referenced by QueryCollidingPairs().

◆ Overlapping() [1/2]

DRC_LAYER DRC_RTREE::Overlapping ( PCB_LAYER_ID  aLayer,
const BOX2I aRect 
) const
inline

Definition at line 566 of file drc_rtree.h.

567 {
568 return DRC_LAYER( m_tree[int( aLayer )], aRect );
569 }

References m_tree.

◆ Overlapping() [2/2]

DRC_LAYER DRC_RTREE::Overlapping ( PCB_LAYER_ID  aLayer,
const VECTOR2I aPoint,
int  aAccuracy = 0 
) const
inline

Definition at line 559 of file drc_rtree.h.

560 {
561 BOX2I rect( aPoint, VECTOR2I( 0, 0 ) );
562 rect.Inflate( aAccuracy );
563 return DRC_LAYER( m_tree[int( aLayer )], rect );
564 }
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618

References BOX2< Vec >::Inflate(), and m_tree.

◆ QueryColliding() [1/3]

int DRC_RTREE::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
inline

This is a fast test which essentially does bounding-box overlap given a worst-case clearance.

It's used when looking up the specific item-to-item clearance might be expensive and should be deferred till we know we have a possible hit.

Definition at line 211 of file drc_rtree.h.

215 {
216 // keep track of BOARD_ITEMs that have already been found to collide (some items might
217 // be built of COMPOUND/triangulated shapes and a single subshape collision means we have
218 // a hit)
219 std::unordered_set<BOARD_ITEM*> collidingCompounds;
220
221 // keep track of results of client filter so we don't ask more than once for compound
222 // shapes
223 std::unordered_map<BOARD_ITEM*, bool> filterResults;
224
225 BOX2I box = aRefItem->GetBoundingBox();
226 box.Inflate( aClearance );
227
228 int min[2] = { box.GetX(), box.GetY() };
229 int max[2] = { box.GetRight(), box.GetBottom() };
230
231 std::shared_ptr<SHAPE> refShape = aRefItem->GetEffectiveShape( aRefLayer );
232
233 int count = 0;
234
235 auto visit =
236 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
237 {
238 if( aItem->parent == aRefItem )
239 return true;
240
241 if( collidingCompounds.find( aItem->parent ) != collidingCompounds.end() )
242 return true;
243
244 bool filtered;
245 auto it = filterResults.find( aItem->parent );
246
247 if( it == filterResults.end() )
248 {
249 filtered = aFilter && !aFilter( aItem->parent );
250 filterResults[ aItem->parent ] = filtered;
251 }
252 else
253 {
254 filtered = it->second;
255 }
256
257 if( filtered )
258 return true;
259
260 if( refShape->Collide( aItem->shape, aClearance ) )
261 {
262 collidingCompounds.insert( aItem->parent );
263 count++;
264
265 if( aVisitor )
266 return aVisitor( aItem->parent );
267 }
268
269 return true;
270 };
271
272 this->m_tree[aTargetLayer]->Search( min, max, visit );
273 return count;
274 }
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition: eda_item.cpp:74

References BOX2< Vec >::GetBottom(), EDA_ITEM::GetBoundingBox(), BOARD_ITEM::GetEffectiveShape(), BOX2< Vec >::GetRight(), BOX2< Vec >::GetX(), BOX2< Vec >::GetY(), BOX2< Vec >::Inflate(), and m_tree.

Referenced by TRACKS_CLEANER::cleanup(), collidesWithArea(), DRC_TEST_PROVIDER_DISALLOW::Run(), DRC_TEST_PROVIDER_HOLE_TO_HOLE::Run(), DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone(), DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testItemAgainstZones(), DRC_TEST_PROVIDER_SOLDER_MASK::testMaskItemAgainstZones(), and CONNECTIVITY_DATA::TestTrackEndpointDangling().

◆ QueryColliding() [2/3]

bool DRC_RTREE::QueryColliding ( const BOX2I aBox,
SHAPE aRefShape,
PCB_LAYER_ID  aLayer 
) const
inline

Quicker version of above that just reports a raw yes/no.

Definition at line 338 of file drc_rtree.h.

339 {
340 SHAPE_POLY_SET* poly = dynamic_cast<SHAPE_POLY_SET*>( aRefShape );
341
342 int min[2] = { aBox.GetX(), aBox.GetY() };
343 int max[2] = { aBox.GetRight(), aBox.GetBottom() };
344 bool collision = false;
345
346 // Special case the polygon case. Otherwise we'll call its Collide() method which will
347 // triangulate it as well and then do triangle/triangle collisions. This ends up being
348 // *much* slower than 4 calls to PointInside().
349 auto polyVisitor =
350 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
351 {
352 const SHAPE* shape = aItem->shape;
353 wxASSERT( dynamic_cast<const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI*>( shape ) );
354 auto tri = static_cast<const SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI*>( shape );
355
356 const SHAPE_LINE_CHAIN& outline = poly->Outline( 0 );
357
358 if( outline.PointInside( tri->GetPoint( 0 ) )
359 || outline.PointInside( tri->GetPoint( 1 ) )
360 || outline.PointInside( tri->GetPoint( 2 ) )
361 || tri->PointInside( outline.CPoint( 0 ) ) )
362 {
363 collision = true;
364 return false;
365 }
366
367 return true;
368 };
369
370 auto visitor =
371 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
372 {
373 if( aRefShape->Collide( aItem->shape, 0 ) )
374 {
375 collision = true;
376 return false;
377 }
378
379 return true;
380 };
381
382 if( poly && poly->OutlineCount() == 1 )
383 this->m_tree[aLayer]->Search( min, max, polyVisitor );
384 else
385 this->m_tree[aLayer]->Search( min, max, visitor );
386
387 return collision;
388 }
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Check if point aP lies inside a polygon (any type) defined by the line chain.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
int OutlineCount() const
Return the number of vertices in a given outline/hole.

References SHAPE::Collide(), SHAPE_LINE_CHAIN::CPoint(), BOX2< Vec >::GetBottom(), BOX2< Vec >::GetRight(), BOX2< Vec >::GetX(), BOX2< Vec >::GetY(), m_tree, SHAPE_POLY_SET::Outline(), SHAPE_POLY_SET::OutlineCount(), and SHAPE_LINE_CHAIN_BASE::PointInside().

◆ QueryColliding() [3/3]

bool DRC_RTREE::QueryColliding ( const BOX2I aBox,
SHAPE aRefShape,
PCB_LAYER_ID  aLayer,
int  aClearance,
int *  aActual,
VECTOR2I aPos 
) const
inline

This one is for tessellated items.

(All shapes in the tree will be from a single BOARD_ITEM.) It checks all items in the bbox overlap to find the minimal actual distance and position.

Definition at line 282 of file drc_rtree.h.

284 {
285 BOX2I bbox = aBox;
286 bbox.Inflate( aClearance );
287
288 int min[2] = { bbox.GetX(), bbox.GetY() };
289 int max[2] = { bbox.GetRight(), bbox.GetBottom() };
290
291 bool collision = false;
292 int actual = INT_MAX;
293 VECTOR2I pos;
294
295 auto visit =
296 [&]( ITEM_WITH_SHAPE* aItem ) -> bool
297 {
298 int curActual;
299 VECTOR2I curPos;
300
301 if( aRefShape->Collide( aItem->shape, aClearance, &curActual, &curPos ) )
302 {
303 collision = true;
304
305 if( curActual < actual )
306 {
307 actual = curActual;
308 pos = curPos;
309 }
310
311 // Stop looking after we have a true collision
312 if( actual <= 0 )
313 return false;
314 }
315
316 return true;
317 };
318
319 this->m_tree[aLayer]->Search( min, max, visit );
320
321 if( collision )
322 {
323 if( aActual )
324 *aActual = std::max( 0, actual );
325
326 if( aPos )
327 *aPos = pos;
328
329 return true;
330 }
331
332 return false;
333 }

References SHAPE::Collide(), BOX2< Vec >::GetBottom(), BOX2< Vec >::GetRight(), BOX2< Vec >::GetX(), BOX2< Vec >::GetY(), BOX2< Vec >::Inflate(), and m_tree.

◆ QueryCollidingPairs()

int DRC_RTREE::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
inline

Definition at line 430 of file drc_rtree.h.

435 {
436 std::vector<PAIR_INFO> pairsToVisit;
437
438 for( LAYER_PAIR& layerPair : aLayerPairs )
439 {
440 const PCB_LAYER_ID refLayer = layerPair.first;
441 const PCB_LAYER_ID targetLayer = layerPair.second;
442
443 for( ITEM_WITH_SHAPE* refItem : aRefTree->OnLayer( refLayer ) )
444 {
445 BOX2I box = refItem->shape->BBox();
446 box.Inflate( aMaxClearance );
447
448 int min[2] = { box.GetX(), box.GetY() };
449 int max[2] = { box.GetRight(), box.GetBottom() };
450
451 auto visit =
452 [&]( ITEM_WITH_SHAPE* aItemToTest ) -> bool
453 {
454 // don't collide items against themselves
455 if( aItemToTest->parent == refItem->parent )
456 return true;
457
458 pairsToVisit.emplace_back( layerPair, refItem, aItemToTest );
459 return true;
460 };
461
462 this->m_tree[targetLayer]->Search( min, max, visit );
463 };
464 }
465
466 // keep track of BOARD_ITEMs pairs that have been already found to collide (some items
467 // might be build of COMPOUND/triangulated shapes and a single subshape collision
468 // means we have a hit)
469 std::unordered_map<PTR_PTR_CACHE_KEY, int> collidingCompounds;
470
471 int progress = 0;
472 int count = pairsToVisit.size();
473
474 for( const PAIR_INFO& pair : pairsToVisit )
475 {
476 if( !aProgressReporter( progress++, count ) )
477 break;
478
479 BOARD_ITEM* a = pair.refItem->parent;
480 BOARD_ITEM* b = pair.testItem->parent;
481
482 // store canonical order so we don't collide in both directions (a:b and b:a)
483 if( static_cast<void*>( a ) > static_cast<void*>( b ) )
484 std::swap( a, b );
485
486 // don't report multiple collisions for compound or triangulated shapes
487 if( collidingCompounds.count( { a, b } ) )
488 continue;
489
490 bool collisionDetected = false;
491
492 if( !aVisitor( pair.layerPair, pair.refItem, pair.testItem, &collisionDetected ) )
493 break;
494
495 if( collisionDetected )
496 collidingCompounds[ { a, b } ] = 1;
497 }
498
499 return 0;
500 }
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:50
DRC_LAYER OnLayer(PCB_LAYER_ID aLayer) const
Definition: drc_rtree.h:554
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > LAYER_PAIR
Definition: drc_rtree.h:415
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:59

References BOX2< Vec >::GetBottom(), BOX2< Vec >::GetRight(), BOX2< Vec >::GetX(), BOX2< Vec >::GetY(), BOX2< Vec >::Inflate(), m_tree, and OnLayer().

Referenced by DRC_TEST_PROVIDER_SILK_CLEARANCE::Run().

◆ size()

size_t DRC_RTREE::size ( ) const
inline

Return the number of items in the tree.

Returns
number of elements in the tree.

Definition at line 507 of file drc_rtree.h.

508 {
509 return m_count;
510 }

References m_count.

Referenced by DRC_TEST_PROVIDER_SILK_CLEARANCE::Run().

Member Data Documentation

◆ m_count

size_t DRC_RTREE::m_count
private

Definition at line 574 of file drc_rtree.h.

Referenced by clear(), DRC_RTREE(), empty(), Insert(), and size().

◆ m_tree


The documentation for this class was generated from the following file: