router: pass collision query options in a structure
Selectively cherry-picked by Jeff Young <jeff@rokeby.ie> 4 April 2023 - Jon's user-clearance-epsilon algo kept intact - Jeff's castellated-pad code kept intact
This commit is contained in:
parent
16b4ec3c7e
commit
eed05191a9
|
@ -143,7 +143,7 @@ bool COMPONENT_DRAGGER::Start( const VECTOR2I& aP, ITEM_SET& aPrimitives )
|
|||
{
|
||||
LINKED_ITEM* li = static_cast<LINKED_ITEM*>( extraJoint->LinkList()[0].item );
|
||||
|
||||
if( li->Collide( solid, nullptr, m_world ) )
|
||||
if( li->Collide( solid, m_world ) )
|
||||
addLinked( solid, extraJoint, li, extraJoint->Pos() - solid->Pos() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,8 @@ typedef VECTOR2I::extended_type ecoord;
|
|||
|
||||
namespace PNS {
|
||||
|
||||
bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOnly, int aOverrideClearance ) const
|
||||
bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode,
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts, OBSTACLE *aObsInfo ) const
|
||||
{
|
||||
const ROUTER_IFACE* iface = ROUTER::GetInstance()->GetInterface();
|
||||
const SHAPE* shapeA = Shape();
|
||||
|
@ -38,6 +39,7 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent
|
|||
const SHAPE* shapeB = aOther->Shape();
|
||||
const SHAPE* holeB = aOther->Hole();
|
||||
int lineWidthB = 0;
|
||||
const int clearanceEpsilon = aNode->GetRuleResolver()->ClearanceEpsilon();
|
||||
|
||||
// Sadly collision routines ignore SHAPE_POLY_LINE widths so we have to pass them in as part
|
||||
// of the clearance value.
|
||||
|
@ -48,11 +50,11 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent
|
|||
lineWidthB = static_cast<const LINE*>( aOther )->Width() / 2;
|
||||
|
||||
// same nets? no collision!
|
||||
if( aDifferentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 )
|
||||
if( aOpts.m_differentNetsOnly && m_net == aOther->m_net && m_net >= 0 && aOther->m_net >= 0 )
|
||||
return false;
|
||||
|
||||
// a pad associated with a "free" pin (NIC) doesn't have a net until it has been used
|
||||
if( aDifferentNetsOnly && ( IsFreePad() || aOther->IsFreePad() ) )
|
||||
if( aOpts.m_differentNetsOnly && ( IsFreePad() || aOther->IsFreePad() ) )
|
||||
return false;
|
||||
|
||||
// check if we are not on completely different layers first
|
||||
|
@ -93,21 +95,35 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent
|
|||
bool thisNotFlashed = !iface->IsFlashedOnLayer( this, aOther->Layer() );
|
||||
bool otherNotFlashed = !iface->IsFlashedOnLayer( aOther, Layer() );
|
||||
|
||||
if( aObsInfo )
|
||||
{
|
||||
aObsInfo->m_headIsHole = false;
|
||||
aObsInfo->m_itemIsHole = false;
|
||||
}
|
||||
|
||||
if( ( aNode->GetCollisionQueryScope() == NODE::CQS_ALL_RULES
|
||||
|| ( thisNotFlashed || otherNotFlashed ) )
|
||||
&& ( holeA || holeB ) )
|
||||
{
|
||||
int holeClearance = aNode->GetHoleClearance( this, aOther );
|
||||
|
||||
if( holeClearance >= 0 && holeA && holeA->Collide( shapeB, holeClearance + lineWidthB ) )
|
||||
if( holeA && holeA->Collide( shapeB, holeClearance + lineWidthB - clearanceEpsilon ) )
|
||||
{
|
||||
Mark( Marker() | MK_HOLE );
|
||||
if( aObsInfo )
|
||||
{
|
||||
aObsInfo->m_headIsHole = true;
|
||||
aObsInfo->m_clearance = holeClearance;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if( holeB && holeClearance >= 0 && holeB->Collide( shapeA, holeClearance + lineWidthA ) )
|
||||
if( holeB && holeB->Collide( shapeA, holeClearance + lineWidthA - clearanceEpsilon ) )
|
||||
{
|
||||
aOther->Mark( aOther->Marker() | MK_HOLE );
|
||||
if( aObsInfo )
|
||||
{
|
||||
aObsInfo->m_itemIsHole = true;
|
||||
aObsInfo->m_clearance = holeClearance;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -115,10 +131,14 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent
|
|||
{
|
||||
int holeToHoleClearance = aNode->GetHoleToHoleClearance( this, aOther );
|
||||
|
||||
if( holeToHoleClearance >= 0 && holeA->Collide( holeB, holeToHoleClearance ) )
|
||||
if( holeA->Collide( holeB, holeToHoleClearance - clearanceEpsilon ) )
|
||||
{
|
||||
Mark( Marker() | MK_HOLE );
|
||||
aOther->Mark( aOther->Marker() | MK_HOLE );
|
||||
if( aObsInfo )
|
||||
{
|
||||
aObsInfo->m_headIsHole = true;
|
||||
aObsInfo->m_itemIsHole = true;
|
||||
aObsInfo->m_clearance = holeToHoleClearance;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +150,8 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent
|
|||
if( !Layers().IsMultilayer() && otherNotFlashed )
|
||||
return false;
|
||||
|
||||
int clearance = aOverrideClearance >= 0 ? aOverrideClearance : aNode->GetClearance( this, aOther );
|
||||
int clearance = aOpts.m_overrideClearance >= 0 ? aOpts.m_overrideClearance
|
||||
: aNode->GetClearance( this, aOther );
|
||||
|
||||
if( clearance >= 0 )
|
||||
{
|
||||
|
@ -151,14 +172,22 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent
|
|||
if( checkNetTie && aNode->GetRuleResolver()->IsNetTieExclusion( aOther, pos, this ) )
|
||||
return false;
|
||||
|
||||
if( aObsInfo )
|
||||
aObsInfo->m_clearance = clearance;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fast method
|
||||
if( shapeA->Collide( shapeB, clearance + lineWidthA + lineWidthB ) )
|
||||
if( shapeA->Collide( shapeB, clearance + lineWidthA + lineWidthB - clearanceEpsilon ) )
|
||||
{
|
||||
if( aObsInfo )
|
||||
aObsInfo->m_clearance = clearance;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,9 +195,10 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent
|
|||
}
|
||||
|
||||
|
||||
bool ITEM::Collide( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOnly, int aOverrideClearance ) const
|
||||
bool ITEM::Collide( const ITEM* aOther, const NODE* aNode,
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts, OBSTACLE *aObsInfo ) const
|
||||
{
|
||||
if( collideSimple( aOther, aNode, aDifferentNetsOnly, aOverrideClearance ) )
|
||||
if( collideSimple( aOther, aNode, aOpts, aObsInfo ) )
|
||||
return true;
|
||||
|
||||
// Special cases for "head" lines with vias attached at the end. Note that this does not
|
||||
|
@ -179,7 +209,7 @@ bool ITEM::Collide( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOn
|
|||
{
|
||||
const LINE* line = static_cast<const LINE*>( this );
|
||||
|
||||
if( line->EndsWithVia() && line->Via().collideSimple( aOther, aNode, aDifferentNetsOnly, aOverrideClearance ) )
|
||||
if( line->EndsWithVia() && line->Via().collideSimple( aOther, aNode, aOpts, aObsInfo ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -187,7 +217,7 @@ bool ITEM::Collide( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOn
|
|||
{
|
||||
const LINE* line = static_cast<const LINE*>( aOther );
|
||||
|
||||
if( line->EndsWithVia() && line->Via().collideSimple( this, aNode, aDifferentNetsOnly, aOverrideClearance ) )
|
||||
if( line->EndsWithVia() && line->Via().collideSimple( this, aNode, aOpts, aObsInfo ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,20 @@ enum LineMarker {
|
|||
MK_HEAD = ( 1 << 0 ),
|
||||
MK_VIOLATION = ( 1 << 3 ),
|
||||
MK_LOCKED = ( 1 << 4 ),
|
||||
MK_DP_COUPLED = ( 1 << 5 ),
|
||||
MK_HOLE = ( 1 << 6 )
|
||||
MK_DP_COUPLED = ( 1 << 5 )
|
||||
};
|
||||
|
||||
struct OBSTACLE;
|
||||
|
||||
|
||||
struct COLLISION_SEARCH_OPTIONS
|
||||
{
|
||||
bool m_differentNetsOnly = true;
|
||||
int m_overrideClearance = -1;
|
||||
int m_limitCount = -1;
|
||||
int m_kindMask = -1;
|
||||
bool m_useClearanceEpsilon = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base class for PNS router board items.
|
||||
|
@ -194,7 +204,9 @@ public:
|
|||
* @param aOther is the item to check collision against.
|
||||
* @return true, if a collision was found.
|
||||
*/
|
||||
bool Collide( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOnly = true, int aOverrideClearance = -1 ) const;
|
||||
bool Collide( const ITEM* aOther, const NODE* aNode,
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts = COLLISION_SEARCH_OPTIONS(),
|
||||
OBSTACLE *aObsInfo = nullptr ) const;
|
||||
|
||||
/**
|
||||
* Return the geometrical shape of the item. Used for collision detection and spatial indexing.
|
||||
|
@ -248,7 +260,9 @@ public:
|
|||
virtual const std::string Format() const;
|
||||
|
||||
private:
|
||||
bool collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferentNetsOnly, int aOverrideClearance ) const;
|
||||
bool collideSimple( const ITEM* aOther, const NODE* aNode,
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts,
|
||||
OBSTACLE *aObsInfo = nullptr ) const;
|
||||
|
||||
protected:
|
||||
PnsKind m_kind;
|
||||
|
|
|
@ -211,23 +211,16 @@ bool OBSTACLE_VISITOR::visit( ITEM* aCandidate )
|
|||
// function object that visits potential obstacles and performs the actual collision refining
|
||||
struct NODE::DEFAULT_OBSTACLE_VISITOR : public OBSTACLE_VISITOR
|
||||
{
|
||||
OBSTACLES& m_tab;
|
||||
OBSTACLES& m_tab;
|
||||
int m_matchCount;
|
||||
const COLLISION_SEARCH_OPTIONS& m_opts;
|
||||
|
||||
int m_kindMask; ///< (solids, vias, segments, etc...)
|
||||
int m_limitCount;
|
||||
int m_matchCount;
|
||||
bool m_differentNetsOnly;
|
||||
int m_overrideClearance;
|
||||
|
||||
DEFAULT_OBSTACLE_VISITOR( NODE::OBSTACLES& aTab, const ITEM* aItem, int aKindMask,
|
||||
bool aDifferentNetsOnly, int aOverrideClearance ) :
|
||||
DEFAULT_OBSTACLE_VISITOR( NODE::OBSTACLES& aTab, const ITEM* aItem,
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts ) :
|
||||
OBSTACLE_VISITOR( aItem ),
|
||||
m_tab( aTab ),
|
||||
m_kindMask( aKindMask ),
|
||||
m_limitCount( -1 ),
|
||||
m_matchCount( 0 ),
|
||||
m_differentNetsOnly( aDifferentNetsOnly ),
|
||||
m_overrideClearance( aOverrideClearance )
|
||||
m_opts( aOpts ),
|
||||
m_matchCount( 0 )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -235,33 +228,28 @@ struct NODE::DEFAULT_OBSTACLE_VISITOR : public OBSTACLE_VISITOR
|
|||
{
|
||||
}
|
||||
|
||||
void SetCountLimit( int aLimit )
|
||||
{
|
||||
m_limitCount = aLimit;
|
||||
}
|
||||
|
||||
bool operator()( ITEM* aCandidate ) override
|
||||
{
|
||||
if( !aCandidate->OfKind( m_kindMask ) )
|
||||
if( !aCandidate->OfKind( m_opts.m_kindMask ) )
|
||||
return true;
|
||||
|
||||
if( visit( aCandidate ) )
|
||||
return true;
|
||||
|
||||
if( !aCandidate->Collide( m_item, m_node, m_differentNetsOnly, m_overrideClearance ) )
|
||||
if( !aCandidate->Collide( m_item, m_node, m_opts ) )
|
||||
return true;
|
||||
|
||||
OBSTACLE obs;
|
||||
|
||||
obs.m_item = aCandidate;
|
||||
obs.m_head = m_item;
|
||||
obs.m_item = aCandidate;
|
||||
obs.m_distFirst = INT_MAX;
|
||||
obs.m_maxFanoutWidth = 0;
|
||||
m_tab.push_back( obs );
|
||||
|
||||
m_matchCount++;
|
||||
|
||||
if( m_limitCount > 0 && m_matchCount >= m_limitCount )
|
||||
if( m_opts.m_limitCount > 0 && m_matchCount >= m_opts.m_limitCount )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -269,28 +257,26 @@ struct NODE::DEFAULT_OBSTACLE_VISITOR : public OBSTACLE_VISITOR
|
|||
};
|
||||
|
||||
|
||||
int NODE::QueryColliding( const ITEM* aItem, NODE::OBSTACLES& aObstacles, int aKindMask,
|
||||
int aLimitCount, bool aDifferentNetsOnly, int aOverrideClearance )
|
||||
int NODE::QueryColliding( const ITEM* aItem, NODE::OBSTACLES& aObstacles,
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts )
|
||||
{
|
||||
/// By default, virtual items cannot collide
|
||||
if( aItem->IsVirtual() )
|
||||
return 0;
|
||||
|
||||
DEFAULT_OBSTACLE_VISITOR visitor( aObstacles, aItem, aKindMask, aDifferentNetsOnly,
|
||||
aOverrideClearance );
|
||||
DEFAULT_OBSTACLE_VISITOR visitor( aObstacles, aItem, aOpts );
|
||||
|
||||
#ifdef DEBUG
|
||||
assert( allocNodes.find( this ) != allocNodes.end() );
|
||||
#endif
|
||||
|
||||
visitor.SetCountLimit( aLimitCount );
|
||||
visitor.SetWorld( this, nullptr );
|
||||
|
||||
// first, look for colliding items in the local index
|
||||
m_index->Query( aItem, m_maxClearance, visitor );
|
||||
|
||||
// if we haven't found enough items, look in the root branch as well.
|
||||
if( !isRoot() && ( visitor.m_matchCount < aLimitCount || aLimitCount < 0 ) )
|
||||
if( !isRoot() && ( visitor.m_matchCount < aOpts.m_limitCount || aOpts.m_limitCount < 0 ) )
|
||||
{
|
||||
visitor.SetWorld( m_root, this );
|
||||
m_root->m_index->Query( aItem, m_maxClearance, visitor );
|
||||
|
@ -302,8 +288,9 @@ int NODE::QueryColliding( const ITEM* aItem, NODE::OBSTACLES& aObstacles, int aK
|
|||
|
||||
NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask,
|
||||
const std::set<ITEM*>* aRestrictedSet,
|
||||
bool aUseClearanceEpsilon )
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts )
|
||||
{
|
||||
const int clearanceEpsilon = GetRuleResolver()->ClearanceEpsilon();
|
||||
OBSTACLES obstacleList;
|
||||
obstacleList.reserve( 100 );
|
||||
|
||||
|
@ -314,11 +301,11 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask,
|
|||
// Disabling the cache will lead to slowness.
|
||||
|
||||
const SEGMENT s( *aLine, aLine->CLine().CSegment( i ) );
|
||||
QueryColliding( &s, obstacleList, aKindMask );
|
||||
QueryColliding( &s, obstacleList, aOpts );
|
||||
}
|
||||
|
||||
if( aLine->EndsWithVia() )
|
||||
QueryColliding( &aLine->Via(), obstacleList, aKindMask );
|
||||
QueryColliding( &aLine->Via(), obstacleList, aOpts );
|
||||
|
||||
if( obstacleList.empty() )
|
||||
return OPT_OBSTACLE();
|
||||
|
@ -340,10 +327,12 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask,
|
|||
nearest.m_distFirst = dist;
|
||||
nearest.m_ipFirst = pt.p;
|
||||
nearest.m_item = obstacle;
|
||||
nearest.m_hull = hull;
|
||||
nearest.m_itemIsHole = isHole;
|
||||
// JEY TODO: are these no longer needed?
|
||||
//nearest.m_hull = hull;
|
||||
|
||||
obstacle->Mark( isHole ? obstacle->Marker() | MK_HOLE
|
||||
: obstacle->Marker() & ~MK_HOLE );
|
||||
//obstacle->Mark( isHole ? obstacle->Marker() | MK_HOLE
|
||||
// : obstacle->Marker() & ~MK_HOLE );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -358,7 +347,7 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask,
|
|||
continue;
|
||||
|
||||
int clearance =
|
||||
GetClearance( obstacle.m_item, aLine, aUseClearanceEpsilon ) + aLine->Width() / 2;
|
||||
GetClearance( obstacle.m_item, aLine, aOpts.m_useClearanceEpsilon ) + aLine->Width() / 2;
|
||||
|
||||
obstacleHull = obstacle.m_item->Hull( clearance, 0, layer );
|
||||
//debugDecorator->AddLine( obstacleHull, 2, 40000, "obstacle-hull-test" );
|
||||
|
@ -381,10 +370,10 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask,
|
|||
|
||||
int viaHoleRadius = static_cast<const SHAPE_CIRCLE*>( via.Hole() )->GetRadius();
|
||||
|
||||
int viaClearance = GetClearance( obstacle.m_item, &via, aUseClearanceEpsilon )
|
||||
int viaClearance = GetClearance( obstacle.m_item, &via, aOpts.m_useClearanceEpsilon )
|
||||
+ via.Diameter() / 2;
|
||||
int holeClearance =
|
||||
GetHoleClearance( obstacle.m_item, &via, aUseClearanceEpsilon ) + viaHoleRadius;
|
||||
int holeClearance = GetHoleClearance( obstacle.m_item, &via, aOpts.m_useClearanceEpsilon )
|
||||
+ viaHoleRadius;
|
||||
|
||||
if( holeClearance > viaClearance )
|
||||
viaClearance = holeClearance;
|
||||
|
@ -406,8 +395,8 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask,
|
|||
layer ) )
|
||||
&& obstacle.m_item->Hole() )
|
||||
{
|
||||
clearance = GetHoleClearance( obstacle.m_item, aLine, aUseClearanceEpsilon );
|
||||
int copperClearance = GetClearance( obstacle.m_item, aLine, aUseClearanceEpsilon );
|
||||
clearance = GetHoleClearance( obstacle.m_item, aLine, aOpts.m_useClearanceEpsilon );
|
||||
int copperClearance = GetClearance( obstacle.m_item, aLine, aOpts.m_useClearanceEpsilon );
|
||||
|
||||
clearance = std::max( clearance, copperClearance );
|
||||
|
||||
|
@ -425,12 +414,12 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask,
|
|||
// Don't use via.Drill(); it doesn't include the plating thickness
|
||||
int viaHoleRadius = static_cast<const SHAPE_CIRCLE*>( via.Hole() )->GetRadius();
|
||||
|
||||
int viaClearance = GetClearance( obstacle.m_item, &via, aUseClearanceEpsilon )
|
||||
int viaClearance = GetClearance( obstacle.m_item, &via, aOpts.m_useClearanceEpsilon )
|
||||
+ via.Diameter() / 2;
|
||||
int holeClearance = GetHoleClearance( obstacle.m_item, &via, aUseClearanceEpsilon )
|
||||
int holeClearance = GetHoleClearance( obstacle.m_item, &via, aOpts.m_useClearanceEpsilon )
|
||||
+ viaHoleRadius;
|
||||
int holeToHole =
|
||||
GetHoleToHoleClearance( obstacle.m_item, &via, aUseClearanceEpsilon )
|
||||
GetHoleToHoleClearance( obstacle.m_item, &via, aOpts.m_useClearanceEpsilon )
|
||||
+ viaHoleRadius;
|
||||
|
||||
if( holeClearance > viaClearance )
|
||||
|
@ -475,6 +464,11 @@ NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM_SET& aSet, int aKindMask )
|
|||
NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, int aKindMask )
|
||||
{
|
||||
OBSTACLES obs;
|
||||
COLLISION_SEARCH_OPTIONS opts;
|
||||
|
||||
opts.m_kindMask = aKindMask;
|
||||
opts.m_limitCount = 1;
|
||||
opts.m_overrideClearance = 1;
|
||||
|
||||
obs.reserve( 100 );
|
||||
|
||||
|
@ -491,7 +485,7 @@ NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, int aKindMask )
|
|||
// Disabling the cache will lead to slowness.
|
||||
|
||||
const SEGMENT s( *line, l.CSegment( i ) );
|
||||
n += QueryColliding( &s, obs, aKindMask, 1 );
|
||||
n += QueryColliding( &s, obs, opts );
|
||||
|
||||
if( n )
|
||||
return OPT_OBSTACLE( obs[0] );
|
||||
|
@ -499,13 +493,13 @@ NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, int aKindMask )
|
|||
|
||||
if( line->EndsWithVia() )
|
||||
{
|
||||
n += QueryColliding( &line->Via(), obs, aKindMask, 1 );
|
||||
n += QueryColliding( &line->Via(), obs, opts );
|
||||
|
||||
if( n )
|
||||
return OPT_OBSTACLE( obs[0] );
|
||||
}
|
||||
}
|
||||
else if( QueryColliding( aItemA, obs, aKindMask, 1 ) > 0 )
|
||||
else if( QueryColliding( aItemA, obs, opts ) > 0 )
|
||||
{
|
||||
return OPT_OBSTACLE( obs[0] );
|
||||
}
|
||||
|
|
|
@ -104,6 +104,11 @@ public:
|
|||
|
||||
virtual void ClearCacheForItem( const ITEM* aItem ) {}
|
||||
virtual void ClearCaches() {}
|
||||
|
||||
virtual int ClearanceEpsilon() const { return m_clearanceEpsilon; }
|
||||
|
||||
protected:
|
||||
int m_clearanceEpsilon = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -111,11 +116,15 @@ public:
|
|||
*/
|
||||
struct OBSTACLE
|
||||
{
|
||||
const ITEM* m_head; ///< Item we search collisions with
|
||||
|
||||
const ITEM* m_head; ///< Line we search collisions against
|
||||
ITEM* m_item; ///< Item found to be colliding with m_head
|
||||
SHAPE_LINE_CHAIN m_hull; ///< Hull of the colliding m_item
|
||||
VECTOR2I m_ipFirst; ///< First intersection between m_head and m_hull
|
||||
int m_clearance;
|
||||
int m_actual;
|
||||
int m_walkaroundThickness;
|
||||
bool m_headIsHole = false;
|
||||
bool m_itemIsHole = false;
|
||||
VECTOR2I m_pos;
|
||||
int m_distFirst; ///< ... and the distance thereof
|
||||
int m_maxFanoutWidth; ///< worst case (largest) width of the tracks connected to the item
|
||||
};
|
||||
|
@ -220,8 +229,8 @@ public:
|
|||
* @param aLimitCount stop looking for collisions after finding this number of colliding items
|
||||
* @return number of obstacles found
|
||||
*/
|
||||
int QueryColliding( const ITEM* aItem, OBSTACLES& aObstacles, int aKindMask = ITEM::ANY_T,
|
||||
int aLimitCount = -1, bool aDifferentNetsOnly = true, int aOverrideClearance = -1 );
|
||||
int QueryColliding( const ITEM* aItem, OBSTACLES& aObstacles,
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts = COLLISION_SEARCH_OPTIONS() );
|
||||
|
||||
int QueryJoints( const BOX2I& aBox, std::vector<JOINT*>& aJoints,
|
||||
LAYER_RANGE aLayerMask = LAYER_RANGE::All(), int aKindMask = ITEM::ANY_T );
|
||||
|
@ -233,12 +242,11 @@ public:
|
|||
* @param aLine the item to find collisions with
|
||||
* @param aKindMask mask of obstacle types to take into account
|
||||
* @param aRestrictedSet is an optional set of items that should be considered as obstacles
|
||||
* @param aUseClearanceEpsilon determines if the epsilon is subtracted from the hull size
|
||||
* @return the obstacle, if found, otherwise empty.
|
||||
*/
|
||||
OPT_OBSTACLE NearestObstacle( const LINE* aLine, int aKindMask = ITEM::ANY_T,
|
||||
const std::set<ITEM*>* aRestrictedSet = nullptr,
|
||||
bool aUseClearanceEpsilon = true );
|
||||
const COLLISION_SEARCH_OPTIONS& aOpts = COLLISION_SEARCH_OPTIONS() );
|
||||
|
||||
/**
|
||||
* Check if the item collides with anything else in the world, and if found, returns the
|
||||
|
@ -389,7 +397,7 @@ public:
|
|||
|
||||
void AllItemsInNet( int aNet, std::set<ITEM*>& aItems, int aKindMask = -1 );
|
||||
|
||||
void ClearRanks( int aMarkerMask = MK_HEAD | MK_VIOLATION | MK_HOLE );
|
||||
void ClearRanks( int aMarkerMask = MK_HEAD | MK_VIOLATION );
|
||||
|
||||
void RemoveByMarker( int aMarker );
|
||||
|
||||
|
|
|
@ -123,11 +123,15 @@ const ITEM_SET ROUTER::QueryHoverItems( const VECTOR2I& aP, bool aUseClearance )
|
|||
{
|
||||
if( aUseClearance )
|
||||
{
|
||||
SEGMENT test( SEG( aP, aP ), -1 );
|
||||
NODE::OBSTACLES obs;
|
||||
SEGMENT test( SEG( aP, aP ), -1 );
|
||||
COLLISION_SEARCH_OPTIONS opts;
|
||||
|
||||
test.SetWidth( 1 );
|
||||
test.SetLayers( LAYER_RANGE::All() );
|
||||
NODE::OBSTACLES obs;
|
||||
m_world->QueryColliding( &test, obs, ITEM::ANY_T, -1, false );
|
||||
|
||||
opts.m_differentNetsOnly = false;
|
||||
m_world->QueryColliding( &test, obs, opts );
|
||||
|
||||
PNS::ITEM_SET ret;
|
||||
|
||||
|
@ -629,8 +633,8 @@ void ROUTER::markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR&
|
|||
|
||||
int clearance;
|
||||
bool removeOriginal = true;
|
||||
bool holeOnly = ( ( itemToMark->Marker() & MK_HOLE )
|
||||
&& !( itemToMark->Marker() & MK_VIOLATION ) );
|
||||
bool holeOnly = false; // JEY TODO ( ( itemToMark->Marker() & MK_HOLE )
|
||||
//&& !( itemToMark->Marker() & MK_VIOLATION ) );
|
||||
|
||||
if( holeOnly )
|
||||
clearance = aNode->GetHoleClearance( currentItem, itemToMark );
|
||||
|
@ -673,7 +677,7 @@ void ROUTER::markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR&
|
|||
{
|
||||
NODE::OBSTACLES obstacles;
|
||||
|
||||
aNode->QueryColliding( item, obstacles, ITEM::ANY_T );
|
||||
aNode->QueryColliding( item, obstacles );
|
||||
|
||||
if( item->OfKind( ITEM::LINE_T ) )
|
||||
{
|
||||
|
@ -682,7 +686,7 @@ void ROUTER::markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR&
|
|||
if( l->EndsWithVia() )
|
||||
{
|
||||
VIA v( l->Via() );
|
||||
aNode->QueryColliding( &v, obstacles, ITEM::ANY_T );
|
||||
aNode->QueryColliding( &v, obstacles );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ enum DRAG_MODE
|
|||
virtual void Commit() = 0;
|
||||
virtual bool ImportSizes( SIZES_SETTINGS& aSizes, ITEM* aStartItem, int aNet ) = 0;
|
||||
virtual int StackupHeight( int aFirstLayer, int aSecondLayer ) const = 0;
|
||||
|
||||
virtual void EraseView() = 0;
|
||||
virtual void UpdateNet( int aNetCode ) = 0;
|
||||
|
||||
|
|
|
@ -538,6 +538,11 @@ const std::set<ITEM*> TOPOLOGY::AssembleCluster( ITEM* aStart, int aLayer )
|
|||
std::set<ITEM*> visited;
|
||||
std::deque<ITEM*> pending;
|
||||
|
||||
COLLISION_SEARCH_OPTIONS opts;
|
||||
|
||||
opts.m_differentNetsOnly = false;
|
||||
opts.m_overrideClearance = 0;
|
||||
|
||||
pending.push_back( aStart );
|
||||
|
||||
while( !pending.empty() )
|
||||
|
@ -549,7 +554,7 @@ const std::set<ITEM*> TOPOLOGY::AssembleCluster( ITEM* aStart, int aLayer )
|
|||
|
||||
visited.insert( top );
|
||||
|
||||
m_world->QueryColliding( top, obstacles, ITEM::ANY_T, -1, false, 0 ); // only query touching objects
|
||||
m_world->QueryColliding( top, obstacles, opts ); // only query touching objects
|
||||
|
||||
for( OBSTACLE& obs : obstacles )
|
||||
{
|
||||
|
|
|
@ -42,8 +42,13 @@ void WALKAROUND::start( const LINE& aInitialPath )
|
|||
|
||||
NODE::OPT_OBSTACLE WALKAROUND::nearestObstacle( const LINE& aPath )
|
||||
{
|
||||
NODE::OPT_OBSTACLE obs = m_world->NearestObstacle(
|
||||
&aPath, m_itemMask, m_restrictedSet.empty() ? nullptr : &m_restrictedSet, false );
|
||||
COLLISION_SEARCH_OPTIONS opts;
|
||||
opts.m_useClearanceEpsilon = false;
|
||||
|
||||
NODE::OPT_OBSTACLE obs = m_world->NearestObstacle( &aPath, m_itemMask,
|
||||
m_restrictedSet.empty() ? nullptr
|
||||
: &m_restrictedSet,
|
||||
opts );
|
||||
|
||||
if( m_restrictedSet.empty() )
|
||||
return obs;
|
||||
|
@ -86,10 +91,14 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::singleStep( LINE& aPath, bool aWinding
|
|||
|
||||
SHAPE_LINE_CHAIN path_walk;
|
||||
|
||||
bool s_cw = aPath.Walkaround( current_obs->m_hull, path_walk, aWindingDirection );
|
||||
|
||||
SHAPE_LINE_CHAIN hull = current_obs->m_item->Hull( current_obs->m_clearance,
|
||||
current_obs->m_walkaroundThickness );
|
||||
|
||||
bool s_cw = aPath.Walkaround( hull, path_walk, aWindingDirection );
|
||||
|
||||
PNS_DBG( Dbg(), BeginGroup, "hull/walk", 1 );
|
||||
PNS_DBG( Dbg(), AddShape, ¤t_obs->m_hull, RED, 0, wxString::Format( "hull-%s-%d", aWindingDirection ? wxT( "cw" ) : wxT( "ccw" ), m_iteration ) );
|
||||
PNS_DBG( Dbg(), AddShape, &hull, RED, 0, wxString::Format( "hull-%s-%d", aWindingDirection ? wxT( "cw" ) : wxT( "ccw" ), m_iteration ) );
|
||||
PNS_DBG( Dbg(), AddShape, &aPath.CLine(), GREEN, 0, wxString::Format( "path-%s-%d", aWindingDirection ? wxT( "cw" ) : wxT( "ccw" ), m_iteration ) );
|
||||
PNS_DBG( Dbg(), AddShape, &path_walk, BLUE, 0, wxString::Format( "result-%s-%d", aWindingDirection ? wxT( "cw" ) : wxT( "ccw" ), m_iteration ) );
|
||||
PNS_DBG( Dbg(), Message, wxString::Format( wxT( "Stat cw %d" ), !!s_cw ) );
|
||||
|
@ -100,8 +109,7 @@ WALKAROUND::WALKAROUND_STATUS WALKAROUND::singleStep( LINE& aPath, bool aWinding
|
|||
|
||||
// If the end of the line is inside an obstacle, additional walkaround iterations are not
|
||||
// going to help. Exit now to prevent pegging the iteration limiter and causing lag.
|
||||
if( current_obs && current_obs->m_hull.PointInside( initialLast ) &&
|
||||
!current_obs->m_hull.PointOnEdge( initialLast ) )
|
||||
if( current_obs && hull.PointInside( initialLast ) && !hull.PointOnEdge( initialLast ) )
|
||||
{
|
||||
return ALMOST_DONE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue