Don't shove stitching vias.

Whether or not it's a good idea, the current algorithm doesn't support
it and leaves them on top of each other.

Fixes: lp:1833214
* https://bugs.launchpad.net/kicad/+bug/1833214
This commit is contained in:
Jeff Young 2019-07-21 16:36:08 -06:00
parent 6f44b00b2c
commit aa4d7682ca
2 changed files with 39 additions and 44 deletions

View File

@ -118,6 +118,11 @@ public:
return ( m_linkedItems.Size() == 3 && vias == 1 && segs == 2 ); return ( m_linkedItems.Size() == 3 && vias == 1 && segs == 2 );
} }
bool IsStitchingVia() const
{
return ( m_linkedItems.Size() == 1 && m_linkedItems.Count( VIA_T ) == 1 );
}
bool IsTraceWidthChange() const bool IsTraceWidthChange() const
{ {
if( m_linkedItems.Size() != 2 ) if( m_linkedItems.Size() != 2 )

View File

@ -19,13 +19,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>. * with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#define PNS_DEBUG
#include <deque> #include <deque>
#include <cassert> #include <cassert>
#include "range.h"
#include "pns_line.h" #include "pns_line.h"
#include "pns_node.h" #include "pns_node.h"
#include "pns_walkaround.h" #include "pns_walkaround.h"
@ -35,14 +31,10 @@
#include "pns_via.h" #include "pns_via.h"
#include "pns_utils.h" #include "pns_utils.h"
#include "pns_router.h" #include "pns_router.h"
#include "pns_shove.h"
#include "pns_utils.h"
#include "pns_topology.h" #include "pns_topology.h"
#include "time_limit.h" #include "time_limit.h"
#include <profile.h>
namespace PNS { namespace PNS {
void SHOVE::replaceItems( ITEM* aOld, std::unique_ptr< ITEM > aNew ) void SHOVE::replaceItems( ITEM* aOld, std::unique_ptr< ITEM > aNew )
@ -128,12 +120,13 @@ bool SHOVE::checkBumpDirection( const LINE& aCurrent, const LINE& aShoved ) cons
} }
SHOVE::SHOVE_STATUS SHOVE::walkaroundLoneVia( LINE& aCurrent, LINE& aObstacle, SHOVE::SHOVE_STATUS SHOVE::walkaroundLoneVia( LINE& aCurrent, LINE& aObstacle, LINE& aShoved )
LINE& aShoved )
{ {
int clearance = getClearance( &aCurrent, &aObstacle ); int clearance = getClearance( &aCurrent, &aObstacle );
const SHAPE_LINE_CHAIN hull = aCurrent.Via().Hull( clearance, aObstacle.Width() ); const SHAPE_LINE_CHAIN hull = aCurrent.Via().Hull( clearance, aObstacle.Width() );
SHAPE_LINE_CHAIN path_cw, path_ccw; SHAPE_LINE_CHAIN path_cw;
SHAPE_LINE_CHAIN path_ccw;
VECTOR2I dummy;
if( ! aObstacle.Walkaround( hull, path_cw, true ) ) if( ! aObstacle.Walkaround( hull, path_cw, true ) )
return SH_INCOMPLETE; return SH_INCOMPLETE;
@ -261,8 +254,7 @@ SHOVE::SHOVE_STATUS SHOVE::processHullSet( LINE& aCurrent, LINE& aObstacle,
} }
SHOVE::SHOVE_STATUS SHOVE::ProcessSingleLine( LINE& aCurrent, LINE& aObstacle, SHOVE::SHOVE_STATUS SHOVE::ProcessSingleLine( LINE& aCurrent, LINE& aObstacle, LINE& aShoved )
LINE& aShoved )
{ {
aShoved.ClearSegmentLinks(); aShoved.ClearSegmentLinks();
@ -610,6 +602,9 @@ SHOVE::SHOVE_STATUS SHOVE::pushVia( VIA* aVia, const VECTOR2I& aForce, int aCurr
if( aVia->IsLocked() ) if( aVia->IsLocked() )
return SH_TRY_WALK; return SH_TRY_WALK;
if( jt->IsStitchingVia() )
return SH_TRY_WALK;
if( jt->IsLocked() ) if( jt->IsLocked() )
return SH_INCOMPLETE; return SH_INCOMPLETE;
@ -723,9 +718,13 @@ SHOVE::SHOVE_STATUS SHOVE::onCollidingVia( ITEM* aCurrent, VIA* aObstacleVia )
{ {
int clearance = getClearance( aCurrent, aObstacleVia ) ; int clearance = getClearance( aCurrent, aObstacleVia ) ;
LINE_PAIR_VEC draggedLines; LINE_PAIR_VEC draggedLines;
bool colLine = false, colVia = false; bool lineCollision = false;
bool viaCollision = false;
LINE* currentLine = NULL; LINE* currentLine = NULL;
VECTOR2I mtvLine, mtvVia, mtv, mtvSolid; VECTOR2I mtvLine;
VECTOR2I mtvVia;
VECTOR2I mtvSolid;
VECTOR2I mtv;
int rank = -1; int rank = -1;
if( aCurrent->OfKind( ITEM::LINE_T ) ) if( aCurrent->OfKind( ITEM::LINE_T ) )
@ -736,20 +735,22 @@ SHOVE::SHOVE_STATUS SHOVE::onCollidingVia( ITEM* aCurrent, VIA* aObstacleVia )
#endif #endif
currentLine = (LINE*) aCurrent; currentLine = (LINE*) aCurrent;
colLine = CollideShapes( aObstacleVia->Shape(), currentLine->Shape(), lineCollision = CollideShapes( aObstacleVia->Shape(), currentLine->Shape(),
clearance + currentLine->Width() / 2 + PNS_HULL_MARGIN, clearance + currentLine->Width() / 2 + PNS_HULL_MARGIN,
true, mtvLine ); true, mtvLine );
if( currentLine->EndsWithVia() ) if( currentLine->EndsWithVia() )
colVia = CollideShapes( currentLine->Via().Shape(), aObstacleVia->Shape(), {
clearance + PNS_HULL_MARGIN, true, mtvVia ); viaCollision = CollideShapes( currentLine->Via().Shape(), aObstacleVia->Shape(),
clearance + PNS_HULL_MARGIN, true, mtvVia );
}
if( !colLine && !colVia ) if( !lineCollision && !viaCollision )
return SH_OK; return SH_OK;
if( colLine && colVia ) if( lineCollision && viaCollision )
mtv = mtvVia.EuclideanNorm() > mtvLine.EuclideanNorm() ? mtvVia : mtvLine; mtv = mtvVia.EuclideanNorm() > mtvLine.EuclideanNorm() ? mtvVia : mtvLine;
else if( colLine ) else if( lineCollision )
mtv = mtvLine; mtv = mtvLine;
else else
mtv = mtvVia; mtv = mtvVia;
@ -1005,9 +1006,8 @@ SHOVE::SHOVE_STATUS SHOVE::shoveIteration( int aIter )
st = onCollidingSegment( currentLine, (SEGMENT*) ni ); st = onCollidingSegment( currentLine, (SEGMENT*) ni );
if( st == SH_TRY_WALK ) if( st == SH_TRY_WALK )
{
st = onCollidingSolid( currentLine, ni ); st = onCollidingSolid( currentLine, ni );
}
break; break;
case ITEM::VIA_T: case ITEM::VIA_T:
@ -1015,9 +1015,8 @@ SHOVE::SHOVE_STATUS SHOVE::shoveIteration( int aIter )
st = onCollidingVia( &currentLine, (VIA*) ni ); st = onCollidingVia( &currentLine, (VIA*) ni );
if( st == SH_TRY_WALK ) if( st == SH_TRY_WALK )
{
st = onCollidingSolid( currentLine, ni ); st = onCollidingSolid( currentLine, ni );
}
break; break;
case ITEM::SOLID_T: case ITEM::SOLID_T:
@ -1077,7 +1076,8 @@ OPT_BOX2I SHOVE::totalAffectedArea() const
{ {
if( m_affectedAreaSum ) if( m_affectedAreaSum )
area->Merge( *m_affectedAreaSum ); area->Merge( *m_affectedAreaSum );
} else }
else
area = m_affectedAreaSum; area = m_affectedAreaSum;
return area; return area;
@ -1268,8 +1268,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveMultiLines( const ITEM_SET& aHeadSet )
} }
SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere, SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere, VIA** aNewVia )
VIA** aNewVia )
{ {
SHOVE_STATUS st = SH_OK; SHOVE_STATUS st = SH_OK;
@ -1309,9 +1308,7 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere,
else else
{ {
if( aNewVia ) if( aNewVia )
{
*aNewVia = nullptr; *aNewVia = nullptr;
}
delete m_currentNode; delete m_currentNode;
m_currentNode = parent; m_currentNode = parent;
@ -1324,7 +1321,8 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( VIA* aVia, const VECTOR2I& aWhere,
void SHOVE::runOptimizer( NODE* aNode ) void SHOVE::runOptimizer( NODE* aNode )
{ {
OPTIMIZER optimizer( aNode ); OPTIMIZER optimizer( aNode );
int optFlags = 0, n_passes = 0; int optFlags = 0;
int n_passes = 0;
PNS_OPTIMIZATION_EFFORT effort = Settings().OptimizerEffort(); PNS_OPTIMIZATION_EFFORT effort = Settings().OptimizerEffort();
@ -1332,16 +1330,11 @@ void SHOVE::runOptimizer( NODE* aNode )
int maxWidth = 0; int maxWidth = 0;
for( std::vector<LINE>::iterator i = m_optimizerQueue.begin(); for( LINE& line : m_optimizerQueue )
i != m_optimizerQueue.end(); ++i ) maxWidth = std::max( line.Width(), maxWidth );
{
maxWidth = std::max( i->Width(), maxWidth );
}
if( area ) if( area )
{
area->Inflate( 10 * maxWidth ); area->Inflate( 10 * maxWidth );
}
switch( effort ) switch( effort )
{ {
@ -1378,11 +1371,8 @@ void SHOVE::runOptimizer( NODE* aNode )
{ {
std::reverse( m_optimizerQueue.begin(), m_optimizerQueue.end() ); std::reverse( m_optimizerQueue.begin(), m_optimizerQueue.end() );
for( std::vector<LINE>::iterator i = m_optimizerQueue.begin(); for( LINE& line : m_optimizerQueue)
i != m_optimizerQueue.end(); ++i )
{ {
LINE& line = *i;
if( !( line.Marker() & MK_HEAD ) ) if( !( line.Marker() & MK_HEAD ) )
{ {
LINE optimized; LINE optimized;