32#include <unordered_set> 
   36#include <geometry/rtree.h> 
   43#define ATOMIC_TABLES true 
   55                         std::shared_ptr<SHAPE> aParentShape = 
nullptr ) :
 
 
   63                         std::shared_ptr<SHAPE> aParentShape = 
nullptr ) :
 
   65            shape( aShape.get() ),
 
 
 
   77    using drc_rtree = RTree<ITEM_WITH_SHAPE*, int, 2, double>;
 
  104        Insert( aItem, aLayer, aLayer, aWorstClearance, aAtomicTables );
 
 
  112                 int aWorstClearance, 
bool aAtomicTables = 
false )
 
  124        std::vector<const SHAPE*> subshapes;
 
  127        wxCHECK2_MSG( shape, 
return, wxT( 
"Item does not have a valid shape for this layer" ) );
 
  129        if( shape->HasIndexableSubshapes() )
 
  130            shape->GetIndexableSubshapes( subshapes );
 
  132            subshapes.push_back( shape.get() );
 
  134        for( 
const SHAPE* subshape : subshapes )
 
  136            if( 
dynamic_cast<const SHAPE_NULL*
>( subshape ) )
 
  139            BOX2I bbox = subshape->BBox();
 
  141            bbox.
Inflate( aWorstClearance );
 
  143            const int        mmin[2] = { bbox.
GetX(), bbox.
GetY() };
 
  147            m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape );
 
  154            BOX2I                          bbox = hole->BBox();
 
  156            bbox.
Inflate( aWorstClearance );
 
  158            const int        mmin[2] = { bbox.
GetX(), bbox.
GetY() };
 
  162            m_tree[aTargetLayer]->Insert( mmin, mmax, itemShape );
 
 
  172        for( 
auto& [
_, tree] : 
m_tree )
 
 
  179                         std::function<
bool( 
BOARD_ITEM*)> aFilter = 
nullptr )
 const 
  184        int min[2] = { box.
GetX(),         box.
GetY() };
 
  192                    if( !aFilter || aFilter( aItem->parent ) )
 
  196                        if( aRefShape->
Collide( aItem->shape, aClearance, &
actual ) )
 
  206        if( 
auto it = 
m_tree.find( aTargetLayer ); it != 
m_tree.end() )
 
  207            it->second->Search( min, max, visit );
 
 
  218                        std::function<
bool( 
BOARD_ITEM* )> aFilter = 
nullptr,
 
  219                        std::function<
bool( 
BOARD_ITEM* )> aVisitor = 
nullptr,
 
  220                        int aClearance = 0 )
 const 
  225        std::unordered_set<BOARD_ITEM*> collidingCompounds;
 
  229        std::unordered_map<BOARD_ITEM*, bool> filterResults;
 
  234        int min[2] = { box.
GetX(),     box.
GetY() };
 
  244                    if( aItem->parent == aRefItem )
 
  247                    if( collidingCompounds.find( aItem->parent ) != collidingCompounds.end() )
 
  251                    auto it = filterResults.find( aItem->parent );
 
  253                    if( it == filterResults.end() )
 
  255                        filtered = aFilter && !aFilter( aItem->parent );
 
  256                        filterResults[ aItem->parent ] = filtered;
 
  260                        filtered = it->second;
 
  266                    wxCHECK( aItem->shape, 
false );
 
  268                    if( refShape->Collide( aItem->shape, aClearance ) )
 
  270                        collidingCompounds.insert( aItem->parent );
 
  274                            return aVisitor( aItem->parent );
 
  280        if( 
auto it = 
m_tree.find( aTargetLayer ); it != 
m_tree.end() )
 
  281            it->second->Search( min, max, visit );
 
 
  293                         int* aActual, 
VECTOR2I* aPos )
 const 
  298        int min[2] = { bbox.
GetX(), bbox.
GetY() };
 
  301        bool     collision = 
false;
 
  311                    if( aRefShape->
Collide( aItem->shape, aClearance, &curActual, &curPos ) )
 
  329        if( 
auto it = 
m_tree.find( aLayer ); it != 
m_tree.end() )
 
  330            it->second->Search( min, max, visit );
 
  335                *aActual = std::max( 0, 
actual );
 
 
  353        int  min[2] = { aBox.
GetX(), aBox.
GetY() };
 
  355        bool collision = 
false;
 
  363                    const SHAPE* shape = aItem->shape;
 
  375                    for( 
int ii = 0; ii < (int) tri->GetSegmentCount(); ++ii )
 
  377                        if( outline.
Collide( tri->GetSegment( ii ) ) )
 
  385                    if( tri->PointInside( outline.
CPoint( 0 ) ) )
 
  397                    if( aRefShape->
Collide( aItem->shape, 0 ) )
 
  405        auto it = 
