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
|
///> 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
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue