64 double bc = ( b.
x * b.
x + b.
y * b.
y ) / 2.0;
65 double cd = ( -d.
x * d.
x - d.
y * d.
y ) / 2.0;
66 double det = -b.
x * d.
y + d.
x * b.
y;
68 if( fabs( det ) < 1.0e-6 )
72 aCenter->
x = ( -bc * d.
y - cd * b.
y ) * det;
73 aCenter->
y = ( b.
x * cd + d.
x * bc ) * det;
85 double yDelta_21 = aMid.
y - aStart.
y;
86 double xDelta_21 = aMid.
x - aStart.
x;
87 double yDelta_32 = aEnd.
y - aMid.
y;
88 double xDelta_32 = aEnd.
x - aMid.
x;
93 if( ( ( xDelta_21 == 0.0 ) && ( yDelta_32 == 0.0 ) )
94 || ( ( yDelta_21 == 0.0 ) && ( xDelta_32 == 0.0 ) ) )
96 center.
x = ( aStart.
x + aEnd.
x ) / 2.0;
97 center.
y = ( aStart.
y + aEnd.
y ) / 2.0;
108 double aSlope = yDelta_21 / xDelta_21;
109 double bSlope = yDelta_32 / xDelta_32;
111 if( aSlope == bSlope )
117 center.
x = ( aStart.
x + aMid.
x ) / 2.0;
118 center.
y = ( aStart.
y + aMid.
y ) / 2.0;
131 center.
x = ( aSlope * bSlope * ( aStart.
y - aEnd.
y ) + bSlope * ( aStart.
x + aMid.
x )
132 - aSlope * ( aMid.
x + aEnd.
x ) )
133 / ( 2 * ( bSlope - aSlope ) );
137 center.
y = ( ( ( aStart.
x + aMid.
x ) / 2.0 - center.
x ) / aSlope
138 + ( aStart.
y + aMid.
y ) / 2.0 );
143 ( ( ( aMid.
x + aEnd.
x ) / 2.0 - center.
x ) / bSlope + ( aMid.
y + aEnd.
y ) / 2.0 );
167 std::vector<TEST_CALC_ARC_CENTER_CASE> calc_center_cases = {
171 const double tolerance = 1.0;
204 double cavg = ( crs + crm + cre ) / 3.0;
206 if(
std::abs( crs - cavg ) > tolerance ||
std::abs( crm - cavg ) > tolerance
207 ||
std::abs( cre - cavg ) > tolerance )
209 msg <<
"CalcArcCenter failed.";
211 msg <<
"\nstart: " << entry.istart.Format();
212 msg <<
"\nmid: " << entry.imid.Format();
213 msg <<
"\nend: " << entry.iend.Format();
216 msg <<
"\nCalculated center: " << wxString::Format(
"%.15f", calcCenter.
x ) <<
", "
217 << wxString::Format(
"%.15f", calcCenter.
y );
219 msg <<
"\n Avg radius: " << wxString::Format(
"%.15f", cavg );
220 msg <<
"\nStart radius: " << wxString::Format(
"%.15f", crs );
221 msg <<
"\n Mid radius: " << wxString::Format(
"%.15f", crm );
222 msg <<
"\n End radius: " << wxString::Format(
"%.15f", cre );
226 EDA_ANGLE angStart( start - calcCenter );
235 RotatePoint( newMid, calcCenter, -angCenter / 2.0 );
238 msg <<
"\nNew mid: " << wxString::Format(
"%.15f", newMid.
x ) <<
", "
239 << wxString::Format(
"%.15f", newMid.
y );
241 msg <<
"\nNew end: " << wxString::Format(
"%.15f", newEnd.
x ) <<
", "
242 << wxString::Format(
"%.15f", newEnd.
y );
247 msg <<
"\nNew end is off by " << wxString::Format(
"%.15f", endsDist );
259 double r0_ravg = ( r0_rs + r0_rm + r0_rre ) / 3.0;
261 msg <<
"\nReference0 center: " << wxString::Format(
"%.15f", ref0Center.
x ) <<
", "
262 << wxString::Format(
"%.15f", ref0Center.
y );
264 msg <<
"\nRef0 Avg radius: " << wxString::Format(
"%.15f", r0_ravg );
265 msg <<
"\nRef0 Start radius: " << wxString::Format(
"%.15f", r0_rs );
266 msg <<
"\nRef0 Mid radius: " << wxString::Format(
"%.15f", r0_rm );
267 msg <<
"\nRef0 End radius: " << wxString::Format(
"%.15f", r0_rre );
278 double r1_ravg = ( r1_rs + r1_rm + r1_rre ) / 3.0;
280 msg <<
"\nReference1 center: " << wxString::Format(
"%.15f", ref1Center.
x ) <<
", "
281 << wxString::Format(
"%.15f", ref1Center.
y );
283 msg <<
"\nRef1 Avg radius: " << wxString::Format(
"%.15f", r1_ravg );
284 msg <<
"\nRef1 Start radius: " << wxString::Format(
"%.15f", r1_rs );
285 msg <<
"\nRef1 Mid radius: " << wxString::Format(
"%.15f", r1_rm );
286 msg <<
"\nRef1 End radius: " << wxString::Format(
"%.15f", r1_rre );
291 BOOST_CHECK_MESSAGE(
false, msg );
320BOOST_AUTO_TEST_SUITE_END()
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
BOOST_CHECK(box.ClosestPointTo(VECTOR2D(0, 0))==VECTOR2D(1, 2))
Test suite for KiCad math code.
BOOST_AUTO_TEST_SUITE(CadstarPartParser)
static const VECTOR2D Ref1CalcArcCenter(const VECTOR2D &aStart, const VECTOR2D &aMid, const VECTOR2D &aEnd)
static bool Ref0CircleCenterFrom3Points(const VECTOR2D &p1, const VECTOR2D &p2, const VECTOR2D &p3, VECTOR2D *aCenter)
Test suite for KiCad math code.
BOOST_AUTO_TEST_CASE(TestCalcArcCenter3Pts)
Declare the test suite.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
bool InterceptsPositiveX(double aStartAngle, double aEndAngle)
Test if an arc from aStartAngle to aEndAngle crosses the positive X axis (0 degrees).
bool InterceptsNegativeX(double aStartAngle, double aEndAngle)
Test if an arc from aStartAngle to aEndAngle crosses the negative X axis (180 degrees).
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
double EuclideanNorm(const VECTOR2I &vector)