m_tree.find( aLayer );
 
  411            it->second->Search( min, max, polyVisitor );
 
  413            it->second->Search( min, max, visitor );
 
 
  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 };
 
  434                    retval.insert( aItem->parent );
 
  438        m_tree[aLayer]->Search( min, max, visitor );
 
 
  462                             std::function<
bool(
int, 
int )> aProgressReporter )
 const 
  464        std::vector<PAIR_INFO> pairsToVisit;
 
  473                BOX2I box = refItem->shape->BBox();
 
  476                int min[2] = { box.
GetX(),     box.
GetY() };
 
  483                            if( aItemToTest->parent == refItem->parent )
 
  486                            pairsToVisit.emplace_back( layerPair, refItem, aItemToTest );
 
  490                auto it = 
m_tree.find( targetLayer );
 
  493                    it->second->Search( min, max, visit );
 
  500        std::unordered_map<PTR_PTR_CACHE_KEY, int> collidingCompounds;
 
  503        int count = pairsToVisit.size();
 
  505        for( 
const PAIR_INFO& pair : pairsToVisit )
 
  507            if( !aProgressReporter( progress++, count ) )
 
  514            if( 
static_cast<void*
>( a ) > 
static_cast<void*
>( b ) )
 
  518            if( collidingCompounds.count( { a, b } ) )
 
  521            bool collisionDetected = 
false;
 
  523            if( !aVisitor( pair.layerPair, pair.refItem, pair.testItem, &collisionDetected ) )
 
  526            if( collisionDetected )
 
  527                collidingCompounds[ { a, b } ] = 1;
 
 
  562            m_rect = { { INT_MIN, INT_MIN }, { INT_MAX, INT_MAX } };
 
 
 
  587        auto it = 
m_tree.find( 
int( aLayer ) );
 
 
  595        auto it = 
m_tree.find( 
int( aLayer ) );
 
 
  601        auto it = 
m_tree.find( 
int( aLayer ) );
 
 
 
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
 
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
 
virtual std::shared_ptr< SHAPE_SEGMENT > GetEffectiveHoleShape() const
 
virtual bool HasHole() const
 
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
 
constexpr coord_type GetY() const
 
constexpr coord_type GetX() const
 
constexpr coord_type GetRight() const
 
constexpr coord_type GetBottom() const
 
DRC_LAYER OnLayer(PCB_LAYER_ID aLayer) const
 
RTree< ITEM_WITH_SHAPE *, int, 2, double > drc_rtree
 
size_t size() const
Return the number of items in the tree.
 
typename drc_rtree::Iterator iterator
 
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.
 
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.
 
bool CheckColliding(SHAPE *aRefShape, PCB_LAYER_ID aTargetLayer, int aClearance=0, std::function< bool(BOARD_ITEM *)> aFilter=nullptr) const
 
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const BOX2I &aRect) const
 
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.
 
bool QueryColliding(const BOX2I &aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer) const
Quicker version of above that just reports a raw yes/no.
 
void clear()
Remove all items from the RTree.
 
std::pair< PCB_LAYER_ID, PCB_LAYER_ID > LAYER_PAIR
 
std::map< int, drc_rtree * > m_tree
 
DRC_LAYER Overlapping(PCB_LAYER_ID aLayer, const VECTOR2I &aPoint, int aAccuracy=0) const
 
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
 
bool QueryColliding(const BOX2I &aBox, SHAPE *aRefShape, PCB_LAYER_ID aLayer, int aClearance, int *aActual, VECTOR2I *aPos) const
This one is for tessellated items.
 
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.
 
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
 
KICAD_T Type() const
Returns the type of object.
 
virtual bool IsVisible() const
 
static const LSET & AllLayersMask()
 
SHAPE_TYPE Type() const
Return the type of the shape.
 
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.
 
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.
 
PCB_LAYER_ID
A quick note on layer IDs:
 
@ SH_POLY_SET_TRIANGLE
a single triangle belonging to a POLY_SET triangulation
 
The DRC_LAYER struct provides a layer-specific auto-range iterator to the RTree.
 
DRC_LAYER(drc_rtree *aTree)
 
DRC_LAYER(drc_rtree *aTree, const BOX2I &aRect)
 
ITEM_WITH_SHAPE(BOARD_ITEM *aParent, const SHAPE *aShape, std::shared_ptr< SHAPE > aParentShape=nullptr)
 
std::shared_ptr< SHAPE > parentShape
 
ITEM_WITH_SHAPE(BOARD_ITEM *aParent, const std::shared_ptr< SHAPE > &aShape, std::shared_ptr< SHAPE > aParentShape=nullptr)
 
std::shared_ptr< SHAPE > shapeStorage
 
ITEM_WITH_SHAPE * refItem
 
PAIR_INFO(LAYER_PAIR aPair, ITEM_WITH_SHAPE *aRef, ITEM_WITH_SHAPE *aTest)
 
ITEM_WITH_SHAPE * testItem
 
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
 
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
 
@ PCB_PAD_T
class PAD, a pad in a footprint
 
VECTOR2< int32_t > VECTOR2I