Fix SHAPE_LINE_CHAIN::NearestPoint when aAllowInternalShapePoints=false
Fixes https://gitlab.com/kicad/code/kicad/-/issues/8770
This commit is contained in:
parent
cc99323c86
commit
ae87dc686a
|
@ -1557,30 +1557,43 @@ const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint( const VECTOR2I& aP,
|
|||
{
|
||||
int d = CSegment( i ).Distance( aP );
|
||||
|
||||
bool isInternalShapePoint = false;
|
||||
|
||||
// An internal shape point here is everything after the start of an arc and before the
|
||||
// second-to-last vertex of the arc, because we are looking at segments here!
|
||||
if( i > 0 && i < SegmentCount() - 1 && m_shapes[i] != SHAPES_ARE_PT
|
||||
&& ( ( m_shapes[i - 1] != SHAPES_ARE_PT && m_shapes[i - 1] == m_shapes[i] )
|
||||
&& ( m_shapes[i + 2] != SHAPES_ARE_PT && m_shapes[i + 2] == m_shapes[i] ) ) )
|
||||
{
|
||||
isInternalShapePoint = true;
|
||||
}
|
||||
|
||||
if( ( d < min_d ) && ( aAllowInternalShapePoints || !isInternalShapePoint ) )
|
||||
if( d < min_d )
|
||||
{
|
||||
min_d = d;
|
||||
nearest = i;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this the start or end of an arc? If so, return it directly
|
||||
if( !aAllowInternalShapePoints && ( IsArcStart( nearest ) || IsArcEnd( nearest ) ) )
|
||||
if( !aAllowInternalShapePoints )
|
||||
{
|
||||
//Snap to arc end points if the closest found segment is part of an arc segment
|
||||
if( nearest > 0 && nearest < PointCount() && IsArcSegment( nearest ) )
|
||||
{
|
||||
VECTOR2I ptToSegStart = CSegment( nearest ).A - aP;
|
||||
VECTOR2I ptToSegEnd = CSegment( nearest ).B - aP;
|
||||
|
||||
if( ptToSegStart.EuclideanNorm() > ptToSegEnd.EuclideanNorm() )
|
||||
nearest++;
|
||||
|
||||
// Is this the start or end of an arc? If so, return it directly
|
||||
if( IsArcStart( nearest ) || IsArcEnd( nearest ) )
|
||||
{
|
||||
//@todo should we calculate the nearest point to the "true" arc?
|
||||
return m_points[nearest];
|
||||
}
|
||||
else
|
||||
{
|
||||
const SHAPE_ARC& nearestArc = Arc( ArcIndex( nearest ) );
|
||||
VECTOR2I ptToArcStart = nearestArc.GetP0() - aP;
|
||||
VECTOR2I ptToArcEnd = nearestArc.GetP1() - aP;
|
||||
|
||||
if( ptToArcStart.EuclideanNorm() > ptToArcEnd.EuclideanNorm() )
|
||||
return nearestArc.GetP1();
|
||||
else
|
||||
return nearestArc.GetP0();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return CSegment( nearest ).NearestPoint( aP );
|
||||
}
|
||||
|
|
|
@ -260,4 +260,35 @@ BOOST_AUTO_TEST_CASE( Slice )
|
|||
}
|
||||
|
||||
|
||||
// Test SHAPE_LINE_CHAIN::NearestPoint( VECTOR2I )
|
||||
BOOST_AUTO_TEST_CASE( NearestPointPt )
|
||||
{
|
||||
SEG seg1( VECTOR2I( 0, 100000 ), VECTOR2I( 50000, 0 ) );
|
||||
SEG seg2( VECTOR2I( 200000, 0 ), VECTOR2I( 300000, 0 ) );
|
||||
SHAPE_ARC arc( VECTOR2I( 200000, 0 ), VECTOR2I( 300000, 0 ), 180.0 );
|
||||
|
||||
// Start a chain with 2 points (seg1)
|
||||
SHAPE_LINE_CHAIN chain( { seg1.A, seg1.B } );
|
||||
BOOST_CHECK_EQUAL( chain.PointCount(), 2 );
|
||||
// Add first arc
|
||||
chain.Append( arc );
|
||||
BOOST_CHECK_EQUAL( chain.PointCount(), 9 );
|
||||
// Add two points (seg2)
|
||||
chain.Append( seg2.A );
|
||||
chain.Append( seg2.B );
|
||||
BOOST_CHECK_EQUAL( chain.PointCount(), 11 );
|
||||
BOOST_CHECK( GEOM_TEST::IsOutlineValid( chain ) );
|
||||
|
||||
VECTOR2I ptOnArcCloseToStart( 297553, 31697 ); //should be index 3 in chain
|
||||
VECTOR2I ptOnArcCloseToEnd( 139709, 82983 ); //should be index 6 in chain
|
||||
|
||||
BOOST_CHECK_EQUAL( chain.NearestPoint( ptOnArcCloseToStart, true ), ptOnArcCloseToStart );
|
||||
BOOST_CHECK_EQUAL( chain.NearestPoint( ptOnArcCloseToStart, false ), arc.GetP0() );
|
||||
|
||||
BOOST_CHECK_EQUAL( chain.NearestPoint( ptOnArcCloseToEnd, true ), ptOnArcCloseToEnd );
|
||||
BOOST_CHECK_EQUAL( chain.NearestPoint( ptOnArcCloseToEnd, false ), arc.GetP1() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
Loading…
Reference in New Issue