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 );
|
||||
}
|
||||
|
||||
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>
|
||||
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:
|
||||
switch( aB->Type() )
|
||||
{
|
||||
case SH_RECT: // RECT to RECT not yet in use in p&s router
|
||||
// Should be (todo) somethink like:
|
||||
//return CollCaseReversed<SHAPE_RECT, SHAPE_RECT>( aA, aB, aClearance, aNeedMTV, aMTV );
|
||||
assert( aB->Type() != SH_RECT );
|
||||
return true;
|
||||
case SH_RECT:
|
||||
return CollCase<SHAPE_RECT, SHAPE_RECT>( aA, aB, aClearance, aNeedMTV, aMTV );
|
||||
|
||||
case SH_CIRCLE:
|
||||
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;
|
||||
}
|
||||
|
||||
#include <common.h>
|
||||
#include <wx/wx.h>
|
||||
void SHAPE_POLY_SET::booleanOp( ClipType aType, const SHAPE_POLY_SET& aOtherShape,
|
||||
bool aFastMode )
|
||||
{
|
||||
|
|
|
@ -142,6 +142,18 @@ public:
|
|||
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:
|
||||
///> Top-left corner
|
||||
VECTOR2I m_p0;
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
#include "pns_line.h"
|
||||
|
||||
bool PNS_ITEM::collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||
VECTOR2I& aMTV ) const
|
||||
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const
|
||||
{
|
||||
// same nets? no collision!
|
||||
if( m_net == aOther->m_net )
|
||||
if( aDifferentNetsOnly && m_net == aOther->m_net )
|
||||
return false;
|
||||
|
||||
// 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,
|
||||
VECTOR2I& aMTV ) const
|
||||
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const
|
||||
{
|
||||
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV ) )
|
||||
if( collideSimple( aOther, aClearance, aNeedMTV, aMTV, aDifferentNetsOnly ) )
|
||||
return true;
|
||||
|
||||
// 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 );
|
||||
|
||||
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;
|
||||
|
|
|
@ -270,18 +270,18 @@ public:
|
|||
* @return true, if a collision was found.
|
||||
*/
|
||||
virtual bool Collide( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||
VECTOR2I& aMTV ) const;
|
||||
VECTOR2I& aMTV, bool aDifferentNetsOnly = true ) const;
|
||||
|
||||
/**
|
||||
* Function Collide()
|
||||
*
|
||||
* 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;
|
||||
|
||||
return Collide( aOther, aClearance, false, dummy );
|
||||
return Collide( aOther, aClearance, false, dummy, aDifferentNetsOnly );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,7 +332,7 @@ public:
|
|||
|
||||
private:
|
||||
bool collideSimple( const PNS_ITEM* aOther, int aClearance, bool aNeedMTV,
|
||||
VECTOR2I& aMTV ) const;
|
||||
VECTOR2I& aMTV, bool aDifferentNetsOnly ) const;
|
||||
|
||||
protected:
|
||||
PnsKind m_kind;
|
||||
|
|
|
@ -477,8 +477,13 @@ bool PNS_LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, PNS_LINE& aNewHead )
|
|||
|
||||
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.SetEffortLevel( PNS_OPTIMIZER::MERGE_OBTUSE | PNS_OPTIMIZER::SMART_PADS );
|
||||
optimizer.SetCollisionMask( PNS_ITEM::ANY );
|
||||
|
@ -1087,3 +1092,11 @@ void PNS_LINE_PLACER::GetModifiedNets( std::vector<int>& aNets ) const
|
|||
{
|
||||
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; }
|
||||
|
||||
void GetModifiedNets( std::vector<int>& aNets ) const;
|
||||
|
||||
PNS_LOGGER* Logger();
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* Function route()
|
||||
|
|
|
@ -185,7 +185,11 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
|||
///> additional clearance
|
||||
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_override( NULL ),
|
||||
m_tab( aTab ),
|
||||
|
@ -193,7 +197,9 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
|||
m_kindMask( aKindMask ),
|
||||
m_limitCount( -1 ),
|
||||
m_matchCount( 0 ),
|
||||
m_extraClearance( 0 )
|
||||
m_extraClearance( 0 ),
|
||||
m_differentNetsOnly( aDifferentNetsOnly ),
|
||||
m_forceClearance( -1 )
|
||||
{
|
||||
if( aItem->Kind() == PNS_ITEM::LINE )
|
||||
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 )
|
||||
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;
|
||||
|
||||
PNS_OBSTACLE obs;
|
||||
|
@ -248,9 +257,9 @@ struct PNS_NODE::OBSTACLE_VISITOR
|
|||
|
||||
|
||||
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
|
||||
assert( allocNodes.find( this ) != allocNodes.end() );
|
||||
|
@ -258,7 +267,7 @@ int PNS_NODE::QueryColliding( const PNS_ITEM* aItem,
|
|||
|
||||
visitor.SetCountLimit( aLimitCount );
|
||||
visitor.SetWorld( this, NULL );
|
||||
|
||||
visitor.m_forceClearance = aForceClearance;
|
||||
// first, look for colliding items in the local index
|
||||
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;
|
||||
bool found_isects = false;
|
||||
|
@ -293,7 +304,6 @@ PNS_NODE::OPT_OBSTACLE PNS_NODE::NearestObstacle( const PNS_LINE* aItem, int aKi
|
|||
if( aItem->EndsWithVia() )
|
||||
n += QueryColliding( &aItem->Via(), obs_list, aKindMask );
|
||||
|
||||
// if(! QueryColliding ( aItem, obs_list, aKindMask ))
|
||||
if( !n )
|
||||
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;
|
||||
int dist_max = INT_MIN;
|
||||
|
||||
if( aRestrictedSet && aRestrictedSet->find( obs.m_item ) == aRestrictedSet->end() )
|
||||
continue;
|
||||
|
||||
std::vector<SHAPE_LINE_CHAIN::INTERSECTION> isect_list;
|
||||
|
||||
int clearance = GetClearance( obs.m_item, &aLine );
|
||||
|
|
|
@ -184,7 +184,9 @@ public:
|
|||
int QueryColliding( const PNS_ITEM* aItem,
|
||||
OBSTACLES& aObstacles,
|
||||
int aKindMask = PNS_ITEM::ANY,
|
||||
int aLimitCount = -1 );
|
||||
int aLimitCount = -1,
|
||||
bool aDifferentNetsOnly = true,
|
||||
int aForceClearance = -1 );
|
||||
|
||||
/**
|
||||
* Function NearestObstacle()
|
||||
|
@ -195,8 +197,9 @@ public:
|
|||
* @param aKindMask mask of obstacle types to take into account
|
||||
* @return the obstacle, if found, otherwise empty.
|
||||
*/
|
||||
OPT_OBSTACLE NearestObstacle( const PNS_LINE* aItem,
|
||||
int aKindMask = PNS_ITEM::ANY );
|
||||
OPT_OBSTACLE NearestObstacle( const PNS_LINE* aItem,
|
||||
int aKindMask = PNS_ITEM::ANY,
|
||||
const std::set<PNS_ITEM*>* aRestrictedSet = NULL );
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
if( net_a == net_b )
|
||||
return 0;
|
||||
|
||||
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;
|
||||
|
@ -1041,6 +1044,10 @@ void PNS_ROUTER::DumpLog()
|
|||
logger = m_dragger->Logger();
|
||||
break;
|
||||
|
||||
case ROUTE_TRACK:
|
||||
logger = m_placer->Logger();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "pns_router.h"
|
||||
#include "pns_shove.h"
|
||||
#include "pns_utils.h"
|
||||
#include "pns_topology.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 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 n_segs = aCurrent.SegmentCount();
|
||||
|
||||
int clearance = getClearance( &aCurrent, &aObstacle );
|
||||
int clearance = getClearance( &aCurrent, &aObstacle ) + 1;
|
||||
|
||||
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 );
|
||||
|
||||
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 ) );
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -333,12 +346,12 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSegment( PNS_LINE& aCurrent, PNS_S
|
|||
m_newHead = shovedLine;
|
||||
}
|
||||
|
||||
sanityCheck( &obstacleLine, &shovedLine );
|
||||
replaceItems( &obstacleLine, &shovedLine );
|
||||
|
||||
int rank = aCurrent.Rank();
|
||||
shovedLine.SetRank( rank - 1 );
|
||||
|
||||
sanityCheck( &obstacleLine, &shovedLine );
|
||||
replaceItems( &obstacleLine, &shovedLine );
|
||||
|
||||
if( !pushLine( shovedLine ) )
|
||||
rv = SH_INCOMPLETE;
|
||||
}
|
||||
|
@ -380,15 +393,13 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingLine( PNS_LINE& aCurrent, PNS_LINE
|
|||
if( !pushLine( shovedLine ) )
|
||||
{
|
||||
rv = SH_INCOMPLETE;
|
||||
//printf( "pushLine failed\n" );
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE& aCurrent, PNS_SOLID* aObstacleSolid )
|
||||
PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::onCollidingSolid( PNS_LINE& aCurrent, PNS_ITEM* aObstacle )
|
||||
{
|
||||
PNS_WALKAROUND walkaround( m_currentNode, Router() );
|
||||
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 ) )
|
||||
return onCollidingVia( aObstacleSolid, via );
|
||||
if( via && m_currentNode->CheckColliding( via, aObstacle ) )
|
||||
return onCollidingVia( aObstacle, via );
|
||||
}
|
||||
|
||||
walkaround.SetSolidsOnly( true );
|
||||
walkaround.SetIterationLimit ( 8 ); // fixme: make configurable
|
||||
PNS_TOPOLOGY topo( m_currentNode );
|
||||
|
||||
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 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 )
|
||||
return SH_INCOMPLETE;
|
||||
if( attempt == 1 || Settings().JumpOverObstacles() )
|
||||
{
|
||||
nextRank = currentRank - 1;
|
||||
walkaround.SetSingleDirection( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
nextRank = currentRank + 10000;
|
||||
walkaround.SetSingleDirection( false );
|
||||
}
|
||||
|
||||
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 )
|
||||
if( walkaround.Route( aCurrent, walkaroundLine, false ) != PNS_WALKAROUND::DONE )
|
||||
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 );
|
||||
walkaroundLine.SetRank( nextRank );
|
||||
|
||||
#ifdef DEBUG
|
||||
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( &walkaroundLine, 3, "walk-line" );
|
||||
#endif
|
||||
|
@ -620,7 +664,7 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::pushVia( PNS_VIA* aVia, const VECTOR2I& aForc
|
|||
replaceItems( &lp.first, &lp.second );
|
||||
lp.second.SetRank( aCurrentRank - 1 );
|
||||
|
||||
if( !pushLine( lp.second ) )
|
||||
if( !pushLine( lp.second, true ) )
|
||||
return SH_INCOMPLETE;
|
||||
}
|
||||
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() ) )
|
||||
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 );
|
||||
|
||||
return true;
|
||||
|
@ -919,6 +971,11 @@ PNS_SHOVE::SHOVE_STATUS PNS_SHOVE::shoveIteration( int aIter )
|
|||
case PNS_ITEM::SEGMENT:
|
||||
TRACE( 2, "iter %d: collide-segment ", aIter );
|
||||
st = onCollidingSegment( currentLine, (PNS_SEGMENT*) ni );
|
||||
|
||||
if( st == SH_TRY_WALK )
|
||||
{
|
||||
st = onCollidingSolid( currentLine, (PNS_SOLID*) ni );
|
||||
}
|
||||
break;
|
||||
|
||||
case PNS_ITEM::VIA:
|
||||
|
|
|
@ -49,7 +49,8 @@ public:
|
|||
SH_OK = 0,
|
||||
SH_NULL,
|
||||
SH_INCOMPLETE,
|
||||
SH_HEAD_MODIFIED
|
||||
SH_HEAD_MODIFIED,
|
||||
SH_TRY_WALK
|
||||
};
|
||||
|
||||
PNS_SHOVE( PNS_NODE* aWorld, PNS_ROUTER* aRouter );
|
||||
|
@ -110,7 +111,7 @@ private:
|
|||
|
||||
SHOVE_STATUS onCollidingLine( PNS_LINE& aCurrent, PNS_LINE& aObstacle );
|
||||
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 onReverseCollidingVia( PNS_LINE& aCurrent, PNS_VIA* aObstacleVia );
|
||||
SHOVE_STATUS pushVia( PNS_VIA* aVia, const VECTOR2I& aForce, int aCurrentRank, bool aDryRun = false );
|
||||
|
@ -122,7 +123,7 @@ private:
|
|||
|
||||
void runOptimizer( PNS_NODE* aNode );
|
||||
|
||||
bool pushLine( const PNS_LINE& aL );
|
||||
bool pushLine( const PNS_LINE& aL, bool aKeepCurrentOnTop = false );
|
||||
void popLine();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 );
|
||||
bool AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair );
|
||||
|
||||
const std::set<PNS_ITEM*> AssembleCluster( PNS_ITEM* aStart, int aLayer );
|
||||
|
||||
private:
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
|
||||
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.Append( path_walk[1] );
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#ifndef __PNS_WALKAROUND_H
|
||||
#define __PNS_WALKAROUND_H
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "pns_line.h"
|
||||
#include "pns_node.h"
|
||||
#include "pns_router.h"
|
||||
|
@ -105,6 +107,14 @@ public:
|
|||
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,
|
||||
bool aOptimize = true );
|
||||
|
||||
|
@ -133,6 +143,7 @@ private:
|
|||
PNS_NODE::OPT_OBSTACLE m_currentObstacle[2];
|
||||
bool m_recursiveCollision[2];
|
||||
PNS_LOGGER m_logger;
|
||||
std::set<PNS_ITEM*> m_restrictedSet;
|
||||
};
|
||||
|
||||
#endif // __PNS_WALKAROUND_H
|
||||
|
|
Loading…
Reference in New Issue