Fix rounding errors in SHAPE_ARC::Collide + fix qa tests

Use CIRCLE::NearestPoint to ensure consistency
This commit is contained in:
Roberto Fernandez Bautista 2022-04-11 13:38:57 +01:00
parent 3b796265a0
commit 4defc946ef
2 changed files with 29 additions and 26 deletions

View File

@ -369,28 +369,28 @@ bool SHAPE_ARC::IsClockwise() const
bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual, bool SHAPE_ARC::Collide( const VECTOR2I& aP, int aClearance, int* aActual,
VECTOR2I* aLocation ) const VECTOR2I* aLocation ) const
{ {
int minDist = aClearance + std::max( m_width / 2, 1 ); int minDist = aClearance + m_width / 2;
auto bbox = BBox( minDist ); auto bbox = BBox( minDist );
// Fast check using bounding box: // Fast check using bounding box:
if( !bbox.Contains( aP ) ) if( !bbox.Contains( aP ) )
return false; return false;
VECTOR2I center = GetCenter(); CIRCLE fullCircle( GetCenter(), GetRadius() );
VECTOR2I vec = aP - center; VECTOR2I nearestPt = fullCircle.NearestPoint( aP );
int dist = abs( vec.EuclideanNorm() - GetRadius() ); int dist = ( nearestPt - aP ).EuclideanNorm();
// If not a 360 degree arc, need to use arc angles to decide if point collides // If not a 360 degree arc, need to use arc angles to decide if point collides
if( m_start != m_end ) if( m_start != m_end )
{ {
bool ccw = GetCentralAngle() > ANGLE_0; bool ccw = GetCentralAngle() > ANGLE_0;
EDA_ANGLE vecAngle( vec ); EDA_ANGLE angleToPt( aP - fullCircle.Center ); // Angle from center to the point
EDA_ANGLE rotatedVecAngle = ( vecAngle.Normalize() - GetStartAngle() ).Normalize(); EDA_ANGLE rotatedPtAngle = ( angleToPt.Normalize() - GetStartAngle() ).Normalize();
EDA_ANGLE rotatedEndAngle = ( GetEndAngle() - GetStartAngle() ).Normalize(); EDA_ANGLE rotatedEndAngle = ( GetEndAngle() - GetStartAngle() ).Normalize();
if( ( ccw && rotatedVecAngle > rotatedEndAngle ) if( ( ccw && rotatedPtAngle > rotatedEndAngle )
|| ( !ccw && rotatedVecAngle < rotatedEndAngle ) ) || ( !ccw && rotatedPtAngle < rotatedEndAngle ) )
{ {
int distStartpt = ( aP - m_start ).EuclideanNorm(); int distStartpt = ( aP - m_start ).EuclideanNorm();
int distEndpt = ( aP - m_end ).EuclideanNorm(); int distEndpt = ( aP - m_end ).EuclideanNorm();

View File

@ -579,14 +579,14 @@ static const std::vector<ARC_PT_COLLIDE_CASE> arc_pt_collide_cases = {
{ " 270deg, 5 cl, 90 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 0, 105 }, true, 5 }, { " 270deg, 5 cl, 90 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 0, 105 }, true, 5 },
{ " 270deg, 5 cl, 180 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { -105, 0 }, true, 5 }, { " 270deg, 5 cl, 180 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { -105, 0 }, true, 5 },
{ " 270deg, 5 cl, 270 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 0, -105 }, true, 5 }, { " 270deg, 5 cl, 270 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 0, -105 }, true, 5 },
{ " 270deg, 5 cl, 45 deg, 5 pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 75, 74 }, true, 5 }, { " 270deg, 5 cl, 45 deg, 5 pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 74, 75 }, true, 5 }, // 74.246, -74.246
{ " 270deg, 5 cl, -45 deg, 5 pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 75, -74 }, false, -1 }, { " 270deg, 5 cl, -45 deg, 5 pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 74, -75 }, false, -1 }, //74.246, -74.246
{ " 270deg, 5 cl, 45 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 67, 68 }, true, 5 }, { " 270deg, 5 cl, 45 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 67, 67 }, true, 5 }, // 67.17, 67.17
{ " 270deg, 5 cl, -45 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 67, -68 }, false, -1 }, { " 270deg, 5 cl, -45 deg, 5 neg", { { 0, 0 }, { 100, 0 }, 270.0 }, 5, { 67, -67 }, false, -1 }, // 67.17, -67.17
{ " 270deg, 4 cl, 0 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { 106, 0 }, false, -1 }, { " 270deg, 4 cl, 0 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { 105, 0 }, false, -1 },
{ " 270deg, 4 cl, 90 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { 0, 106 }, false, -1 }, { " 270deg, 4 cl, 90 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { 0, 105 }, false, -1 },
{ " 270deg, 4 cl, 180 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { -106, 0 }, false, -1 }, { " 270deg, 4 cl, 180 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { -105, 0 }, false, -1 },
{ " 270deg, 4 cl, 270 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { 0, -106 }, false, -1 }, { " 270deg, 4 cl, 270 deg pos", { { 0, 0 }, { 100, 0 }, 270.0 }, 4, { 0, -105 }, false, -1 },
{ " 90deg, 0 cl, 0 deg ", { { 0, 0 }, { 71, -71 }, 90.0 }, 0, { 71, -71 }, true, 0 }, { " 90deg, 0 cl, 0 deg ", { { 0, 0 }, { 71, -71 }, 90.0 }, 0, { 71, -71 }, true, 0 },
{ " 90deg, 0 cl, 45 deg ", { { 0, 0 }, { 71, -71 }, 90.0 }, 0, { 100, 0 }, true, 0 }, { " 90deg, 0 cl, 45 deg ", { { 0, 0 }, { 71, -71 }, 90.0 }, 0, { 100, 0 }, true, 0 },
{ " 90deg, 0 cl, 90 deg ", { { 0, 0 }, { 71, -71 }, 90.0 }, 0, { 71, 71 }, true, 0 }, { " 90deg, 0 cl, 90 deg ", { { 0, 0 }, { 71, -71 }, 90.0 }, 0, { 71, 71 }, true, 0 },
@ -597,6 +597,12 @@ static const std::vector<ARC_PT_COLLIDE_CASE> arc_pt_collide_cases = {
{ " -90deg, 0 cl, 90 deg ", { { 0, 0 }, { 71, 71 }, -90.0 }, 0, { 71, 71 }, true, 0 }, { " -90deg, 0 cl, 90 deg ", { { 0, 0 }, { 71, 71 }, -90.0 }, 0, { 71, 71 }, true, 0 },
{ " -90deg, 0 cl, 135 deg ", { { 0, 0 }, { 71, 71 }, -90.0 }, 0, { 0, -100 }, false, -1 }, { " -90deg, 0 cl, 135 deg ", { { 0, 0 }, { 71, 71 }, -90.0 }, 0, { 0, -100 }, false, -1 },
{ " -90deg, 0 cl, -45 deg ", { { 0, 0 }, { 71, 71 }, -90.0 }, 0, { 0, 100 }, false, -1 }, { " -90deg, 0 cl, -45 deg ", { { 0, 0 }, { 71, 71 }, -90.0 }, 0, { 0, 100 }, false, -1 },
{ "issue 11358",
{ { 119888000, 60452000 }, { 120904000, 60452000 }, 360.0 },
0,
{ 120395500, 59571830 },
true,
0 },
}; };
@ -609,8 +615,6 @@ BOOST_AUTO_TEST_CASE( CollidePt )
SHAPE_ARC arc( c.m_geom.m_center_point, c.m_geom.m_start_point, SHAPE_ARC arc( c.m_geom.m_center_point, c.m_geom.m_start_point,
EDA_ANGLE( c.m_geom.m_center_angle, DEGREES_T ) ); EDA_ANGLE( c.m_geom.m_center_angle, DEGREES_T ) );
if( c.m_arc_clearance > 0 )
{
// Test a zero width arc (distance should equal the clearance) // Test a zero width arc (distance should equal the clearance)
BOOST_TEST_CONTEXT( "Test Clearance" ) BOOST_TEST_CONTEXT( "Test Clearance" )
{ {
@ -619,7 +623,6 @@ BOOST_AUTO_TEST_CASE( CollidePt )
c.m_exp_result ); c.m_exp_result );
BOOST_CHECK_EQUAL( dist, c.m_exp_distance ); BOOST_CHECK_EQUAL( dist, c.m_exp_distance );
} }
}
// Test by changing the width of the arc (distance should equal zero) // Test by changing the width of the arc (distance should equal zero)
BOOST_TEST_CONTEXT( "Test Width" ) BOOST_TEST_CONTEXT( "Test Width" )