From a96299d456274cb5ed178635cb05f97d91140e17 Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Wed, 19 Aug 2015 18:07:16 +0200 Subject: [PATCH] router: improvements to shove algorithm --- common/geometry/shape_collisions.cpp | 13 ++- common/geometry/shape_poly_set.cpp | 2 - include/geometry/shape_rect.h | 12 +++ pcbnew/router/pns_item.cpp | 10 +- pcbnew/router/pns_item.h | 8 +- pcbnew/router/pns_line_placer.cpp | 15 ++- pcbnew/router/pns_line_placer.h | 4 + pcbnew/router/pns_node.cpp | 29 ++++-- pcbnew/router/pns_node.h | 9 +- pcbnew/router/pns_router.cpp | 7 ++ pcbnew/router/pns_shove.cpp | 137 +++++++++++++++++++-------- pcbnew/router/pns_shove.h | 7 +- pcbnew/router/pns_topology.cpp | 31 ++++++ pcbnew/router/pns_topology.h | 2 + pcbnew/router/pns_walkaround.cpp | 12 ++- pcbnew/router/pns_walkaround.h | 11 +++ 16 files changed, 236 insertions(+), 73 deletions(-) diff --git a/common/geometry/shape_collisions.cpp b/common/geometry/shape_collisions.cpp index 3e8e51cdc7..bb4f330a1d 100644 --- a/common/geometry/shape_collisions.cpp +++ b/common/geometry/shape_collisions.cpp @@ -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 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( aA, aB, aClearance, aNeedMTV, aMTV ); - assert( aB->Type() != SH_RECT ); - return true; + case SH_RECT: + return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); case SH_CIRCLE: return CollCase( aA, aB, aClearance, aNeedMTV, aMTV ); diff --git a/common/geometry/shape_poly_set.cpp b/common/geometry/shape_poly_set.cpp index 1d42a41b70..4348b2ec51 100644 --- a/common/geometry/shape_poly_set.cpp +++ b/common/geometry/shape_poly_set.cpp @@ -206,8 +206,6 @@ const SHAPE_LINE_CHAIN SHAPE_POLY_SET::convertFromClipper( const Path& aPath ) return lc; } -#include -#include void SHAPE_POLY_SET::booleanOp( ClipType aType, const SHAPE_POLY_SET& aOtherShape, bool aFastMode ) { diff --git a/include/geometry/shape_rect.h b/include/geometry/shape_rect.h index 682abcfeff..47e6b13ba9 100644 --- a/include/geometry/shape_rect.h +++ b/include/geometry/shape_rect.h @@ -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; diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index 67fd14ad7b..eb4b60766c 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -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( 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; diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index cfdfe29c97..a7511a7110 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -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; diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index 0cab79133b..3d388e5657 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -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& aNets ) const { aNets.push_back( m_currentNet ); } + +PNS_LOGGER* PNS_LINE_PLACER::Logger() +{ + if( m_shove ) + return m_shove->Logger(); + + return NULL; +} \ No newline at end of file diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index 0f3b4a7605..38f29e3982 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -184,6 +184,10 @@ public: bool IsPlacingVia() const { return m_placingVia; } void GetModifiedNets( std::vector& aNets ) const; + + PNS_LOGGER* Logger(); + + private: /** * Function route() diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index 3eb90c1046..8cf2441b09 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -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( aItem )->Width() / 2; @@ -228,7 +234,10 @@ struct PNS_NODE::OBSTACLE_VISITOR if( aItem->Kind() == PNS_ITEM::LINE ) clearance += static_cast( 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* 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 isect_list; int clearance = GetClearance( obs.m_item, &aLine ); diff --git a/pcbnew/router/pns_node.h b/pcbnew/router/pns_node.h index ca531221ba..7ff4b8d374 100644 --- a/pcbnew/router/pns_node.h +++ b/pcbnew/router/pns_node.h @@ -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* aRestrictedSet = NULL ); /** * Function CheckColliding() diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index d72fd61234..fc871fa549 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -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; } diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index 99a9609c88..f13983dc9f 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -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 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: diff --git a/pcbnew/router/pns_shove.h b/pcbnew/router/pns_shove.h index b8b4dfef99..f9eb60b958 100644 --- a/pcbnew/router/pns_shove.h +++ b/pcbnew/router/pns_shove.h @@ -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 ); diff --git a/pcbnew/router/pns_topology.cpp b/pcbnew/router/pns_topology.cpp index 2044aefbf0..bb4b83247b 100644 --- a/pcbnew/router/pns_topology.cpp +++ b/pcbnew/router/pns_topology.cpp @@ -396,3 +396,34 @@ bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair ) return true; } + +const std::set PNS_TOPOLOGY::AssembleCluster( PNS_ITEM* aStart, int aLayer ) +{ + std::set visited; + std::deque 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; +} diff --git a/pcbnew/router/pns_topology.h b/pcbnew/router/pns_topology.h index ebc4894b74..bbc36a875a 100644 --- a/pcbnew/router/pns_topology.h +++ b/pcbnew/router/pns_topology.h @@ -61,6 +61,8 @@ public: const PNS_LINE DpCoupledLine( PNS_LINE* aLine ); bool AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair ); + const std::set AssembleCluster( PNS_ITEM* aStart, int aLayer ); + private: bool followTrivialPath( PNS_LINE* aLine, bool aLeft, PNS_ITEMSET& aSet, std::set& aVisited ); diff --git a/pcbnew/router/pns_walkaround.cpp b/pcbnew/router/pns_walkaround.cpp index 570e691f8e..c7e7e194f3 100644 --- a/pcbnew/router/pns_walkaround.cpp +++ b/pcbnew/router/pns_walkaround.cpp @@ -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] ); diff --git a/pcbnew/router/pns_walkaround.h b/pcbnew/router/pns_walkaround.h index 179fe81a74..f143b46b1e 100644 --- a/pcbnew/router/pns_walkaround.h +++ b/pcbnew/router/pns_walkaround.h @@ -21,6 +21,8 @@ #ifndef __PNS_WALKAROUND_H #define __PNS_WALKAROUND_H +#include + #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& 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 m_restrictedSet; }; #endif // __PNS_WALKAROUND_H