router: snap to clearance boundaries in Highlight Collisions mode

Fixes: lp:1655819
* https://bugs.launchpad.net/kicad/+bug/1655819
This commit is contained in:
Tomasz Włostowski 2017-01-19 13:55:22 +01:00 committed by Maciej Suminski
parent 2eb840b2ed
commit ba9576b014
5 changed files with 166 additions and 13 deletions

View File

@ -27,12 +27,13 @@
bool SHAPE::Parse( std::stringstream& aStream ) bool SHAPE::Parse( std::stringstream& aStream )
{ {
assert ( false ); assert( false );
return false; return false;
}; }
const std::string SHAPE::Format( ) const
const std::string SHAPE::Format() const
{ {
assert ( false ); assert( false );
return std::string(""); return std::string( "" );
}; }

View File

@ -1,7 +1,7 @@
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2013 CERN * Copyright (C) 2013-2017 CERN
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
@ -587,3 +587,28 @@ bool SHAPE_LINE_CHAIN::Parse( std::stringstream& aStream )
return true; return true;
} }
const VECTOR2I SHAPE_LINE_CHAIN::PointAlong( int aPathLength ) const
{
int total = 0;
if( aPathLength == 0 )
return CPoint( 0 );
for( int i = 0; i < SegmentCount(); i++ )
{
const SEG& s = CSegment( i );
int l = s.Length();
if( total + l >= aPathLength )
{
VECTOR2I d( s.B - s.A );
return s.A + d.Resize( aPathLength - total );
}
total += l;
}
return CPoint( -1 );
}

View File

@ -571,7 +571,7 @@ public:
return false; return false;
} }
bool CompareGeometry( const SHAPE_LINE_CHAIN & aOther ) const; bool CompareGeometry( const SHAPE_LINE_CHAIN& aOther ) const;
void Move( const VECTOR2I& aVector ) override void Move( const VECTOR2I& aVector ) override
{ {
@ -584,6 +584,8 @@ public:
return false; return false;
} }
const VECTOR2I PointAlong( int aPathLength ) const;
private: private:
/// array of vertices /// array of vertices
std::vector<VECTOR2I> m_points; std::vector<VECTOR2I> m_points;

View File

