pcbnew: Split Layers in connectivity
Splits the connectivity search RTree by layers to avoid large penalty on zone searches.
This commit is contained in:
parent
099fcf1247
commit
dc1736eb87
|
@ -288,6 +288,9 @@ protected:
|
|||
///> dirty flag, used to identify recently added item not yet scanned into the connectivity search
|
||||
bool m_dirty;
|
||||
|
||||
///> layer range over which the item exists
|
||||
LAYER_RANGE m_layers;
|
||||
|
||||
///> bounding box for the item
|
||||
BOX2I m_bbox;
|
||||
|
||||
|
@ -302,6 +305,7 @@ public:
|
|||
m_valid = true;
|
||||
m_dirty = true;
|
||||
m_anchors.reserve( 2 );
|
||||
m_layers = LAYER_RANGE( 0, PCB_LAYER_ID_COUNT );
|
||||
}
|
||||
|
||||
virtual ~CN_ITEM() {};
|
||||
|
@ -336,7 +340,58 @@ public:
|
|||
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 )
|
||||
{
|
||||
|
@ -498,8 +553,31 @@ public:
|
|||
|
||||
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->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 );
|
||||
m_items.push_back( item );
|
||||
SetDirty();
|
||||
|
@ -512,6 +590,7 @@ public:
|
|||
m_items.push_back( item );
|
||||
item->AddAnchor( track->GetStart() );
|
||||
item->AddAnchor( track->GetEnd() );
|
||||
item->SetLayer( track->GetLayer() );
|
||||
addItemtoTree( item );
|
||||
SetDirty();
|
||||
return item;
|
||||
|
@ -519,10 +598,11 @@ public:
|
|||
|
||||
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 );
|
||||
item->AddAnchor( via->GetStart() );
|
||||
item->SetLayers( LAYER_RANGE( 0, PCB_LAYER_ID_COUNT ) );
|
||||
addItemtoTree( item );
|
||||
SetDirty();
|
||||
return item;
|
||||
|
@ -599,6 +679,7 @@ public:
|
|||
zitem->AddAnchor( outline.CPoint( k ) );
|
||||
|
||||
m_items.push_back( zitem );
|
||||
zitem->SetLayer( zone->GetLayer() );
|
||||
addItemtoTree( zitem );
|
||||
rv.push_back( zitem );
|
||||
SetDirty();
|
||||
|
@ -606,33 +687,12 @@ public:
|
|||
|
||||
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>
|
||||
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
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#define PCBNEW_CONNECTIVITY_RTREE_H_
|
||||
|
||||
#include <math/box2.h>
|
||||
#include <router/pns_layerset.h>
|
||||
|
||||
#include <geometry/rtree.h>
|
||||
|
||||
|
@ -41,7 +42,7 @@ public:
|
|||
|
||||
CN_RTREE()
|
||||
{
|
||||
this->m_tree = new RTree<T, int, 2, float>();
|
||||
this->m_tree = new RTree<T, int, 3, double>();
|
||||
}
|
||||
|
||||
~CN_RTREE()
|
||||
|
@ -55,9 +56,11 @@ public:
|
|||
*/
|
||||
void Insert( T aItem )
|
||||
{
|
||||
const BOX2I& bbox = aItem->BBox();
|
||||
const int mmin[2] = { bbox.GetX(), bbox.GetY() };
|
||||
const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
|
||||
const BOX2I& bbox = aItem->BBox();
|
||||
const LAYER_RANGE layers = aItem->Layers();
|
||||
|
||||
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 );
|
||||
}
|
||||
|
@ -71,9 +74,10 @@ public:
|
|||
{
|
||||
|
||||
// First, attempt to remove the item using its given BBox
|
||||
const BOX2I& bbox = aItem->BBox();
|
||||
const int mmin[2] = { bbox.GetX(), bbox.GetY() };
|
||||
const int mmax[2] = { bbox.GetRight(), bbox.GetBottom() };
|
||||
const BOX2I& bbox = aItem->BBox();
|
||||
const LAYER_RANGE layers = aItem->Layers();
|
||||
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
|
||||
// the search to the full tree
|
||||
|
@ -82,8 +86,8 @@ public:
|
|||
// 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
|
||||
// delete it from the tree
|
||||
const int mmin2[2] = { INT_MIN, INT_MIN };
|
||||
const int mmax2[2] = { INT_MAX, INT_MAX };
|
||||
const int mmin2[3] = { INT_MIN, INT_MIN, INT_MIN };
|
||||
const int mmax2[3] = { INT_MAX, INT_MAX, INT_MAX };
|
||||
m_tree->Remove( mmin2, mmax2, aItem );
|
||||
}
|
||||
}
|
||||
|
@ -103,17 +107,17 @@ public:
|
|||
* with aBounds.
|
||||
*/
|
||||
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 mmax[2] = { aBounds.GetRight(), aBounds.GetBottom() };
|
||||
const int mmin[3] = { aRange.Start(), aBounds.GetX(), aBounds.GetY() };
|
||||
const int mmax[3] = { aRange.End(), aBounds.GetRight(), aBounds.GetBottom() };
|
||||
|
||||
m_tree->Search( mmin, mmax, aVisitor );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
RTree<T, int, 2, float>* m_tree;
|
||||
RTree<T, int, 3, double>* m_tree;
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue