router: correct walkaround corner case when both ends of the line lie on the hull edge

Fixes: lp:1810935
* https://bugs.launchpad.net/kicad/+bug/1810935
This commit is contained in:
Tomasz Włostowski 2019-02-03 11:21:48 +01:00
parent bb4d3faad7
commit 313ebb9dff
5 changed files with 50 additions and 7 deletions

View File

@ -377,30 +377,35 @@ bool SHAPE_LINE_CHAIN::PointInside( const VECTOR2I& aP ) const
inside = !inside; inside = !inside;
} }
} }
return inside; return inside && !PointOnEdge( aP );
} }
bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const bool SHAPE_LINE_CHAIN::PointOnEdge( const VECTOR2I& aP ) const
{ {
if( !PointCount() ) return EdgeContainingPoint( aP ) >= 0;
return false; }
int SHAPE_LINE_CHAIN::EdgeContainingPoint( const VECTOR2I& aP ) const
{
if( !PointCount() )
return -1;
else if( PointCount() == 1 ) else if( PointCount() == 1 )
return m_points[0] == aP; return m_points[0] == aP ? 0 : -1;
for( int i = 0; i < SegmentCount(); i++ ) for( int i = 0; i < SegmentCount(); i++ )
{ {
const SEG s = CSegment( i ); const SEG s = CSegment( i );
if( s.A == aP || s.B == aP ) if( s.A == aP || s.B == aP )
return true; return i;
if( s.Distance( aP ) <= 1 ) if( s.Distance( aP ) <= 1 )
return true; return i;
} }
return false; return -1;
} }

View File

@ -564,6 +564,15 @@ public:
*/ */
bool PointOnEdge( const VECTOR2I& aP ) const; bool PointOnEdge( const VECTOR2I& aP ) const;
/**
* Function EdgeContainingPoint()
*
* Checks if point aP lies on an edge or vertex of the line chain.
* @param aP point to check
* @return index of the first edge containing the point, otherwise negative
*/
int EdgeContainingPoint( const VECTOR2I& aP ) const;
/** /**
* Function CheckClearance() * Function CheckClearance()
* *

View File

@ -163,13 +163,21 @@ bool LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
if( line.SegmentCount() < 1 ) if( line.SegmentCount() < 1 )
return false; return false;
const auto pFirst = line.CPoint(0);
const auto pLast = line.CPoint(-1);
if( aObstacle.PointInside( line.CPoint( 0 ) ) || aObstacle.PointInside( line.CPoint( -1 ) ) ) if( aObstacle.PointInside( line.CPoint( 0 ) ) || aObstacle.PointInside( line.CPoint( -1 ) ) )
{
return false; return false;
}
SHAPE_LINE_CHAIN::INTERSECTIONS ips; SHAPE_LINE_CHAIN::INTERSECTIONS ips;
line.Intersect( aObstacle, ips ); line.Intersect( aObstacle, ips );
auto eFirst = aObstacle.EdgeContainingPoint( pFirst );
auto eLast = aObstacle.EdgeContainingPoint( pLast );
aWalk.Clear(); aWalk.Clear();
aPost.Clear(); aPost.Clear();
@ -177,6 +185,23 @@ bool LINE::Walkaround( SHAPE_LINE_CHAIN aObstacle, SHAPE_LINE_CHAIN& aPre,
int farthest_dist = 0; int farthest_dist = 0;
SHAPE_LINE_CHAIN::INTERSECTION nearest, farthest; SHAPE_LINE_CHAIN::INTERSECTION nearest, farthest;
SHAPE_LINE_CHAIN::INTERSECTION is;
if( eFirst >= 0 )
{
is.our = line.CSegment(0);
is.their = aObstacle.CSegment( eFirst );
is.p = pFirst;
ips.push_back(is);
}
if ( eLast >= 0 )
{
is.our = line.CSegment(-1);
is.their = aObstacle.CSegment( eLast );
is.p = pLast;
ips.push_back(is);
}
for( int i = 0; i < (int) ips.size(); i++ ) for( int i = 0; i < (int) ips.size(); i++ )
{ {

View File

@ -367,6 +367,7 @@ bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead )
WALKAROUND walkaround( m_currentNode, Router() ); WALKAROUND walkaround( m_currentNode, Router() );
walkaround.SetSolidsOnly( false ); walkaround.SetSolidsOnly( false );
walkaround.SetDebugDecorator( Dbg() );
walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() ); walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false ); WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false );
@ -565,6 +566,7 @@ bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead )
walkaround.SetSolidsOnly( true ); walkaround.SetSolidsOnly( true );
walkaround.SetIterationLimit( 10 ); walkaround.SetIterationLimit( 10 );
walkaround.SetDebugDecorator( Dbg() );
WALKAROUND::WALKAROUND_STATUS stat_solids = walkaround.Route( initTrack, walkSolids ); WALKAROUND::WALKAROUND_STATUS stat_solids = walkaround.Route( initTrack, walkSolids );
optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS ); optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS );

View File

@ -801,6 +801,8 @@ void ROUTER_TOOL::performRouting()
// Don't crash if we missed an operation that cancelled routing. // Don't crash if we missed an operation that cancelled routing.
wxCHECK2( m_router->RoutingInProgress(), break ); wxCHECK2( m_router->RoutingInProgress(), break );
handleCommonEvents( *evt );
if( evt->IsMotion() ) if( evt->IsMotion() )
{ {
m_router->SetOrthoMode( evt->Modifier( MD_CTRL ) ); m_router->SetOrthoMode( evt->Modifier( MD_CTRL ) );