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:
parent
bb4d3faad7
commit
313ebb9dff
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
*
|
*
|
||||||
|
|
|
@ -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++ )
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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 ) );
|
||||||
|
|
Loading…
Reference in New Issue