SHAPE_ARC: Fix GetCentralAngle normalization documentation

This appears to have always been [-360 .. 360], as some tests in
test_shape_arc.cpp have had negative values for a very long time.

Add tests on the start, end and central angle accessors to enforce
the documented normalizations.
This commit is contained in:
John Beard 2025-06-03 09:24:50 +08:00
parent 026eb2512d
commit d15b2b7305
3 changed files with 47 additions and 9 deletions

View File

@ -245,7 +245,9 @@ public:
} }
/** /**
* @return the central angle of the arc shape, normalized between 0..360 deg. * Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
*
* @return the central angle of the arc shape, normalized between -360..360 deg.
*/ */
EDA_ANGLE GetCentralAngle() const; EDA_ANGLE GetCentralAngle() const;

View File

@ -875,8 +875,8 @@ EDA_ANGLE SHAPE_ARC::GetCentralAngle() const
// Using only m_start and m_end arc points to calculate the central arc is not enough // Using only m_start and m_end arc points to calculate the central arc is not enough
// there are 2 arcs having the same center and end points. // there are 2 arcs having the same center and end points.
// Using the middle point is mandatory to know what arc is the right one. // Using the middle point is mandatory to know what arc is the right one.
// IsClockwise() uses m_start, m_middle and m_end arc points to know the arc orientation // IsCCW() uses m_start, m_middle and m_end arc points to know the arc orientation
if( !IsClockwise() ) if( IsCCW() )
{ {
if( angle < ANGLE_0 ) if( angle < ANGLE_0 )
angle += ANGLE_360; angle += ANGLE_360;

View File

@ -88,8 +88,18 @@ static void CheckArcGeom( const SHAPE_ARC& aArc, const ARC_PROPERTIES& aProps, c
BOOST_CHECK_PREDICATE( KI_TEST::IsWithin<double>, BOOST_CHECK_PREDICATE( KI_TEST::IsWithin<double>,
( aArc.GetRadius() )( aProps.m_radius )( aSynErrIU ) ); ( aArc.GetRadius() )( aProps.m_radius )( aSynErrIU ) );
// Angle normalization contracts
BOOST_TEST( aArc.GetStartAngle().AsDegrees() >= 0.0 );
BOOST_TEST( aArc.GetStartAngle().AsDegrees() <= 360.0 );
BOOST_TEST( aArc.GetEndAngle().AsDegrees() >= 0.0 );
BOOST_TEST( aArc.GetEndAngle().AsDegrees() <= 360.0 );
BOOST_TEST( aArc.GetCentralAngle().AsDegrees() >= -360.0 );
BOOST_TEST( aArc.GetCentralAngle().AsDegrees() <= 360.0 );
/// Check the chord agrees /// Check the chord agrees
const auto chord = aArc.GetChord(); const SEG chord = aArc.GetChord();
BOOST_CHECK_PREDICATE( KI_TEST::IsVecWithinTol<VECTOR2I>, BOOST_CHECK_PREDICATE( KI_TEST::IsVecWithinTol<VECTOR2I>,
( chord.A )( aProps.m_start_point )( pos_tol ) ); ( chord.A )( aProps.m_start_point )( pos_tol ) );
@ -197,6 +207,25 @@ static const std::vector<ARC_SME_CASE> arc_sme_cases = {
{ { -100, 0 }, { 200, 100 } }, { { -100, 0 }, { 200, 100 } },
}, },
}, },
{
"S(100,0), M(0,100), E(-100,0) (reversed)",
{
{ 100, 0 },
{ 0, 100 },
{ -100, 0 },
},
0,
{
{ 0, 0 },
{ 100, 0 },
{ -100, 0 },
-180,
0,
180,
100,
{ { -100, 0 }, { 200, 100 } },
},
},
{ {
// This data has a midpoint not exactly at the midway point of the arc. // This data has a midpoint not exactly at the midway point of the arc.
// This should be corrected by the constructor. // This should be corrected by the constructor.
@ -225,7 +254,12 @@ static const std::vector<ARC_SME_CASE> arc_sme_cases = {
BOOST_DATA_TEST_CASE( BasicSMEGeom, boost::unit_test::data::make( arc_sme_cases ), c ) BOOST_DATA_TEST_CASE( BasicSMEGeom, boost::unit_test::data::make( arc_sme_cases ), c )
{ {
const auto this_arc = SHAPE_ARC{ c.m_geom.m_start_point, c.m_geom.m_mid_point, c.m_geom.m_end_point, c.m_width }; const SHAPE_ARC this_arc{
c.m_geom.m_start_point,
c.m_geom.m_mid_point,
c.m_geom.m_end_point,
c.m_width,
};
CheckArc( this_arc, c.m_properties ); CheckArc( this_arc, c.m_properties );
} }
@ -402,10 +436,12 @@ static const std::vector<ARC_CPA_CASE> arc_cases = {
BOOST_DATA_TEST_CASE( BasicCPAGeom, boost::unit_test::data::make( arc_cases ), c ) BOOST_DATA_TEST_CASE( BasicCPAGeom, boost::unit_test::data::make( arc_cases ), c )
{ {
const SHAPE_ARC this_arc{
const auto this_arc = SHAPE_ARC{ c.m_geom.m_center_point, c.m_geom.m_start_point, c.m_geom.m_center_point,
EDA_ANGLE( c.m_geom.m_center_angle, DEGREES_T ), c.m_geom.m_start_point,
c.m_width }; EDA_ANGLE( c.m_geom.m_center_angle, DEGREES_T ),
c.m_width,
};
CheckArc( this_arc, c.m_properties ); CheckArc( this_arc, c.m_properties );
} }