33 #include <unordered_set> 37 #include <geometry/rtree.h> 54 std::shared_ptr<SHAPE> aParentShape =
nullptr ) :
67 using drc_rtree = RTree<ITEM_WITH_SHAPE*, int, 2, double>;
83 for(
auto el : *tree )
97 if( aItem->
Type() ==
PCB_FP_TEXT_T && !static_cast<FP_TEXT*>( aItem )->IsVisible() )
100 std::vector<SHAPE*> subshapes;
104 if( shape->HasIndexableSubshapes() )
105 shape->GetIndexableSubshapes( subshapes );
107 subshapes.push_back( shape.get() );
111 PAD*
pad = static_cast<PAD*>( aItem );
113 if(
pad->GetDrillSizeX() )
115 const SHAPE* hole =
pad->GetEffectiveHoleShape();
116 subshapes.push_back( const_cast<SHAPE*>( hole ) );
120 for(
SHAPE* subshape : subshapes )
122 BOX2I bbox = subshape->BBox();
124 bbox.
Inflate( aWorstClearance );
126 const int mmin[2] = { bbox.
GetX(), bbox.
GetY() };
130 m_tree[aLayer]->Insert( mmin, mmax, itemShape );
147 std::function<
bool(
BOARD_ITEM*)> aFilter =
nullptr )
const 152 int min[2] = { box.
GetX(), box.
GetY() };
160 if( !aFilter || aFilter( aItem->parent ) )
164 if( aRefShape->
Collide( aItem->shape, aClearance, &actual ) )
174 this->
m_tree[aTargetLayer]->Search( min, max, visit );
186 std::function<
bool(
BOARD_ITEM* )> aFilter =
nullptr,
187 std::function<
bool(
BOARD_ITEM* )> aVisitor =
nullptr,
188 int aClearance = 0 )
const 193 std::unordered_set<BOARD_ITEM*> collidingCompounds;
197 std::map<BOARD_ITEM*, bool> filterResults;
202 int min[2] = { box.
GetX(), box.
GetY() };
212 if( aItem->parent == aRefItem )
215 if( collidingCompounds.find( aItem->parent ) != collidingCompounds.end() )
219 auto it = filterResults.find( aItem->parent );
221 if( it == filterResults.end() )
223 filtered = aFilter && !aFilter( aItem->parent );
224 filterResults[ aItem->parent ] = filtered;
228 filtered = it->second;
234 if( refShape->Collide( aItem->shape, aClearance ) )
236 collidingCompounds.insert( aItem->parent );
240 return aVisitor( aItem->parent );
246 this->
m_tree[aTargetLayer]->Search( min, max, visit );
257 int* aActual,
VECTOR2I* aPos )
const 261 int min[2] = { aBox.
GetX(), aBox.
GetY() };
264 bool collision =
false;
265 int actual = INT_MAX;
274 if( aRefShape->
Collide( aItem->shape, aClearance, &curActual, &curPos ) )
278 if( curActual < actual )
292 this->
m_tree[aLayer]->Search( min, max, visit );
297 *aActual = std::max( 0, actual );
313 SHAPE_POLY_SET* poly = dynamic_cast<SHAPE_POLY_SET*>( aRefShape );
315 int min[2] = { aBox.
GetX(), aBox.
GetY() };
317 bool collision =
false;
325 SHAPE* shape = aItem->shape;
326 wxASSERT( dynamic_cast<SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI*>( shape ) );
327 auto tri = static_cast<SHAPE_POLY_SET::TRIANGULATED_POLYGON::TRI*>( shape );
334 || tri->PointInside( outline.
CPoint( 0 ) ) )
346 if( aRefShape->
Collide( aItem->shape, 0 ) )
356 this->
m_tree[aLayer]->Search( min, max, polyVisitor );
358 this->
m_tree[aLayer]->Search( min, max, visitor );
379 std::vector<LAYER_PAIR> aLayerPairs,
382 bool* aCollision )> aVisitor,
384 std::function<
bool(
int,
int )> aProgressReporter )
const 386 std::vector<PAIR_INFO> pairsToVisit;
395 BOX2I box = refItem->shape->BBox();
398 int min[2] = { box.
GetX(), box.
GetY() };
405 if( aItemToTest->parent == refItem->parent )
408 pairsToVisit.emplace_back( layerPair, refItem, aItemToTest );
412 this->
m_tree[targetLayer]->Search( min, max, visit );
419 std::map< std::pair<BOARD_ITEM*, BOARD_ITEM*>,
int> collidingCompounds;
422 int count = pairsToVisit.size();
424 for(
const PAIR_INFO& pair : pairsToVisit )
426 if( !aProgressReporter( progress++, count ) )
433 if( static_cast<void*>( a ) > static_cast<void*>( b ) )
437 if( collidingCompounds.count( { a, b } ) )
440 bool collisionDetected =
false;
442 if( !aVisitor( pair.layerPair, pair.refItem, pair.testItem, &collisionDetected ) )
445 if( collisionDetected )
446 collidingCompounds[ { a, b } ] = 1;
481 m_rect = { { INT_MIN, INT_MIN }, { INT_MAX, INT_MAX } };
511 EDA_RECT rect( aPoint, wxSize( 0, 0 ) );
ITEM_WITH_SHAPE(BOARD_ITEM *aParent, SHAPE *aShape, std::shared_ptr< SHAPE > aParentShape=nullptr)
int OutlineCount() const
Return the number of vertices in a given outline/hole.
class FP_TEXT, text in a footprint
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
coord_type GetRight() const
DRC_LAYER(drc_rtree *aTree)
class PAD, a pad in a footprint
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > LAYER_PAIR
coord_type GetBottom() const
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.
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,...
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const EDA_RECT &aRect) const
RTree< ITEM_WITH_SHAPE *, int, 2, double > drc_rtree
DRC_LAYER(drc_rtree *aTree, const EDA_RECT aRect)
The DRC_LAYER struct provides a layer-specific auto-range iterator to the RTree.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const wxPoint &aPoint, int aAccuracy=0) const
bool CheckColliding(SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
size_t size() const
Return the number of items in the tree.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
drc_rtree * m_tree[PCB_LAYER_ID_COUNT]
std::shared_ptr< SHAPE > parentShape
ITEM_WITH_SHAPE * testItem
ITEM_WITH_SHAPE * refItem
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.
void clear()
Remove all items from the RTree.
static LSET AllLayersMask()
An abstract shape on 2D plane.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
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
PAIR_INFO(LAYER_PAIR aPair, ITEM_WITH_SHAPE *aRef, ITEM_WITH_SHAPE *aTest)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
PCB_LAYER_ID
A quick note on layer IDs:
Handle the component boundary box.
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.
virtual const EDA_RECT GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Implement an R-tree for fast spatial and layer indexing of connectable items.
typename drc_rtree::Iterator iterator
bool QueryColliding(EDA_RECT aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer, int aClearance, int *aActual, VECTOR2I *aPos) const
This one is for tessellated items.
bool QueryColliding(EDA_RECT aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer) const
Quicker version of above that just reports a raw yes/no.
PCB_LAYER_ID ToLAYER_ID(int aLayer)
EDA_RECT & Inflate(wxCoord dx, wxCoord dy)
Inflate the rectangle horizontally by dx and vertically by dy.
KICAD_T Type() const
Returns the type of object.
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.
DRC_LAYER OnLayer(PCB_LAYER_ID aLayer) const