@ -1,7 +1,7 @@
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013-2014 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
@ -413,11 +413,128 @@ bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead )
bool LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, LINE& aNewHead ) bool LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, LINE& aNewHead )
{ {
buildInitialLine( aP, m_head ); buildInitialLine( aP, m_head );
auto obs = m_currentNode->NearestObstacle( &m_head );
if( obs )
{
int cl = m_currentNode->GetClearance( obs->m_item, &m_head );
auto hull = obs->m_item->Hull( cl, m_head.Width() );
auto nearest = hull.NearestPoint( aP );
Dbg()->AddLine( hull, 2, 10000 );
if( ( nearest - aP ).EuclideanNorm() < m_head.Width() )
{
buildInitialLine( nearest, m_head );
}
}
aNewHead = m_head; aNewHead = m_head;
return static_cast<bool>( m_currentNode->CheckColliding( &m_head ) ); return static_cast<bool>( m_currentNode->CheckColliding( &m_head ) );
} }
const LINE LINE_PLACER::reduceToNearestObstacle( const LINE& aOriginalLine )
{
auto l0 = aOriginalLine.CLine();
if ( !l0.PointCount() )
return aOriginalLine;
int l = l0.Length();
int step = l / 2;
VECTOR2I target;
LINE l_test( aOriginalLine );
while( step > 0 )
{
target = l0.PointAlong( l );
SHAPE_LINE_CHAIN l_cur( l0 );
int index = l_cur.Split( target );
l_test.SetShape( l_cur.Slice( 0, index ) );
if ( m_currentNode->CheckColliding( &l_test ) )
l -= step;
else
l += step;
step /= 2;
}
l = l_test.CLine().Length();
while( m_currentNode->CheckColliding( &l_test ) && l > 0 )
{
l--;
target = l0.PointAlong( l );
SHAPE_LINE_CHAIN l_cur( l0 );
int index = l_cur.Split( target );
l_test.SetShape( l_cur.Slice( 0, index ) );
}
return l_test;
}
bool LINE_PLACER::rhStopAtNearestObstacle( const VECTOR2I& aP, LINE& aNewHead )
{
LINE l0;
l0 = m_head;
buildInitialLine( aP, l0 );
LINE l_cur = reduceToNearestObstacle( l0 );
const auto l_shape = l_cur.CLine();
if( l_shape.SegmentCount() == 0 )
{
return false;
}
if( l_shape.SegmentCount() == 1 )
{
auto s = l_shape.CSegment( 0 );
VECTOR2I dL( DIRECTION_45( s ).Left().ToVector() );
VECTOR2I dR( DIRECTION_45( s ).Right().ToVector() );
SEG leadL( s.B, s.B + dL );
SEG leadR( s.B, s.B + dR );
SEG segL( s.B, leadL.LineProject( aP ) );
SEG segR( s.B, leadR.LineProject( aP ) );
LINE finishL( l0, SHAPE_LINE_CHAIN( segL.A, segL.B ) );
LINE finishR( l0, SHAPE_LINE_CHAIN( segR.A, segR.B ) );
LINE reducedL = reduceToNearestObstacle( finishL );
LINE reducedR = reduceToNearestObstacle( finishR );
int lL = reducedL.CLine().Length();
int lR = reducedR.CLine().Length();
if( lL > lR )
l_cur.Line().Append( reducedL.CLine() );
else
l_cur.Line().Append( reducedR.CLine() );
l_cur.Line().Simplify();
}
m_head = l_cur;
aNewHead = m_head;
return true;
}
bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead ) bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead )
{ {
LINE initTrack( m_head ); LINE initTrack( m_head );
@ -1027,7 +1144,7 @@ void LINE_PLACER::SetOrthoMode( bool aOrthoMode )
} }
bool LINE_PLACER::buildInitialLine( const VECTOR2I& aP, LINE& aHead ) bool LINE_PLACER::buildInitialLine( const VECTOR2I& aP, LINE& aHead, bool aInvertPosture )
{ {
SHAPE_LINE_CHAIN l; SHAPE_LINE_CHAIN l;
@ -1043,6 +1160,9 @@ bool LINE_PLACER::buildInitialLine( const VECTOR2I& aP, LINE& aHead )
} }
else else
{ {
if ( aInvertPosture )
l = m_direction.Right().BuildInitialTrace( m_p_start, aP );
else
l = m_direction.BuildInitialTrace( m_p_start, aP ); l = m_direction.BuildInitialTrace( m_p_start, aP );
} }

View File

@ -1,7 +1,7 @@
/* /*
* KiRouter - a push-and-(sometimes-)shove PCB router * KiRouter - a push-and-(sometimes-)shove PCB router
* *
* Copyright (C) 2013-2014 CERN * Copyright (C) 2013-2017 CERN
* Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
* Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch> * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* *
@ -335,6 +335,11 @@ private:
*/ */
void routeStep( const VECTOR2I& aP ); void routeStep( const VECTOR2I& aP );
const LINE reduceToNearestObstacle( const LINE& aOriginalLine );
bool rhStopAtNearestObstacle( const VECTOR2I& aP, LINE& aNewHead );
///> route step, walkaround mode ///> route step, walkaround mode
bool rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead); bool rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead);
@ -346,7 +351,7 @@ private:
const VIA makeVia( const VECTOR2I& aP ); const VIA makeVia( const VECTOR2I& aP );
bool buildInitialLine( const VECTOR2I& aP, LINE& aHead ); bool buildInitialLine( const VECTOR2I& aP, LINE& aHead, bool aInvertPosture = false );
///> current routing direction ///> current routing direction
DIRECTION_45 m_direction; DIRECTION_45 m_direction;