P&S: support for custom visitor objects in PNS_NODE::QueryColliding()
This commit is contained in:
parent
2b32b6f72e
commit
4cbb0aebfd
|
@ -54,7 +54,6 @@ PNS_NODE::PNS_NODE()
|
||||||
m_maxClearance = 800000; // fixme: depends on how thick traces are.
|
m_maxClearance = 800000; // fixme: depends on how thick traces are.
|
||||||
m_ruleResolver = NULL;
|
m_ruleResolver = NULL;
|
||||||
m_index = new PNS_INDEX;
|
m_index = new PNS_INDEX;
|
||||||
m_collisionFilter = NULL;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
allocNodes.insert( this );
|
allocNodes.insert( this );
|
||||||
|
@ -117,7 +116,6 @@ PNS_NODE* PNS_NODE::Branch()
|
||||||
child->m_parent = this;
|
child->m_parent = this;
|
||||||
child->m_ruleResolver = m_ruleResolver;
|
child->m_ruleResolver = m_ruleResolver;
|
||||||
child->m_root = isRoot() ? this : m_root;
|
child->m_root = isRoot() ? this : m_root;
|
||||||
child->m_collisionFilter = m_collisionFilter;
|
|
||||||
|
|
||||||
// immmediate offspring of the root branch needs not copy anything.
|
// immmediate offspring of the root branch needs not copy anything.
|
||||||
// For the rest, deep-copy joints, overridden item map and pointers
|
// For the rest, deep-copy joints, overridden item map and pointers
|
||||||
|
@ -149,22 +147,39 @@ void PNS_NODE::unlinkParent()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PNS_OBSTACLE_VISITOR::PNS_OBSTACLE_VISITOR( const PNS_ITEM* aItem ) :
|
||||||
|
m_item ( aItem ),
|
||||||
|
m_node ( NULL ),
|
||||||
|
m_override( NULL ),
|
||||||
|
m_extraClearance ( 0 )
|
||||||
|
{
|
||||||
|
if( aItem && aItem->Kind() == PNS_ITEM::LINE )
|
||||||
|
m_extraClearance += static_cast<const PNS_LINE*>( aItem )->Width() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PNS_OBSTACLE_VISITOR::SetWorld( const PNS_NODE* aNode, const PNS_NODE* aOverride )
|
||||||
|
{
|
||||||
|
m_node = aNode;
|
||||||
|
m_override = aOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PNS_OBSTACLE_VISITOR::visit( PNS_ITEM *aCandidate )
|
||||||
|
{
|
||||||
|
// check if there is a more recent branch with a newer
|
||||||
|
// (possibily modified) version of this item.
|
||||||
|
if( m_override && m_override->Overrides( aCandidate ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// function object that visits potential obstacles and performs
|
// function object that visits potential obstacles and performs
|
||||||
// the actual collision refining
|
// the actual collision refining
|
||||||
struct PNS_NODE::OBSTACLE_VISITOR
|
struct PNS_NODE::DEFAULT_OBSTACLE_VISITOR : public PNS_OBSTACLE_VISITOR
|
||||||
{
|
{
|
||||||
///> node we are searching in (either root or a branch)
|
|
||||||
PNS_NODE* m_node;
|
|
||||||
|
|
||||||
///> node that overrides root entries
|
|
||||||
PNS_NODE* m_override;
|
|
||||||
|
|
||||||
///> list of encountered obstacles
|
///> list of encountered obstacles
|
||||||
OBSTACLES& m_tab;
|
OBSTACLES& m_tab;
|
||||||
|
|
||||||
///> the item we are looking for collisions with
|
|
||||||
const PNS_ITEM* m_item;
|
|
||||||
|
|
||||||
///> acccepted kinds of colliding items (solids, vias, segments, etc...)
|
///> acccepted kinds of colliding items (solids, vias, segments, etc...)
|
||||||
int m_kindMask;
|
int m_kindMask;
|
||||||
|
|
||||||
|
@ -181,20 +196,15 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
||||||
|
|
||||||
int m_forceClearance;
|
int m_forceClearance;
|
||||||
|
|
||||||
OBSTACLE_VISITOR( PNS_NODE::OBSTACLES& aTab, const PNS_ITEM* aItem, int aKindMask, bool aDifferentNetsOnly ) :
|
DEFAULT_OBSTACLE_VISITOR( PNS_NODE::OBSTACLES& aTab, const PNS_ITEM* aItem, int aKindMask, bool aDifferentNetsOnly ) :
|
||||||
m_node( NULL ),
|
PNS_OBSTACLE_VISITOR ( aItem ),
|
||||||
m_override( NULL ),
|
|
||||||
m_tab( aTab ),
|
m_tab( aTab ),
|
||||||
m_item( aItem ),
|
|
||||||
m_kindMask( aKindMask ),
|
m_kindMask( aKindMask ),
|
||||||
m_limitCount( -1 ),
|
m_limitCount( -1 ),
|
||||||
m_matchCount( 0 ),
|
m_matchCount( 0 ),
|
||||||
m_extraClearance( 0 ),
|
|
||||||
m_differentNetsOnly( aDifferentNetsOnly ),
|
m_differentNetsOnly( aDifferentNetsOnly ),
|
||||||
m_forceClearance( -1 )
|
m_forceClearance( -1 )
|
||||||
{
|
{
|
||||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
|
||||||
m_extraClearance += static_cast<const PNS_LINE*>( aItem )->Width() / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCountLimit( int aLimit )
|
void SetCountLimit( int aLimit )
|
||||||
|
@ -202,39 +212,31 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
||||||
m_limitCount = aLimit;
|
m_limitCount = aLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetWorld( PNS_NODE* aNode, PNS_NODE* aOverride = NULL )
|
bool operator()( PNS_ITEM* aCandidate )
|
||||||
{
|
{
|
||||||
m_node = aNode;
|
if( !aCandidate->OfKind( m_kindMask ) )
|
||||||
m_override = aOverride;
|
return true;
|
||||||
|
|
||||||
|
if ( visit(aCandidate) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
int clearance = m_extraClearance + m_node->GetClearance( aCandidate, m_item );
|
||||||
|
|
||||||
|
if( aCandidate->Kind() == PNS_ITEM::LINE ) // this should never happen.
|
||||||
|
{
|
||||||
|
assert( false );
|
||||||
|
clearance += static_cast<PNS_LINE*>( aCandidate )->Width() / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator()( PNS_ITEM* aItem )
|
|
||||||
{
|
|
||||||
if( !aItem->OfKind( m_kindMask ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// check if there is a more recent branch with a newer
|
|
||||||
// (possibily modified) version of this item.
|
|
||||||
if( m_override && m_override->overrides( aItem ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
int clearance = m_extraClearance + m_node->GetClearance( aItem, m_item );
|
|
||||||
|
|
||||||
if( m_node->m_collisionFilter && (*m_node->m_collisionFilter)( aItem, m_item ) )
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
|
||||||
clearance += static_cast<PNS_LINE*>( aItem )->Width() / 2;
|
|
||||||
|
|
||||||
if( m_forceClearance >= 0 )
|
if( m_forceClearance >= 0 )
|
||||||
clearance = m_forceClearance;
|
clearance = m_forceClearance;
|
||||||
|
|
||||||
if( !aItem->Collide( m_item, clearance, m_differentNetsOnly ) )
|
if( !aCandidate->Collide( m_item, clearance, m_differentNetsOnly ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
PNS_OBSTACLE obs;
|
PNS_OBSTACLE obs;
|
||||||
|
|
||||||
obs.m_item = aItem;
|
obs.m_item = aCandidate;
|
||||||
obs.m_head = m_item;
|
obs.m_head = m_item;
|
||||||
m_tab.push_back( obs );
|
m_tab.push_back( obs );
|
||||||
|
|
||||||
|
@ -247,11 +249,25 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int PNS_NODE::QueryColliding( const PNS_ITEM *aItem,
|
||||||
|
PNS_OBSTACLE_VISITOR& aVisitor )
|
||||||
|
{
|
||||||
|
aVisitor.SetWorld( this, NULL );
|
||||||
|
m_index->Query( aItem, m_maxClearance, aVisitor );
|
||||||
|
|
||||||
|
// if we haven't found enough items, look in the root branch as well.
|
||||||
|
if( !isRoot() )
|
||||||
|
{
|
||||||
|
aVisitor.SetWorld( m_root, this );
|
||||||
|
m_root->m_index->Query( aItem, m_maxClearance, aVisitor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
||||||
PNS_NODE::OBSTACLES& aObstacles, int aKindMask, int aLimitCount, bool aDifferentNetsOnly, int aForceClearance )
|
PNS_NODE::OBSTACLES& aObstacles, int aKindMask, int aLimitCount, bool aDifferentNetsOnly, int aForceClearance )
|
||||||
{
|
{
|
||||||
OBSTACLE_VISITOR visitor( aObstacles, aItem, aKindMask, aDifferentNetsOnly );
|
DEFAULT_OBSTACLE_VISITOR visitor( aObstacles, aItem, aKindMask, aDifferentNetsOnly );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert( allocNodes.find( this ) != allocNodes.end() );
|
assert( allocNodes.find( this ) != allocNodes.end() );
|
||||||
|
@ -453,14 +469,14 @@ bool PNS_NODE::CheckColliding( const PNS_ITEM* aItemA, const PNS_ITEM* aItemB, i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct HIT_VISITOR
|
struct HIT_VISITOR : public PNS_OBSTACLE_VISITOR
|
||||||
{
|
{
|
||||||
PNS_ITEMSET& m_items;
|
PNS_ITEMSET& m_items;
|
||||||
const VECTOR2I& m_point;
|
const VECTOR2I& m_point;
|
||||||
const PNS_NODE* m_world;
|
|
||||||
|
|
||||||
HIT_VISITOR( PNS_ITEMSET& aTab, const VECTOR2I& aPoint, const PNS_NODE* aWorld ) :
|
HIT_VISITOR( PNS_ITEMSET& aTab, const VECTOR2I& aPoint ) :
|
||||||
m_items( aTab ), m_point( aPoint ), m_world( aWorld )
|
PNS_OBSTACLE_VISITOR ( NULL ),
|
||||||
|
m_items( aTab ), m_point( aPoint )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool operator()( PNS_ITEM* aItem )
|
bool operator()( PNS_ITEM* aItem )
|
||||||
|
@ -483,19 +499,21 @@ const PNS_ITEMSET PNS_NODE::HitTest( const VECTOR2I& aPoint ) const
|
||||||
|
|
||||||
// fixme: we treat a point as an infinitely small circle - this is inefficient.
|
// fixme: we treat a point as an infinitely small circle - this is inefficient.
|
||||||
SHAPE_CIRCLE s( aPoint, 0 );
|
SHAPE_CIRCLE s( aPoint, 0 );
|
||||||
HIT_VISITOR visitor( items, aPoint, this );
|
HIT_VISITOR visitor( items, aPoint );
|
||||||
|
visitor.SetWorld(this, NULL);
|
||||||
|
|
||||||
m_index->Query( &s, m_maxClearance, visitor );
|
m_index->Query( &s, m_maxClearance, visitor );
|
||||||
|
|
||||||
if( !isRoot() ) // fixme: could be made cleaner
|
if( !isRoot() ) // fixme: could be made cleaner
|
||||||
{
|
{
|
||||||
PNS_ITEMSET items_root;
|
PNS_ITEMSET items_root;
|
||||||
HIT_VISITOR visitor_root( items_root, aPoint, m_root );
|
visitor.SetWorld(m_root, NULL);
|
||||||
|
HIT_VISITOR visitor_root( items_root, aPoint );
|
||||||
m_root->m_index->Query( &s, m_maxClearance, visitor_root );
|
m_root->m_index->Query( &s, m_maxClearance, visitor_root );
|
||||||
|
|
||||||
for( PNS_ITEM* item : items_root.Items() )
|
for( PNS_ITEM* item : items_root.Items() )
|
||||||
{
|
{
|
||||||
if( !overrides( item ) )
|
if( !Overrides( item ) )
|
||||||
items.Add( item );
|
items.Add( item );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1192,7 +1210,7 @@ void PNS_NODE::AllItemsInNet( int aNet, std::set<PNS_ITEM*>& aItems )
|
||||||
|
|
||||||
if( l_root )
|
if( l_root )
|
||||||
for( PNS_INDEX::NET_ITEMS_LIST::iterator i = l_root->begin(); i!= l_root->end(); ++i )
|
for( PNS_INDEX::NET_ITEMS_LIST::iterator i = l_root->begin(); i!= l_root->end(); ++i )
|
||||||
if( !overrides( *i ) )
|
if( !Overrides( *i ) )
|
||||||
aItems.insert( *i );
|
aItems.insert( *i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1270,12 +1288,6 @@ PNS_SEGMENT* PNS_NODE::findRedundantSegment( PNS_SEGMENT* aSeg )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PNS_NODE::SetCollisionFilter( PNS_COLLISION_FILTER* aFilter )
|
|
||||||
{
|
|
||||||
m_collisionFilter = aFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PNS_ITEM *PNS_NODE::FindItemByParent( const BOARD_CONNECTED_ITEM* aParent )
|
PNS_ITEM *PNS_NODE::FindItemByParent( const BOARD_CONNECTED_ITEM* aParent )
|
||||||
{
|
{
|
||||||
PNS_INDEX::NET_ITEMS_LIST* l_cur = m_index->GetItemsForNet( aParent->GetNetCode() );
|
PNS_INDEX::NET_ITEMS_LIST* l_cur = m_index->GetItemsForNet( aParent->GetNetCode() );
|
||||||
|
|
|
@ -40,9 +40,9 @@ class PNS_SEGMENT;
|
||||||
class PNS_LINE;
|
class PNS_LINE;
|
||||||
class PNS_SOLID;
|
class PNS_SOLID;
|
||||||
class PNS_VIA;
|
class PNS_VIA;
|
||||||
class PNS_RATSNEST;
|
|
||||||
class PNS_INDEX;
|
class PNS_INDEX;
|
||||||
class PNS_ROUTER;
|
class PNS_ROUTER;
|
||||||
|
class PNS_NODE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PNS_RULE_RESOLVER
|
* Class PNS_RULE_RESOLVER
|
||||||
|
@ -65,7 +65,6 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct PNS_OBSTACLE
|
* Struct PNS_OBSTACLE
|
||||||
*
|
*
|
||||||
|
@ -92,12 +91,33 @@ struct PNS_OBSTACLE
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Struct PNS_COLLISION_FILTER
|
* Struct PNS_OBSTACLE_VISITOR
|
||||||
* Used to override the decision of the collision search algorithm whether two
|
|
||||||
* items collide.
|
|
||||||
**/
|
**/
|
||||||
struct PNS_COLLISION_FILTER {
|
class PNS_OBSTACLE_VISITOR {
|
||||||
virtual bool operator()( const PNS_ITEM *aItemA, const PNS_ITEM *aItemB ) const = 0;
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
PNS_OBSTACLE_VISITOR( const PNS_ITEM* aItem );
|
||||||
|
|
||||||
|
void SetWorld( const PNS_NODE* aNode, const PNS_NODE* aOverride = NULL );
|
||||||
|
|
||||||
|
virtual bool operator()( PNS_ITEM *aCandidate ) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
bool visit( PNS_ITEM *aCandidate );
|
||||||
|
|
||||||
|
///> the item we are looking for collisions with
|
||||||
|
const PNS_ITEM* m_item;
|
||||||
|
|
||||||
|
///> node we are searching in (either root or a branch)
|
||||||
|
const PNS_NODE* m_node;
|
||||||
|
|
||||||
|
///> node that overrides root entries
|
||||||
|
const PNS_NODE* m_override;
|
||||||
|
|
||||||
|
///> additional clearance
|
||||||
|
int m_extraClearance;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -177,6 +197,10 @@ public:
|
||||||
bool aDifferentNetsOnly = true,
|
bool aDifferentNetsOnly = true,
|
||||||
int aForceClearance = -1 );
|
int aForceClearance = -1 );
|
||||||
|
|
||||||
|
int QueryColliding( const PNS_ITEM *aItem,
|
||||||
|
PNS_OBSTACLE_VISITOR& aVisitor
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function NearestObstacle()
|
* Function NearestObstacle()
|
||||||
*
|
*
|
||||||
|
@ -366,7 +390,6 @@ public:
|
||||||
|
|
||||||
int FindByMarker( int aMarker, PNS_ITEMSET& aItems );
|
int FindByMarker( int aMarker, PNS_ITEMSET& aItems );
|
||||||
int RemoveByMarker( int aMarker );
|
int RemoveByMarker( int aMarker );
|
||||||
void SetCollisionFilter( PNS_COLLISION_FILTER* aFilter );
|
|
||||||
|
|
||||||
PNS_ITEM* FindItemByParent( const BOARD_CONNECTED_ITEM *aParent );
|
PNS_ITEM* FindItemByParent( const BOARD_CONNECTED_ITEM *aParent );
|
||||||
|
|
||||||
|
@ -375,8 +398,15 @@ public:
|
||||||
return !m_children.empty();
|
return !m_children.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///> checks if this branch contains an updated version of the m_item
|
||||||
|
///> from the root branch.
|
||||||
|
bool Overrides( PNS_ITEM* aItem ) const
|
||||||
|
{
|
||||||
|
return m_override.find( aItem ) != m_override.end();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct OBSTACLE_VISITOR;
|
struct DEFAULT_OBSTACLE_VISITOR;
|
||||||
typedef boost::unordered_multimap<PNS_JOINT::HASH_TAG, PNS_JOINT> JOINT_MAP;
|
typedef boost::unordered_multimap<PNS_JOINT::HASH_TAG, PNS_JOINT> JOINT_MAP;
|
||||||
typedef JOINT_MAP::value_type TagJointPair;
|
typedef JOINT_MAP::value_type TagJointPair;
|
||||||
|
|
||||||
|
@ -417,13 +447,6 @@ private:
|
||||||
return m_parent == NULL;
|
return m_parent == NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
///> checks if this branch contains an updated version of the m_item
|
|
||||||
///> from the root branch.
|
|
||||||
bool overrides( PNS_ITEM* aItem ) const
|
|
||||||
{
|
|
||||||
return m_override.find( aItem ) != m_override.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
PNS_SEGMENT* findRedundantSegment( PNS_SEGMENT* aSeg );
|
PNS_SEGMENT* findRedundantSegment( PNS_SEGMENT* aSeg );
|
||||||
|
|
||||||
///> scans the joint map, forming a line starting from segment (current).
|
///> scans the joint map, forming a line starting from segment (current).
|
||||||
|
@ -464,9 +487,6 @@ private:
|
||||||
///> depth of the node (number of parent nodes in the inheritance chain)
|
///> depth of the node (number of parent nodes in the inheritance chain)
|
||||||
int m_depth;
|
int m_depth;
|
||||||
|
|
||||||
///> optional collision filtering object
|
|
||||||
PNS_COLLISION_FILTER* m_collisionFilter;
|
|
||||||
|
|
||||||
boost::unordered_set<PNS_ITEM*> m_garbageItems;
|
boost::unordered_set<PNS_ITEM*> m_garbageItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue