DRC_TREE: Allow indexing on triangulated zones

Also move to BOARD_ITEM* as we might want to run DRC on non-copper items
This commit is contained in:
Seth Hillbrand 2020-09-04 15:53:06 -07:00
parent e05069ce3c
commit 3095d0e335
1 changed files with 65 additions and 15 deletions

View File

@ -41,7 +41,7 @@
class DRC_RTREE class DRC_RTREE
{ {
private: private:
using drc_rtree = RTree<BOARD_CONNECTED_ITEM*, int, 2, double>; using drc_rtree = RTree<BOARD_ITEM*, int, 2, double>;
public: public:
DRC_RTREE() DRC_RTREE()
@ -62,14 +62,46 @@ public:
* Function Insert() * Function Insert()
* Inserts an item into the tree. Item's bounding box is taken via its GetBoundingBox() method. * Inserts an item into the tree. Item's bounding box is taken via its GetBoundingBox() method.
*/ */
void insert( BOARD_CONNECTED_ITEM* aItem ) void insert( BOARD_ITEM* aItem )
{
if( ZONE_CONTAINER* zone = dyn_cast<ZONE_CONTAINER*>( aItem ) )
{
for( int layer : zone->GetLayerSet().Seq() )
{
const SHAPE_POLY_SET& polyset = zone->GetFilledPolysList( PCB_LAYER_ID( layer ) );
for( int ii = 0; ii < polyset.TriangulatedPolyCount(); ++ii )
{
const auto poly = polyset.TriangulatedPolygon( ii );
for( int jj = 0; jj < poly->GetTriangleCount(); ++jj )
{
VECTOR2I a;
VECTOR2I b;
VECTOR2I c;
poly->GetTriangle( jj, a, b, c );
const int mmin2[2] = { std::min( a.x, std::min( b.x, c.x ) ),
std::min( a.y, std::min( b.y, c.y ) ) };
const int mmax2[2] = { std::max( a.x, std::max( b.x, c.x ) ),
std::max( a.y, std::max( b.y, c.y ) ) };
m_tree[layer]->Insert( mmin2, mmax2, aItem );
}
}
}
}
else
{ {
const EDA_RECT& bbox = aItem->GetBoundingBox(); const EDA_RECT& bbox = aItem->GetBoundingBox();
const int mmin[2] = { bbox.GetX(), bbox.GetY() }; const int mmin[2] = { bbox.GetX(), bbox.GetY() };
const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() }; const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
for( int layer : aItem->GetLayerSet().Seq() ) for( int layer : aItem->GetLayerSet().Seq() )
{
m_tree[layer]->Insert( mmin, mmax, aItem ); m_tree[layer]->Insert( mmin, mmax, aItem );
}
}
m_count++; m_count++;
} }
@ -79,7 +111,7 @@ public:
* Removes an item from the tree. Removal is done by comparing pointers, attempting * Removes an item from the tree. Removal is done by comparing pointers, attempting
* to remove a copy of the item will fail. * to remove a copy of the item will fail.
*/ */
bool remove( BOARD_CONNECTED_ITEM* aItem ) bool remove( BOARD_ITEM* aItem )
{ {
// First, attempt to remove the item using its given BBox // First, attempt to remove the item using its given BBox
const EDA_RECT& bbox = aItem->GetBoundingBox(); const EDA_RECT& bbox = aItem->GetBoundingBox();
@ -89,8 +121,26 @@ public:
for( auto layer : aItem->GetLayerSet().Seq() ) for( auto layer : aItem->GetLayerSet().Seq() )
{ {
if( ZONE_CONTAINER* zone = dyn_cast<ZONE_CONTAINER*>( aItem ) )
{
// Continue removing the zone elements from the tree until they cannot be found
while( !m_tree[int( layer )]->Remove( mmin, mmax, aItem ) )
;
const int mmin2[2] = { INT_MIN, INT_MIN };
const int mmax2[2] = { INT_MAX, INT_MAX };
// If we are not successful ( true == not found ), then we expand // If we are not successful ( true == not found ), then we expand
// the search to the full tree // the search to the full tree
while( !m_tree[int( layer )]->Remove( mmin2, mmax2, aItem ) )
;
// Loop to the next layer
continue;
}
// The non-zone search expects only a single element in the tree with the same
// pointer aItem
if( m_tree[int( layer )]->Remove( mmin, mmax, aItem ) ) if( m_tree[int( layer )]->Remove( mmin, mmax, aItem ) )
{ {
// N.B. We must search the whole tree for the pointer to remove // N.B. We must search the whole tree for the pointer to remove
@ -131,14 +181,14 @@ public:
* @param aRobust If true, search the whole tree, not just the bounding box * @param aRobust If true, search the whole tree, not just the bounding box
* @return true if the item definitely exists, false if it does not exist within bbox * @return true if the item definitely exists, false if it does not exist within bbox
*/ */
bool contains( BOARD_CONNECTED_ITEM* aItem, bool aRobust = false ) bool contains( BOARD_ITEM* aItem, bool aRobust = false )
{ {
const EDA_RECT& bbox = aItem->GetBoundingBox(); const EDA_RECT& bbox = aItem->GetBoundingBox();
const int mmin[2] = { bbox.GetX(), bbox.GetY() }; const int mmin[2] = { bbox.GetX(), bbox.GetY() };
const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() }; const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
bool found = false; bool found = false;
auto search = [&found, &aItem]( const BOARD_CONNECTED_ITEM* aSearchItem ) { auto search = [&found, &aItem]( const BOARD_ITEM* aSearchItem ) {
if( aSearchItem == aItem ) if( aSearchItem == aItem )
{ {
found = true; found = true;
@ -177,7 +227,7 @@ public:
return found; return found;
} }
std::vector<std::pair<int, BOARD_CONNECTED_ITEM*>> GetNearest( const wxPoint &aPoint, std::vector<std::pair<int, BOARD_ITEM*>> GetNearest( const wxPoint &aPoint,
PCB_LAYER_ID aLayer, PCB_LAYER_ID aLayer,
int aLimit ) int aLimit )
{ {
@ -188,12 +238,12 @@ public:
{ {
return a_count >= aLimit; return a_count >= aLimit;
}, },
[]( BOARD_CONNECTED_ITEM* aElement) -> bool []( BOARD_ITEM* aElement) -> bool
{ {
// Don't remove any elements from the list // Don't remove any elements from the list
return false; return false;
}, },
[aLayer]( const int* a_point, BOARD_CONNECTED_ITEM* a_data ) -> int [aLayer]( const int* a_point, BOARD_ITEM* a_data ) -> int
{ {
switch( a_data->Type() ) switch( a_data->Type() )
{ {