pcbnew: Split Layers in connectivity

Splits the connectivity search RTree by layers to avoid large penalty on
zone searches.
This commit is contained in:
Seth Hillbrand 2018-07-05 14:16:25 -07:00
parent 099fcf1247
commit dc1736eb87
2 changed files with 102 additions and 38 deletions

View File

@ -288,6 +288,9 @@ protected:
///> dirty flag, used to identify recently added item not yet scanned into the connectivity search ///> dirty flag, used to identify recently added item not yet scanned into the connectivity search
bool m_dirty; bool m_dirty;
///> layer range over which the item exists
LAYER_RANGE m_layers;
///> bounding box for the item ///> bounding box for the item
BOX2I m_bbox; BOX2I m_bbox;
@ -302,6 +305,7 @@ public:
m_valid = true; m_valid = true;
m_dirty = true; m_dirty = true;
m_anchors.reserve( 2 ); m_anchors.reserve( 2 );
m_layers = LAYER_RANGE( 0, PCB_LAYER_ID_COUNT );
} }
virtual ~CN_ITEM() {}; virtual ~CN_ITEM() {};
@ -336,7 +340,58 @@ public:
return m_dirty; return m_dirty;
} }
const BOX2I BBox() /**
* Function SetLayers()
*
* Sets the layers spanned by the item to aLayers.
*/
void SetLayers( const LAYER_RANGE& aLayers )
{
m_layers = aLayers;
}
/**
* Function SetLayer()
*
* Sets the layers spanned by the item to a single layer aLayer.
*/
void SetLayer( int aLayer )
{
m_layers = LAYER_RANGE( aLayer, aLayer );
}
/**
* Function Layers()
*
* Returns the contiguous set of layers spanned by the item.
*/
const LAYER_RANGE& Layers() const
{
return m_layers;
}
/**
* Function Layer()
*
* Returns the item's layer, for single-layered items only.
*/
virtual int Layer() const
{
return Layers().Start();
}
/**
* Function LayersOverlap()
*
* Returns true if the set of layers spanned by aOther overlaps our
* layers.
*/
bool LayersOverlap( const CN_ITEM* aOther ) const
{
return Layers().Overlaps( aOther->Layers() );
}
const BOX2I& BBox()
{ {
if( m_dirty ) if( m_dirty )
{ {
@ -498,8 +553,31 @@ public:
CN_ITEM* Add( D_PAD* pad ) CN_ITEM* Add( D_PAD* pad )
{ {
auto item = new CN_ITEM( pad, false, 2 ); auto item = new CN_ITEM( pad, false, 1 );
item->AddAnchor( pad->ShapePos() ); item->AddAnchor( pad->ShapePos() );
item->SetLayers( LAYER_RANGE( 0, PCB_LAYER_ID_COUNT ) );
switch( pad->GetAttribute() )
{
case PAD_ATTRIB_SMD:
case PAD_ATTRIB_HOLE_NOT_PLATED:
case PAD_ATTRIB_CONN:
{
LSET lmsk = pad->GetLayerSet();
for( int i = 0; i <= MAX_CU_LAYERS; i++ )
{
if( lmsk[i] )
{
item->SetLayer( i );
break;
}
}
}
default:
break;
}
addItemtoTree( item ); addItemtoTree( item );
m_items.push_back( item ); m_items.push_back( item );
SetDirty(); SetDirty();
@ -512,6 +590,7 @@ public:
m_items.push_back( item ); m_items.push_back( item );
item->AddAnchor( track->GetStart() ); item->AddAnchor( track->GetStart() );
item->AddAnchor( track->GetEnd() ); item->AddAnchor( track->GetEnd() );
item->SetLayer( track->GetLayer() );
addItemtoTree( item ); addItemtoTree( item );
SetDirty(); SetDirty();
return item; return item;
@ -519,10 +598,11 @@ public:
CN_ITEM* Add( VIA* via ) CN_ITEM* Add( VIA* via )
{ {
auto item = new CN_ITEM( via, true ); auto item = new CN_ITEM( via, true, 1 );
m_items.push_back( item ); m_items.push_back( item );
item->AddAnchor( via->GetStart() ); item->AddAnchor( via->GetStart() );
item->SetLayers( LAYER_RANGE( 0, PCB_LAYER_ID_COUNT ) );
addItemtoTree( item ); addItemtoTree( item );
SetDirty(); SetDirty();
return item; return item;
@ -599,6 +679,7 @@ public:
zitem->AddAnchor( outline.CPoint( k ) ); zitem->AddAnchor( outline.CPoint( k ) );
m_items.push_back( zitem ); m_items.push_back( zitem );
zitem->SetLayer( zone->GetLayer() );
addItemtoTree( zitem ); addItemtoTree( zitem );
rv.push_back( zitem ); rv.push_back( zitem );
SetDirty(); SetDirty();
@ -606,33 +687,12 @@ public:
return rv; return rv;
} }
template <class T>
void FindNearbyZones( BOX2I aBBox, T aFunc, bool aDirtyOnly = false );
}; };
template <class T>
void CN_ZONE_LIST::FindNearbyZones( BOX2I aBBox, T aFunc, bool aDirtyOnly )
{
for( auto item : m_items )
{
auto zone = static_cast<CN_ZONE*>( item );
if( aBBox.Intersects( zone->BBox() ) )
{
if( !aDirtyOnly || zone->Dirty() )
{
aFunc( zone );
}
}
}
}
template <class T> template <class T>
void CN_LIST::FindNearby( CN_ITEM *aItem, T aFunc ) void CN_LIST::FindNearby( CN_ITEM *aItem, T aFunc )
{ {
m_index.Query( aItem->BBox(), aFunc ); m_index.Query( aItem->BBox(), aItem->Layers(), aFunc );
} }
class CN_CONNECTIVITY_ALGO class CN_CONNECTIVITY_ALGO

View File

@ -25,6 +25,7 @@
#define PCBNEW_CONNECTIVITY_RTREE_H_ #define PCBNEW_CONNECTIVITY_RTREE_H_
#include <math/box2.h> #include <math/box2.h>
#include <router/pns_layerset.h>
#include <geometry/rtree.h> #include <geometry/rtree.h>
@ -41,7 +42,7 @@ public:
CN_RTREE() CN_RTREE()
{ {
this->m_tree = new RTree<T, int, 2, float>(); this->m_tree = new RTree<T, int, 3, double>();
} }
~CN_RTREE() ~CN_RTREE()
@ -55,9 +56,11 @@ public:
*/ */
void Insert( T aItem ) void Insert( T aItem )
{ {
const BOX2I& bbox = aItem->BBox(); const BOX2I& bbox = aItem->BBox();
const int mmin[2] = { bbox.GetX(), bbox.GetY() }; const LAYER_RANGE layers = aItem->Layers();
const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
const int mmin[3] = { layers.Start(), bbox.GetX(), bbox.GetY() };
const int mmax[3] = { layers.End(), bbox.GetRight(), bbox.GetBottom() };
m_tree->Insert( mmin, mmax, aItem ); m_tree->Insert( mmin, mmax, aItem );
} }
@ -71,9 +74,10 @@ public:
{ {
// First, attempt to remove the item using its given BBox // First, attempt to remove the item using its given BBox
const BOX2I& bbox = aItem->BBox(); const BOX2I& bbox = aItem->BBox();
const int mmin[2] = { bbox.GetX(), bbox.GetY() }; const LAYER_RANGE layers = aItem->Layers();
const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() }; const int mmin[3] = { layers.Start(), bbox.GetX(), bbox.GetY() };
const int mmax[3] = { layers.End(), bbox.GetRight(), bbox.GetBottom() };
// If we are not successful ( 1 == not found ), then we expand // If we are not successful ( 1 == not found ), then we expand
// the search to the full tree // the search to the full tree
@ -82,8 +86,8 @@ public:
// 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
// because the item may have been moved before we have the chance to // because the item may have been moved before we have the chance to
// delete it from the tree // delete it from the tree
const int mmin2[2] = { INT_MIN, INT_MIN }; const int mmin2[3] = { INT_MIN, INT_MIN, INT_MIN };
const int mmax2[2] = { INT_MAX, INT_MAX }; const int mmax2[3] = { INT_MAX, INT_MAX, INT_MAX };
m_tree->Remove( mmin2, mmax2, aItem ); m_tree->Remove( mmin2, mmax2, aItem );
} }
} }
@ -103,17 +107,17 @@ public:
* with aBounds. * with aBounds.
*/ */
template <class Visitor> template <class Visitor>
void Query( const BOX2I& aBounds, Visitor& aVisitor ) void Query( const BOX2I& aBounds, const LAYER_RANGE& aRange, Visitor& aVisitor )
{ {
const int mmin[2] = { aBounds.GetX(), aBounds.GetY() }; const int mmin[3] = { aRange.Start(), aBounds.GetX(), aBounds.GetY() };
const int mmax[2] = { aBounds.GetRight(), aBounds.GetBottom() }; const int mmax[3] = { aRange.End(), aBounds.GetRight(), aBounds.GetBottom() };
m_tree->Search( mmin, mmax, aVisitor ); m_tree->Search( mmin, mmax, aVisitor );
} }
private: private:
RTree<T, int, 2, float>* m_tree; RTree<T, int, 3, double>* m_tree;
}; };