router: improvements to shove algorithm
This commit is contained in:
parent
95c59c8060
commit
a96299d456
|
@ -282,6 +282,12 @@ static inline bool Collide( const SHAPE_CONVEX& aA, const SHAPE_SEGMENT& aB, int
|
||||||
return Collide( aA.Vertices(), aB, aClearance, aNeedMTV, aMTV );
|
return Collide( aA.Vertices(), aB, aClearance, aNeedMTV, aMTV );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool Collide( const SHAPE_RECT& aA, const SHAPE_RECT& aB, int aClearance,
|
||||||
|
bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
{
|
||||||
|
return Collide( aA.Outline(), aB.Outline(), aClearance, aNeedMTV, aMTV );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class ShapeAType, class ShapeBType>
|
template<class ShapeAType, class ShapeBType>
|
||||||
inline bool CollCase( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
|
inline bool CollCase( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeedMTV, VECTOR2I& aMTV )
|
||||||
|
@ -310,11 +316,8 @@ bool CollideShapes( const SHAPE* aA, const SHAPE* aB, int aClearance, bool aNeed
|
||||||
case SH_RECT:
|
case SH_RECT:
|
||||||
switch( aB->Type() )
|
switch( aB->Type() )
|
||||||
{
|
{
|
||||||
case SH_RECT: // RECT to RECT not yet in use in p&s router
|
case SH_RECT:
|
||||||
// Should be (todo) somethink like:
|
return CollCase<SHAPE_RECT, SHAPE_RECT>( aA, aB, aClearance, aNeedMTV, aMTV );
|
||||||
//return CollCaseReversed<SHAPE_RECT, SHAPE_RECT>( aA, aB, aClearance, aNeedMTV, aMTV );
|
|
||||||
assert( aB->Type() != SH_RECT );
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SH_CIRCLE:
|
case SH_CIRCLE:
|
||||||
return CollCase<SHAPE_RECT, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
|
return CollCase<SHAPE_RECT, SHAPE_CIRCLE>( aA, aB, aClearance, aNeedMTV, aMTV );
|
||||||
|
|
|
@ -206,8 +206,6 @@ const SHAPE_LINE_CHAIN SHAPE_POLY_SET::convertFromClipper( const Path& aPath )
|
||||||
return lc;
|
return lc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <common.h>
|
|
||||||
#include <wx/wx.h>
|
|
||||||
void SHAPE_POLY_SET::booleanOp( ClipType aType, const SHAPE_POLY_SET& aOtherShape,
|
void SHAPE_POLY_SET::booleanOp( ClipType aType, const SHAPE_POLY_SET& aOtherShape,
|
||||||
bool aFastMode )
|
bool aFastMode )
|
||||||
{
|
{
|
||||||
|
|
|
@ -142,6 +142,18 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SHAPE_LINE_CHAIN Outline() const
|
||||||
|
{
|
||||||
|
SHAPE_LINE_CHAIN rv;
|
||||||
|
rv.Append( m_p0 );
|
||||||
|
rv.Append( m_p0.x, m_p0.y + m_w );
|
||||||
|
rv.Append( m_p0.x + m_h, m_p0.y + m_w );
|
||||||
|
rv.Append( m_p0.x + m_h, m_p0.y );
|
||||||
|
rv.Append( m_p0 );
|
||||||
|
rv.SetClosed( true );
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///> Top-left corner
|
///> Top-left corner
|
||||||
VECTOR2I m_p0;
|
VECTOR2I m_p0;
|
||||||
|
|
|
@ -22,10 +22,10 @@
|
||||||
#include "pns_line.h"
|
#include "pns_line.h"
|
||||||
|
|
||||||
bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||||
VECTOR2I& aMTV ) const
|
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const
|
||||||
{
|
{
|
||||||
// same nets? no collision!
|
// same nets? no collision!
|
||||||
if( m_net == aOther->m_net )
|
if( aDifferentNetsOnly && m_net == aOther->m_net )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// check if we are not on completely different layers first
|
// check if we are not on completely different layers first
|
||||||
|
@ -39,9 +39,9 @@ bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeed
|
||||||
|
|
||||||
|
|
||||||
bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||||
VECTOR2I& aMTV ) const
|
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const
|
||||||
{
|
{
|
||||||
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) )
|
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV, aDifferentNetsOnly ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// special case for "head" line with a via attached at the end.
|
// special case for "head" line with a via attached at the end.
|
||||||
|
@ -50,7 +50,7 @@ bool PNS_ITEM::Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||||
const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
|
const PNS_LINE* line = static_cast<const PNS_LINE*>( aOther );
|
||||||
|
|
||||||
if( line->EndsWithVia() )
|
if( line->EndsWithVia() )
|
||||||
return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, aMTV );
|
return collideSimple( &line->Via(), aClearance - line->Width() / 2, aNeedMTV, aMTV, aDifferentNetsOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -270,18 +270,18 @@ public:
|
||||||
* @return true, if a collision was found.
|
* @return true, if a collision was found.
|
||||||
*/
|
*/
|
||||||
virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||||
VECTOR2I& aMTV ) const;
|
VECTOR2I& aMTV, bool aDifferentNetsOnly = true ) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function Collide()
|
* Function Collide()
|
||||||
*
|
*
|
||||||
* A shortcut for PNS_ITEM::Colllide() without MTV stuff.
|
* A shortcut for PNS_ITEM::Colllide() without MTV stuff.
|
||||||
*/
|
*/
|
||||||
bool Collide( const PNS_ITEM* aOther, int aClearance ) const
|
bool Collide( const PNS_ITEM* aOther, int aClearance, bool aDifferentNetsOnly = true ) const
|
||||||
{
|
{
|
||||||
VECTOR2I dummy;
|
VECTOR2I dummy;
|
||||||
|
|
||||||
return Collide( aOther, aClearance, false, dummy );
|
return Collide( aOther, aClearance, false, dummy, aDifferentNetsOnly );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -332,7 +332,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||||
VECTOR2I& aMTV ) const;
|
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PnsKind m_kind;
|
PnsKind m_kind;
|
||||||
|
|
|
@ -477,8 +477,13 @@ bool PNS_LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
||||||
|
|
||||||
m_currentNode = m_shove->CurrentNode();
|
m_currentNode = m_shove->CurrentNode();
|
||||||
|
|
||||||
if( status == PNS_SHOVE::SH_OK )
|
if( status == PNS_SHOVE::SH_OK || status == PNS_SHOVE::SH_HEAD_MODIFIED )
|
||||||
{
|
{
|
||||||
|
if( status == PNS_SHOVE::SH_HEAD_MODIFIED )
|
||||||
|
{
|
||||||
|
l2 = m_shove->NewHead();
|
||||||
|
}
|
||||||
|
|
||||||
optimizer.SetWorld( m_currentNode );
|
optimizer.SetWorld( m_currentNode );
|
||||||
optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS );
|
optimizer.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS );
|
||||||
optimizer.SetCollisionMask( PNS_ITEM::ANY );
|
optimizer.SetCollisionMask( PNS_ITEM::ANY );
|
||||||
|
@ -1087,3 +1092,11 @@ void PNS_LINE_PLACER::GetModifiedNets( std::vector<int>& aNets ) const
|
||||||
{
|
{
|
||||||
aNets.push_back( m_currentNet );
|
aNets.push_back( m_currentNet );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PNS_LOGGER* PNS_LINE_PLACER::Logger()
|
||||||
|
{
|
||||||
|
if( m_shove )
|
||||||
|
return m_shove->Logger();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
|
@ -184,6 +184,10 @@ public:
|
||||||
bool IsPlacingVia() const { return m_placingVia; }
|
bool IsPlacingVia() const { return m_placingVia; }
|
||||||
|
|
||||||
void GetModifiedNets( std::vector<int>& aNets ) const;
|
void GetModifiedNets( std::vector<int>& aNets ) const;
|
||||||
|
|
||||||
|
PNS_LOGGER* Logger();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Function route()
|
* Function route()
|
||||||
|
|
|
@ -185,7 +185,11 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
||||||
///> additional clearance
|
///> additional clearance
|
||||||
int m_extraClearance;
|
int m_extraClearance;
|
||||||
|
|
||||||
OBSTACLE_VISITOR( PNS_NODE::OBSTACLES& aTab, const PNS_ITEM* aItem, int aKindMask ) :
|
bool m_differentNetsOnly;
|
||||||
|
|
||||||
|
int m_forceClearance;
|
||||||
|
|
||||||
|
OBSTACLE_VISITOR( PNS_NODE::OBSTACLES& aTab, const PNS_ITEM* aItem, int aKindMask, bool aDifferentNetsOnly ) :
|
||||||
m_node( NULL ),
|
m_node( NULL ),
|
||||||
m_override( NULL ),
|
m_override( NULL ),
|
||||||
m_tab( aTab ),
|
m_tab( aTab ),
|
||||||
|
@ -193,7 +197,9 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
||||||
m_kindMask( aKindMask ),
|
m_kindMask( aKindMask ),
|
||||||
m_limitCount( -1 ),
|
m_limitCount( -1 ),
|
||||||
m_matchCount( 0 ),
|
m_matchCount( 0 ),
|
||||||
m_extraClearance( 0 )
|
m_extraClearance( 0 ),
|
||||||
|
m_differentNetsOnly( aDifferentNetsOnly ),
|
||||||
|
m_forceClearance( -1 )
|
||||||
{
|
{
|
||||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
if( aItem->Kind() == PNS_ITEM::LINE )
|
||||||
m_extraClearance += static_cast<const PNS_LINE*>( aItem )->Width() / 2;
|
m_extraClearance += static_cast<const PNS_LINE*>( aItem )->Width() / 2;
|
||||||
|
@ -228,7 +234,10 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
||||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
if( aItem->Kind() == PNS_ITEM::LINE )
|
||||||
clearance += static_cast<PNS_LINE*>( aItem )->Width() / 2;
|
clearance += static_cast<PNS_LINE*>( aItem )->Width() / 2;
|
||||||
|
|
||||||
if( !aItem->Collide( m_item, clearance ) )
|
if( m_forceClearance >= 0 )
|
||||||
|
clearance = m_forceClearance;
|
||||||
|
|
||||||
|
if( !aItem->Collide( m_item, clearance, m_differentNetsOnly ) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
PNS_OBSTACLE obs;
|
PNS_OBSTACLE obs;
|
||||||
|
@ -248,9 +257,9 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
||||||
|
|
||||||
|
|
||||||
int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
||||||
PNS_NODE::OBSTACLES& aObstacles, int aKindMask, int aLimitCount )
|
PNS_NODE::OBSTACLES& aObstacles, int aKindMask, int aLimitCount, bool aDifferentNetsOnly, int aForceClearance )
|
||||||
{
|
{
|
||||||
OBSTACLE_VISITOR visitor( aObstacles, aItem, aKindMask );
|
OBSTACLE_VISITOR visitor( aObstacles, aItem, aKindMask, aDifferentNetsOnly );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert( allocNodes.find( this ) != allocNodes.end() );
|
assert( allocNodes.find( this ) != allocNodes.end() );
|
||||||
|
@ -258,7 +267,7 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
||||||
|
|
||||||
visitor.SetCountLimit( aLimitCount );
|
visitor.SetCountLimit( aLimitCount );
|
||||||
visitor.SetWorld( this, NULL );
|
visitor.SetWorld( this, NULL );
|
||||||
|
visitor.m_forceClearance = aForceClearance;
|
||||||
// first, look for colliding items in the local index
|
// first, look for colliding items in the local index
|
||||||
m_index->Query( aItem, m_maxClearance, visitor );
|
m_index->Query( aItem, m_maxClearance, visitor );
|
||||||
|
|
||||||
|
@ -273,7 +282,9 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PNS_NODE::OPT_OBSTACLE PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKindMask )
|
PNS_NODE::OPT_OBSTACLE PNS_NODE::NearestObstacle( const PNS_LINE* aItem,
|
||||||
|
int aKindMask,
|
||||||
|
const std::set<PNS_ITEM*>* aRestrictedSet )
|
||||||
{
|
{
|
||||||
OBSTACLES obs_list;
|
OBSTACLES obs_list;
|
||||||
bool found_isects = false;
|
bool found_isects = false;
|
||||||
|
@ -293,7 +304,6 @@ PNS_NODE::OPT_OBSTACLE PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKi
|
||||||
if( aItem->EndsWithVia() )
|
if( aItem->EndsWithVia() )
|
||||||
n += QueryColliding( &aItem->Via(), obs_list, aKindMask );
|
n += QueryColliding( &aItem->Via(), obs_list, aKindMask );
|
||||||
|
|
||||||
// if(! QueryColliding ( aItem, obs_list, aKindMask ))
|
|
||||||
if( !n )
|
if( !n )
|
||||||
return OPT_OBSTACLE();
|
return OPT_OBSTACLE();
|
||||||
|
|
||||||
|
@ -308,6 +318,9 @@ PNS_NODE::OPT_OBSTACLE PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKi
|
||||||
VECTOR2I ip_first, ip_last;
|
VECTOR2I ip_first, ip_last;
|
||||||
int dist_max = INT_MIN;
|
int dist_max = INT_MIN;
|
||||||
|
|
||||||
|
if( aRestrictedSet && aRestrictedSet->find( obs.m_item ) == aRestrictedSet->end() )
|
||||||
|
continue;
|
||||||
|
|
||||||
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> isect_list;
|
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> isect_list;
|
||||||
|
|
||||||
int clearance = GetClearance( obs.m_item, &aLine );
|
int clearance = GetClearance( obs.m_item, &aLine );
|
||||||
|
|
|
@ -184,7 +184,9 @@ public:
|
||||||
int QueryColliding( const PNS_ITEM* aItem,
|
int QueryColliding( const PNS_ITEM* aItem,
|
||||||
OBSTACLES& aObstacles,
|
OBSTACLES& aObstacles,
|
||||||
int aKindMask = PNS_ITEM::ANY,
|
int aKindMask = PNS_ITEM::ANY,
|
||||||
int aLimitCount = -1 );
|
int aLimitCount = -1,
|
||||||
|
bool aDifferentNetsOnly = true,
|
||||||
|
int aForceClearance = -1 );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function NearestObstacle()
|
* Function NearestObstacle()
|
||||||
|
@ -195,8 +197,9 @@ public:
|
||||||
* @param aKindMask mask of obstacle types to take into account
|
* @param aKindMask mask of obstacle types to take into account
|
||||||
* @return the obstacle, if found, otherwise empty.
|
* @return the obstacle, if found, otherwise empty.
|
||||||
*/
|
*/
|
||||||
OPT_OBSTACLE NearestObstacle( const PNS_LINE* aItem,
|
OPT_OBSTACLE NearestObstacle( const PNS_LINE* aItem,
|
||||||
int aKindMask = PNS_ITEM::ANY );
|
int aKindMask = PNS_ITEM::ANY,
|
||||||
|
const std::set<PNS_ITEM*>* aRestrictedSet = NULL );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function CheckColliding()
|
* Function CheckColliding()
|
||||||
|
|
|
@ -125,6 +125,9 @@ int PNS_PCBNEW_CLEARANCE_FUNC::operator()( const PNS_ITEM* aA, const PNS_ITEM* a
|
||||||
|
|
||||||
bool linesOnly = aA->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE ) && aB->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE );
|
bool linesOnly = aA->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE ) && aB->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE );
|
||||||
|
|
||||||
|
if( net_a == net_b )
|
||||||
|
return 0;
|
||||||
|
|
||||||
if( linesOnly && net_a >= 0 && net_b >= 0 && m_clearanceCache[net_a].coupledNet == net_b )
|
if( linesOnly && net_a >= 0 && net_b >= 0 && m_clearanceCache[net_a].coupledNet == net_b )
|
||||||
{
|
{
|
||||||
cl_a = cl_b = m_router->Sizes().DiffPairGap() - 2 * PNS_HULL_MARGIN;
|
cl_a = cl_b = m_router->Sizes().DiffPairGap() - 2 * PNS_HULL_MARGIN;
|
||||||
|
@ -1041,6 +1044,10 @@ void PNS_ROUTER::DumpLog()
|
||||||
logger = m_dragger->Logger();
|
logger = m_dragger->Logger();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ROUTE_TRACK:
|
||||||
|
logger = m_placer->Logger();
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "pns_router.h"
|
#include "pns_router.h"
|
||||||
#include "pns_shove.h"
|
#include "pns_shove.h"
|
||||||
#include "pns_utils.h"
|
#include "pns_utils.h"
|
||||||
|
#include "pns_topology.h"
|
||||||
|
|
||||||
#include "time_limit.h"
|
#include "time_limit.h"
|
||||||
|
|
||||||
|
@ -242,7 +243,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::processHullSet( PNS_LINE& aCurrent, PNS_LINE&
|
||||||
return SH_OK;
|
return SH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return failingDirCheck ? SH_OK : SH_INCOMPLETE;
|
return SH_INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -277,7 +278,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::ProcessSingleLine( PNS_LINE& aCurrent, PNS_LI
|
||||||
int w = aObstacle.Width();
|
int w = aObstacle.Width();
|
||||||
int n_segs = aCurrent.SegmentCount();
|
int n_segs = aCurrent.SegmentCount();
|
||||||
|
|
||||||
int clearance = getClearance( &aCurrent, &aObstacle );
|
int clearance = getClearance( &aCurrent, &aObstacle ) + 1;
|
||||||
|
|
||||||
HULL_SET hulls;
|
HULL_SET hulls;
|
||||||
|
|
||||||
|
@ -313,6 +314,18 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSegment( PNS_LINE& aCurrent, PNS_S
|
||||||
|
|
||||||
SHOVE_STATUS rv = ProcessSingleLine( aCurrent, obstacleLine, shovedLine );
|
SHOVE_STATUS rv = ProcessSingleLine( aCurrent, obstacleLine, shovedLine );
|
||||||
|
|
||||||
|
const double extensionWalkThreshold = 1.0;
|
||||||
|
|
||||||
|
double obsLen = obstacleLine.CLine().Length();
|
||||||
|
double shovedLen = shovedLine.CLine().Length();
|
||||||
|
double extensionFactor = 0.0;
|
||||||
|
|
||||||
|
if( obsLen != 0.0f )
|
||||||
|
extensionFactor = shovedLen / obsLen - 1.0;
|
||||||
|
|
||||||
|
if( extensionFactor > extensionWalkThreshold )
|
||||||
|
return SH_TRY_WALK;
|
||||||
|
|
||||||
assert( obstacleLine.LayersOverlap( &shovedLine ) );
|
assert( obstacleLine.LayersOverlap( &shovedLine ) );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -333,12 +346,12 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSegment( PNS_LINE& aCurrent, PNS_S
|
||||||
m_newHead = shovedLine;
|
m_newHead = shovedLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
sanityCheck( &obstacleLine, &shovedLine );
|
|
||||||
replaceItems( &obstacleLine, &shovedLine );
|
|
||||||
|
|
||||||
int rank = aCurrent.Rank();
|
int rank = aCurrent.Rank();
|
||||||
shovedLine.SetRank( rank - 1 );
|
shovedLine.SetRank( rank - 1 );
|
||||||
|
|
||||||
|
sanityCheck( &obstacleLine, &shovedLine );
|
||||||
|
replaceItems( &obstacleLine, &shovedLine );
|
||||||
|
|
||||||
if( !pushLine( shovedLine ) )
|
if( !pushLine( shovedLine ) )
|
||||||
rv = SH_INCOMPLETE;
|
rv = SH_INCOMPLETE;
|
||||||
}
|
}
|
||||||
|
@ -380,15 +393,13 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingLine( PNS_LINE& aCurrent, PNS_LINE
|
||||||
if( !pushLine( shovedLine ) )
|
if( !pushLine( shovedLine ) )
|
||||||
{
|
{
|
||||||
rv = SH_INCOMPLETE;
|
rv = SH_INCOMPLETE;
|
||||||
//printf( "pushLine failed\n" );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE& aCurrent, PNS_ITEM* aObstacle )
|
||||||
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE& aCurrent, PNS_SOLID* aObstacleSolid )
|
|
||||||
{
|
{
|
||||||
PNS_WALKAROUND walkaround( m_currentNode, Router() );
|
PNS_WALKAROUND walkaround( m_currentNode, Router() );
|
||||||
PNS_LINE walkaroundLine( aCurrent );
|
PNS_LINE walkaroundLine( aCurrent );
|
||||||
|
@ -411,54 +422,87 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE& aCurrent, PNS_SOL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( via && m_currentNode->CheckColliding( via, aObstacleSolid ) )
|
if( via && m_currentNode->CheckColliding( via, aObstacle ) )
|
||||||
return onCollidingVia( aObstacleSolid, via );
|
return onCollidingVia( aObstacle, via );
|
||||||
}
|
}
|
||||||
|
|
||||||
walkaround.SetSolidsOnly( true );
|
PNS_TOPOLOGY topo( m_currentNode );
|
||||||
walkaround.SetIterationLimit ( 8 ); // fixme: make configurable
|
|
||||||
|
std::set<PNS_ITEM*> cluster = topo.AssembleCluster( aObstacle, aCurrent.Layers().Start() );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
m_logger.NewGroup( "on-colliding-solid-cluster", m_iter );
|
||||||
|
BOOST_FOREACH( PNS_ITEM* item, cluster )
|
||||||
|
{
|
||||||
|
m_logger.Log( item, 0, "cluster-entry" );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
walkaround.SetSolidsOnly( false );
|
||||||
|
walkaround.RestrictToSet( true, cluster );
|
||||||
|
walkaround.SetIterationLimit( 16 ); // fixme: make configurable
|
||||||
|
|
||||||
int currentRank = aCurrent.Rank();
|
int currentRank = aCurrent.Rank();
|
||||||
int nextRank;
|
int nextRank;
|
||||||
|
|
||||||
if( !Settings().JumpOverObstacles() )
|
for( int attempt = 0; attempt < 2; attempt++ )
|
||||||
{
|
{
|
||||||
nextRank = currentRank + 10000;
|
|
||||||
walkaround.SetSingleDirection( false );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nextRank = currentRank - 1;
|
|
||||||
walkaround.SetSingleDirection( true );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( walkaround.Route( aCurrent, walkaroundLine, false ) != PNS_WALKAROUND::DONE )
|
if( attempt == 1 || Settings().JumpOverObstacles() )
|
||||||
return SH_INCOMPLETE;
|
{
|
||||||
|
nextRank = currentRank - 1;
|
||||||
|
walkaround.SetSingleDirection( true );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextRank = currentRank + 10000;
|
||||||
|
walkaround.SetSingleDirection( false );
|
||||||
|
}
|
||||||
|
|
||||||
walkaroundLine.ClearSegmentLinks();
|
|
||||||
walkaroundLine.Unmark();
|
|
||||||
walkaroundLine.Line().Simplify();
|
|
||||||
|
|
||||||
if( walkaroundLine.HasLoops() )
|
if( walkaround.Route( aCurrent, walkaroundLine, false ) != PNS_WALKAROUND::DONE )
|
||||||
return SH_INCOMPLETE;
|
|
||||||
|
|
||||||
if( aCurrent.Marker() & MK_HEAD )
|
|
||||||
{
|
|
||||||
walkaroundLine.Mark( MK_HEAD );
|
|
||||||
|
|
||||||
if( m_multiLineMode )
|
|
||||||
return SH_INCOMPLETE;
|
return SH_INCOMPLETE;
|
||||||
|
|
||||||
m_newHead = walkaroundLine;
|
walkaroundLine.ClearSegmentLinks();
|
||||||
|
walkaroundLine.Unmark();
|
||||||
|
walkaroundLine.Line().Simplify();
|
||||||
|
|
||||||
|
if( walkaroundLine.HasLoops() )
|
||||||
|
return SH_INCOMPLETE;
|
||||||
|
|
||||||
|
if( aCurrent.Marker() & MK_HEAD )
|
||||||
|
{
|
||||||
|
walkaroundLine.Mark( MK_HEAD );
|
||||||
|
|
||||||
|
if( m_multiLineMode )
|
||||||
|
return SH_INCOMPLETE;
|
||||||
|
|
||||||
|
m_newHead = walkaroundLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
sanityCheck( &aCurrent, &walkaroundLine );
|
||||||
|
|
||||||
|
if( !m_lineStack.empty() )
|
||||||
|
{
|
||||||
|
PNS_LINE lastLine = m_lineStack.front();
|
||||||
|
|
||||||
|
if( m_currentNode->CheckColliding( &lastLine, &walkaroundLine ) )
|
||||||
|
{
|
||||||
|
PNS_LINE dummy ( lastLine );
|
||||||
|
|
||||||
|
if( ProcessSingleLine( walkaroundLine, lastLine, dummy ) == SH_OK )
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sanityCheck( &aCurrent, &walkaroundLine );
|
|
||||||
replaceItems( &aCurrent, &walkaroundLine );
|
replaceItems( &aCurrent, &walkaroundLine );
|
||||||
walkaroundLine.SetRank( nextRank );
|
walkaroundLine.SetRank( nextRank );
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
m_logger.NewGroup( "on-colliding-solid", m_iter );
|
m_logger.NewGroup( "on-colliding-solid", m_iter );
|
||||||
m_logger.Log( aObstacleSolid, 0, "obstacle-solid" );
|
m_logger.Log( aObstacle, 0, "obstacle-solid" );
|
||||||
m_logger.Log( &aCurrent, 1, "current-line" );
|
m_logger.Log( &aCurrent, 1, "current-line" );
|
||||||
m_logger.Log( &walkaroundLine, 3, "walk-line" );
|
m_logger.Log( &walkaroundLine, 3, "walk-line" );
|
||||||
#endif
|
#endif
|
||||||
|
@ -620,7 +664,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
|
||||||
replaceItems( &lp.first, &lp.second );
|
replaceItems( &lp.first, &lp.second );
|
||||||
lp.second.SetRank( aCurrentRank - 1 );
|
lp.second.SetRank( aCurrentRank - 1 );
|
||||||
|
|
||||||
if( !pushLine( lp.second ) )
|
if( !pushLine( lp.second, true ) )
|
||||||
return SH_INCOMPLETE;
|
return SH_INCOMPLETE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -807,12 +851,20 @@ void PNS_SHOVE::unwindStack( PNS_ITEM* aItem )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PNS_SHOVE::pushLine( const PNS_LINE& aL )
|
bool PNS_SHOVE::pushLine( const PNS_LINE& aL, bool aKeepCurrentOnTop )
|
||||||
{
|
{
|
||||||
if( aL.LinkCount() >= 0 && ( aL.LinkCount() != aL.SegmentCount() ) )
|
if( aL.LinkCount() >= 0 && ( aL.LinkCount() != aL.SegmentCount() ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_lineStack.push_back( aL );
|
if( aKeepCurrentOnTop && m_lineStack.size() > 0)
|
||||||
|
{
|
||||||
|
m_lineStack.insert( m_lineStack.begin() + m_lineStack.size() - 1, aL );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_lineStack.push_back( aL );
|
||||||
|
}
|
||||||
|
|
||||||
m_optimizerQueue.push_back( aL );
|
m_optimizerQueue.push_back( aL );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -919,6 +971,11 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
|
||||||
case PNS_ITEM::SEGMENT:
|
case PNS_ITEM::SEGMENT:
|
||||||
TRACE( 2, "iter %d: collide-segment ", aIter );
|
TRACE( 2, "iter %d: collide-segment ", aIter );
|
||||||
st = onCollidingSegment( currentLine, (PNS_SEGMENT*) ni );
|
st = onCollidingSegment( currentLine, (PNS_SEGMENT*) ni );
|
||||||
|
|
||||||
|
if( st == SH_TRY_WALK )
|
||||||
|
{
|
||||||
|
st = onCollidingSolid( currentLine, (PNS_SOLID*) ni );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNS_ITEM::VIA:
|
case PNS_ITEM::VIA:
|
||||||
|
|
|
@ -49,7 +49,8 @@ public:
|
||||||
SH_OK = 0,
|
SH_OK = 0,
|
||||||
SH_NULL,
|
SH_NULL,
|
||||||
SH_INCOMPLETE,
|
SH_INCOMPLETE,
|
||||||
SH_HEAD_MODIFIED
|
SH_HEAD_MODIFIED,
|
||||||
|
SH_TRY_WALK
|
||||||
};
|
};
|
||||||
|
|
||||||
PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter );
|
PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter );
|
||||||
|
@ -110,7 +111,7 @@ private:
|
||||||
|
|
||||||
SHOVE_STATUS onCollidingLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle );
|
SHOVE_STATUS onCollidingLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle );
|
||||||
SHOVE_STATUS onCollidingSegment( PNS_LINE& aCurrent, PNS_SEGMENT* aObstacleSeg );
|
SHOVE_STATUS onCollidingSegment( PNS_LINE& aCurrent, PNS_SEGMENT* aObstacleSeg );
|
||||||
SHOVE_STATUS onCollidingSolid( PNS_LINE& aCurrent, PNS_SOLID* aObstacleSolid );
|
SHOVE_STATUS onCollidingSolid( PNS_LINE& aCurrent, PNS_ITEM* aObstacle );
|
||||||
SHOVE_STATUS onCollidingVia( PNS_ITEM* aCurrent, PNS_VIA* aObstacleVia );
|
SHOVE_STATUS onCollidingVia( PNS_ITEM* aCurrent, PNS_VIA* aObstacleVia );
|
||||||
SHOVE_STATUS onReverseCollidingVia( PNS_LINE& aCurrent, PNS_VIA* aObstacleVia );
|
SHOVE_STATUS onReverseCollidingVia( PNS_LINE& aCurrent, PNS_VIA* aObstacleVia );
|
||||||
SHOVE_STATUS pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank, bool aDryRun = false );
|
SHOVE_STATUS pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank, bool aDryRun = false );
|
||||||
|
@ -122,7 +123,7 @@ private:
|
||||||
|
|
||||||
void runOptimizer( PNS_NODE* aNode );
|
void runOptimizer( PNS_NODE* aNode );
|
||||||
|
|
||||||
bool pushLine( const PNS_LINE& aL );
|
bool pushLine( const PNS_LINE& aL, bool aKeepCurrentOnTop = false );
|
||||||
void popLine();
|
void popLine();
|
||||||
|
|
||||||
PNS_LINE assembleLine( const PNS_SEGMENT* aSeg, int* aIndex = NULL );
|
PNS_LINE assembleLine( const PNS_SEGMENT* aSeg, int* aIndex = NULL );
|
||||||
|
|
|
@ -396,3 +396,34 @@ bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair )
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::set<PNS_ITEM*> PNS_TOPOLOGY::AssembleCluster( PNS_ITEM* aStart, int aLayer )
|
||||||
|
{
|
||||||
|
std::set<PNS_ITEM*> visited;
|
||||||
|
std::deque<PNS_ITEM*> pending;
|
||||||
|
|
||||||
|
pending.push_back( aStart );
|
||||||
|
|
||||||
|
while( !pending.empty() )
|
||||||
|
{
|
||||||
|
PNS_NODE::OBSTACLES obstacles;
|
||||||
|
PNS_ITEM* top = pending.front();
|
||||||
|
|
||||||
|
pending.pop_front();
|
||||||
|
|
||||||
|
visited.insert( top );
|
||||||
|
|
||||||
|
m_world->QueryColliding( top, obstacles, PNS_ITEM::ANY, -1, false, 0 );
|
||||||
|
|
||||||
|
BOOST_FOREACH( PNS_OBSTACLE& obs, obstacles )
|
||||||
|
{
|
||||||
|
if( visited.find( obs.m_item ) == visited.end() && obs.m_item->Layers().Overlaps( aLayer ) && !( obs.m_item->Marker() & MK_HEAD ) )
|
||||||
|
{
|
||||||
|
visited.insert( obs.m_item );
|
||||||
|
pending.push_back( obs.m_item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return visited;
|
||||||
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ public:
|
||||||
const PNS_LINE DpCoupledLine( PNS_LINE* aLine );
|
const PNS_LINE DpCoupledLine( PNS_LINE* aLine );
|
||||||
bool AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair );
|
bool AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair );
|
||||||
|
|
||||||
|
const std::set<PNS_ITEM*> AssembleCluster( PNS_ITEM* aStart, int aLayer );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool followTrivialPath( PNS_LINE* aLine, bool aLeft, PNS_ITEMSET& aSet, std::set<PNS_ITEM*>& aVisited );
|
bool followTrivialPath( PNS_LINE* aLine, bool aLeft, PNS_ITEMSET& aSet, std::set<PNS_ITEM*>& aVisited );
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,15 @@ void PNS_WALKAROUND::start( const PNS_LINE& aInitialPath )
|
||||||
|
|
||||||
PNS_NODE::OPT_OBSTACLE PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath )
|
PNS_NODE::OPT_OBSTACLE PNS_WALKAROUND::nearestObstacle( const PNS_LINE& aPath )
|
||||||
{
|
{
|
||||||
return m_world->NearestObstacle( &aPath, m_itemMask );
|
PNS_NODE::OPT_OBSTACLE obs = m_world->NearestObstacle( &aPath, m_itemMask, m_restrictedSet.empty() ? NULL : &m_restrictedSet );
|
||||||
|
|
||||||
|
if( m_restrictedSet.empty() )
|
||||||
|
return obs;
|
||||||
|
|
||||||
|
else if( obs && m_restrictedSet.find ( obs->m_item ) != m_restrictedSet.end() )
|
||||||
|
return obs;
|
||||||
|
|
||||||
|
return PNS_NODE::OPT_OBSTACLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,7 +101,7 @@ PNS_WALKAROUND::WALKAROUND_STATUS PNS_WALKAROUND::singleStep( PNS_LINE& aPath,
|
||||||
|
|
||||||
SHAPE_LINE_CHAIN pnew;
|
SHAPE_LINE_CHAIN pnew;
|
||||||
|
|
||||||
if( !m_forceSingleDirection && len_alt < len_pre && !alt_collides && !prev_recursive )
|
if( !m_forceLongerPath && len_alt < len_pre && !alt_collides && !prev_recursive )
|
||||||
{
|
{
|
||||||
pnew = path_pre[1];
|
pnew = path_pre[1];
|
||||||
pnew.Append( path_walk[1] );
|
pnew.Append( path_walk[1] );
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#ifndef __PNS_WALKAROUND_H
|
#ifndef __PNS_WALKAROUND_H
|
||||||
#define __PNS_WALKAROUND_H
|
#define __PNS_WALKAROUND_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include "pns_line.h"
|
#include "pns_line.h"
|
||||||
#include "pns_node.h"
|
#include "pns_node.h"
|
||||||
#include "pns_router.h"
|
#include "pns_router.h"
|
||||||
|
@ -105,6 +107,14 @@ public:
|
||||||
m_forceWinding = aEnabled;
|
m_forceWinding = aEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RestrictToSet( bool aEnabled, const std::set<PNS_ITEM*>& aSet )
|
||||||
|
{
|
||||||
|
if( aEnabled )
|
||||||
|
m_restrictedSet = aSet;
|
||||||
|
else
|
||||||
|
m_restrictedSet.clear();
|
||||||
|
}
|
||||||
|
|
||||||
WALKAROUND_STATUS Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
|
WALKAROUND_STATUS Route( const PNS_LINE& aInitialPath, PNS_LINE& aWalkPath,
|
||||||
bool aOptimize = true );
|
bool aOptimize = true );
|
||||||
|
|
||||||
|
@ -133,6 +143,7 @@ private:
|
||||||
PNS_NODE::OPT_OBSTACLE m_currentObstacle[2];
|
PNS_NODE::OPT_OBSTACLE m_currentObstacle[2];
|
||||||
bool m_recursiveCollision[2];
|
bool m_recursiveCollision[2];
|
||||||
PNS_LOGGER m_logger;
|
PNS_LOGGER m_logger;
|
||||||
|
std::set<PNS_ITEM*> m_restrictedSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __PNS_WALKAROUND_H
|
#endif // __PNS_WALKAROUND_H
|
||||||
|
|
Loading…
Reference in New Issue