diff --git a/pcbnew/drc/drc_rtree.h b/pcbnew/drc/drc_rtree.h index f12a023f94..fdcd6783d5 100644 --- a/pcbnew/drc/drc_rtree.h +++ b/pcbnew/drc/drc_rtree.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,9 @@ */ class DRC_RTREE { -private: + +public: + struct ITEM_WITH_SHAPE { ITEM_WITH_SHAPE( BOARD_ITEM *aParent, SHAPE* aShape, std::shared_ptr aParentShape = nullptr ) : @@ -54,12 +57,12 @@ private: std::shared_ptr parentShape; }; +private: + using drc_rtree = RTree; public: - - DRC_RTREE() { for( int layer : LSET::AllLayersMask().Seq() ) @@ -279,6 +282,63 @@ public: return 0; } + typedef std::pair LAYER_PAIR; + + int QueryCollidingPairs( DRC_RTREE* aRefTree, + std::vector aLayers, + std::function aVisitor, + + // std::function aResolver, + // std::function aVisitor, + int aMaxClearance + ) + { + // keep track of BOARD_ITEMs pairs that have been already found to collide (some items + // might be build of COMPOUND/triangulated shapes and a single subshape collision + // means we have a hit) + std::set< std::pair> collidingCompounds; + + for( auto refLayerIter : aLayers ) + { + const PCB_LAYER_ID refLayer = refLayerIter.first; + const PCB_LAYER_ID targetLayer = refLayerIter.second; + + for( auto refItem : aRefTree->OnLayer( refLayer ) ) + { + BOX2I box = refItem->shape->BBox(); + box.Inflate( aMaxClearance ); + + int min[2] = { box.GetX(), box.GetY() }; + int max[2] = { box.GetRight(), box.GetBottom() }; + + auto visit = [&] ( ITEM_WITH_SHAPE* aItemToTest ) -> bool + { + const std::pair chkCompoundPair( refItem->parent, aItemToTest->parent ); + + // don't report multiple collisions for compound or triangulated shapes + if( collidingCompounds.find( chkCompoundPair ) != collidingCompounds.end() ) + return true; + + // don't collide items against themselves + if( refLayer == targetLayer && aItemToTest->parent == refItem->parent ) + return true; + + bool colliding = aVisitor( refLayerIter, refItem, aItemToTest ); + + if( colliding ) + { + collidingCompounds.insert( chkCompoundPair ); + } + + return true; + }; + + this->m_tree[targetLayer]->Search( min, max, visit ); + }; + } + return 0; + } + #if 0 std::vector> GetNearest( const wxPoint &aPoint, PCB_LAYER_ID aLayer,