37 template <
typename Real>
61 void GetRoots(Real d0, Real c0,
int& numRoots, Real* roots);
62 void GetRoots(Real d0, Real d1, Real c0, Real c1,
int& numRoots,
65 int Classify(Real minSqrDistance, Real maxSqrDistance, Real d0c0pd1c1);
68 template <
typename Real>
146 std::array<Real, 5>& coeff);
148 void DoRootFinding(Result&
result);
149 void D4NotZeroEBarNotZero(Result&
result);
150 void D4NotZeroEBarZero(Real
const& xbar, Result&
result);
151 void D4ZeroD2NotZeroE2NotZero(Result&
result);
152 void D4ZeroD2NotZeroE2Zero(Result&
result);
153 void D4ZeroD2Zero(Result&
result);
156 void SpecialIntersection(Real
const&
x,
bool transverse, Result&
result);
163 std::array<Vector2<Real>, 2>
axis;
174 void FinishEllipseInfo(EllipseInfo& E);
176 void AreaDispatch(EllipseInfo
const& E0, EllipseInfo
const& E1,
179 void AreaCS(EllipseInfo
const& E0, EllipseInfo
const& E1,
182 void Area2(EllipseInfo
const& E0, EllipseInfo
const& E1,
int i0,
int i1,
185 void Area4(EllipseInfo
const& E0, EllipseInfo
const& E1,
188 Real ComputeAreaChordRegion(EllipseInfo
const& E,
191 Real ComputeIntegral(EllipseInfo
const& E, Real
const& theta);
195 Real
mZero, mOne, mTwo, mPi, mTwoPi;
199 std::array<Real, 5> mA, mB, mD,
mF;
200 std::array<Real, 3> mC,
mE;
205 template <
typename Real>
208 template <
typename Real>
214 template <
typename Real>
216 Ellipse2<Real>
const& ellipse0, Ellipse2<Real>
const& ellipse1)
218 Real
const zero = 0, one = 1;
223 R0.
SetCol(0, ellipse0.axis[0]);
224 R0.
SetCol(1, ellipse0.axis[1]);
226 one / (ellipse0.extent[0] * ellipse0.extent[0]), zero,
227 zero, one / (ellipse0.extent[1] * ellipse0.extent[1]) };
232 R1.
SetCol(0, ellipse1.axis[0]);
233 R1.
SetCol(1, ellipse1.axis[1]);
235 one / (ellipse1.extent[0] * ellipse1.extent[0]), zero,
236 zero, one / (ellipse1.extent[1] * ellipse1.extent[1]) };
240 ellipse0.extent[0], zero,
241 zero, ellipse0.extent[1] };
243 one / ellipse0.extent[0], zero,
244 zero, one / ellipse0.extent[1] };
253 std::array<Real, 2> D;
254 std::array<std::array<Real, 2>, 2> evec;
255 es(M2(0, 0), M2(0, 1), M2(1, 1), +1, D, evec);
269 Real minSqrDistance = std::numeric_limits<Real>::max();
270 Real maxSqrDistance = zero;
276 for (
int i = 0; i < 2; ++i)
278 Real invD = one / D[i];
279 if (invD < minSqrDistance)
281 minSqrDistance = invD;
283 if (invD > maxSqrDistance)
285 maxSqrDistance = invD;
288 return Classify(minSqrDistance, maxSqrDistance, zero);
296 Real d0 = D[0], d1 = D[1];
297 Real c0 = K[0] * K[0], c1 = K[1] * K[1];
301 std::vector<std::pair<Real, Real>>
param(2);
304 param[0] = std::make_pair(d0, c0);
305 param[1] = std::make_pair(d1, c1);
309 param[0] = std::make_pair(d1, c1);
310 param[1] = std::make_pair(d0, c0);
313 std::vector<std::pair<Real, Real>> valid;
318 for (
int i = 0; i < 2; ++i)
320 if (param[i].second > zero)
322 valid.push_back(param[i]);
329 param[0].second += param[1].second;
330 if (param[0].second > zero)
332 valid.push_back(param[0]);
336 size_t numValid = valid.size();
341 GetRoots(valid[0].first, valid[1].first, valid[0].second,
342 valid[1].second, numRoots, roots);
344 else if (numValid == 1)
346 GetRoots(valid[0].first, valid[0].second, numRoots, roots);
350 for (
int i = 0; i < numRoots; ++i)
353 Real p0 = d0 * K[0] * s / (d0 * s - (Real)1);
354 Real p1 = d1 * K[1] * s / (d1 * s - (Real)1);
355 Real sqrDistance = p0 * p0 + p1 * p1;
356 if (sqrDistance < minSqrDistance)
358 minSqrDistance = sqrDistance;
360 if (sqrDistance > maxSqrDistance)
362 maxSqrDistance = sqrDistance;
366 return Classify(minSqrDistance, maxSqrDistance, d0 * c0 + d1 * c1);
369 template <
typename Real>
370 void TIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::GetRoots(Real d0, Real c0,
371 int& numRoots, Real* roots)
374 Real
const one = (Real)1;
375 Real temp = sqrt(d0*c0);
378 roots[0] = (one - temp) * inv;
379 roots[1] = (one + temp) * inv;
382 template <
typename Real>
383 void TIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::GetRoots(Real d0, Real d1,
384 Real c0, Real c1,
int& numRoots, Real* roots)
389 Real
const zero = 0, one = (Real)1;
392 Real sum = d0c0 + d1c1;
393 Real sqrtsum = sqrt(sum);
395 std::function<Real(Real)> F = [&one, d0, d1, d0c0, d1c1](Real
s)
397 Real invN0 = one / (d0*
s - one);
398 Real invN1 = one / (d1*
s - one);
399 Real term0 = d0c0 * invN0 * invN0;
400 Real term1 = d1c1 * invN1 * invN1;
401 Real
f = term0 + term1 - one;
405 std::function<Real(Real)> DF = [&one, d0, d1, d0c0, d1c1](Real
s)
408 Real invN0 = one / (d0*
s - one);
409 Real invN1 = one / (d1*
s - one);
410 Real term0 = d0 * d0c0 * invN0 * invN0 * invN0;
411 Real term1 = d1 * d1c1 * invN1 * invN1 * invN1;
412 Real df = -two * (term0 + term1);
416 unsigned int const maxIterations = (
unsigned int)(
417 3 + std::numeric_limits<Real>::digits -
418 std::numeric_limits<Real>::min_exponent);
419 unsigned int iterations;
422 Real invD0 = one / d0;
423 Real invD1 = one / d1;
424 Real smin, smax,
s, fval;
432 smin = (one - sqrtsum) * invD1;
434 LogAssert(fval <= zero,
"Unexpected condition.");
443 LogAssert(iterations > 0,
"Unexpected condition.");
444 roots[numRoots++] =
s;
454 Real
const oneThird = (Real)(1.0 / 3.0);
455 Real rho = pow(d0 * d0c0 / (d1 * d1c1), oneThird);
456 Real smid = (one + rho) / (d0 + rho * d1);
465 LogAssert(iterations > 0,
"Unexpected condition.");
466 roots[numRoots++] =
s;
470 LogAssert(iterations > 0,
"Unexpected condition.");
471 roots[numRoots++] =
s;
473 else if (fmid == zero)
475 roots[numRoots++] = smid;
481 smax = (one + sqrtsum) * invD1;
483 LogAssert(fval <= zero,
"Unexpected condition.");
487 LogAssert(iterations > 0,
"Unexpected condition.");
488 roots[numRoots++] =
s;
491 template <
typename Real>
492 int TIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::Classify(
493 Real minSqrDistance, Real maxSqrDistance, Real d0c0pd1c1)
495 Real
const one = (Real)1;
497 if (maxSqrDistance < one)
499 return ELLIPSE0_STRICTLY_CONTAINS_ELLIPSE1;
501 else if (maxSqrDistance > one)
503 if (minSqrDistance < one)
505 return ELLIPSES_OVERLAP;
507 else if (minSqrDistance > one)
511 return ELLIPSES_SEPARATED;
515 return ELLIPSE1_STRICTLY_CONTAINS_ELLIPSE0;
522 return ELLIPSE0_OUTSIDE_ELLIPSE1_BUT_TANGENT;
526 return ELLIPSE1_CONTAINS_ELLIPSE0_BUT_TANGENT;
532 if (minSqrDistance < one)
534 return ELLIPSE0_CONTAINS_ELLIPSE1_BUT_TANGENT;
538 return ELLIPSES_EQUAL;
547 template <
typename Real>
562 template <
typename Real>
565 Ellipse2<Real>
const& ellipse0, Ellipse2<Real>
const& ellipse1)
569 rCenter = { ellipse0.center[0], ellipse0.center[1] };
570 rAxis[0] = { ellipse0.axis[0][0], ellipse0.axis[0][1] };
571 rAxis[1] = { ellipse0.axis[1][0], ellipse0.axis[1][1] };
574 ellipse0.extent[0] * ellipse0.extent[0],
575 ellipse0.extent[1] * ellipse0.extent[1]
577 ToCoefficients(rCenter, rAxis, rSqrExtent, mA);
579 rCenter = { ellipse1.center[0], ellipse1.center[1] };
580 rAxis[0] = { ellipse1.axis[0][0], ellipse1.axis[0][1] };
581 rAxis[1] = { ellipse1.axis[1][0], ellipse1.axis[1][1] };
584 ellipse1.extent[0] * ellipse1.extent[0],
585 ellipse1.extent[1] * ellipse1.extent[1]
587 ToCoefficients(rCenter, rAxis, rSqrExtent, mB);
590 DoRootFinding(result);
594 template <
typename Real>
603 rCenter = { center0[0], center0[1] };
604 rAxis[0] = { axis0[0][0], axis0[0][1] };
605 rAxis[1] = { axis0[1][0], axis0[1][1] };
606 rSqrExtent = { sqrExtent0[0], sqrExtent0[1] };
607 ToCoefficients(rCenter, rAxis, rSqrExtent, mA);
609 rCenter = { center1[0], center1[1] };
610 rAxis[0] = { axis1[0][0], axis1[0][1] };
611 rAxis[1] = { axis1[1][0], axis1[1][1] };
612 rSqrExtent = { sqrExtent1[0], sqrExtent1[1] };
613 ToCoefficients(rCenter, rAxis, rSqrExtent, mB);
616 DoRootFinding(result);
620 template <
typename Real>
625 Real denom0 =
Dot(axis[0], axis[0]) * sqrExtent[0];
626 Real denom1 =
Dot(axis[1], axis[1]) * sqrExtent[1];
632 Real
const& denom = A(1, 1);
633 coeff[0] = (
Dot(center, product) - mOne) / denom;
634 coeff[1] = B[0] / denom;
635 coeff[2] = B[1] / denom;
636 coeff[3] = A(0, 0) / denom;
637 coeff[4] = mTwo * A(0, 1) / denom;
641 template <
typename Real>
642 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::DoRootFinding(
646 for (
int i = 0; i < 5; ++i)
648 mD[i] = mA[i] - mB[i];
656 result.intersect =
false;
657 result.numPoints = std::numeric_limits<int>::max();
661 result.numPoints = 0;
663 mA2Div2 = mA[2] / mTwo;
664 mA4Div2 = mA[4] / mTwo;
665 mC[0] = mA[0] - mA2Div2 * mA2Div2;
666 mC[1] = mA[1] - mA2Div2 * mA[4];
667 mC[2] = mA[3] - mA4Div2 * mA4Div2;
668 mE[0] = mD[0] - mA2Div2 * mD[2];
669 mE[1] = mD[1] - mA2Div2 * mD[4] - mA4Div2 * mD[2];
670 mE[2] = mD[3] - mA4Div2 * mD[4];
674 Real xbar = -mD[2] / mD[4];
675 Real ebar = mE[0] + xbar * (mE[1] + xbar * mE[2]);
678 D4NotZeroEBarNotZero(result);
682 D4NotZeroEBarZero(xbar, result);
685 else if (mD[2] != mZero)
689 D4ZeroD2NotZeroE2NotZero(result);
693 D4ZeroD2NotZeroE2Zero(result);
698 D4ZeroD2Zero(result);
701 result.intersect = (result.numPoints > 0);
704 template <
typename Real>
705 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::D4NotZeroEBarNotZero(
709 Real d2d2 = mD[2] * mD[2], d2d4 = mD[2] * mD[4], d4d4 = mD[4] * mD[4];
710 Real e0e0 = mE[0] * mE[0], e0e1 = mE[0] * mE[1], e0e2 = mE[0] * mE[2];
711 Real e1e1 = mE[1] * mE[1], e1e2 = mE[1] * mE[2], e2e2 = mE[2] * mE[2];
712 std::array<Real, 5>
f =
715 mC[1] * d2d2 + mTwo * (mC[0] * d2d4 + e0e1),
716 mC[2] * d2d2 + mC[0] * d4d4 + e1e1 + mTwo * (mC[1] * d2d4 + e0e2),
717 mC[1] * d4d4 + mTwo * (mC[2] * d2d4 + e1e2),
721 std::map<Real, int> rmMap;
727 for (
auto const& rm : rmMap)
729 Real
const&
x = rm.first;
730 Real
w = -(mE[0] + x * (mE[1] + x * mE[2])) / (mD[2] + mD[4] *
x);
731 Real
y = w - (mA2Div2 + x * mA4Div2);
732 result.points[result.numPoints] = {
x, y };
733 result.isTransverse[result.numPoints++] = (rm.second == 1);
737 template <
typename Real>
738 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::D4NotZeroEBarZero(
739 Real
const& xbar, Result&
result)
743 Real translate,
w,
y;
746 Real ncbar = -(mC[0] + xbar * (mC[1] + xbar * mC[2]));
749 translate = mA2Div2 + xbar * mA4Div2;
752 result.points[result.numPoints] = { xbar, y };
755 result.isTransverse[result.numPoints++] =
true;
758 result.points[result.numPoints] = { xbar, y };
759 result.isTransverse[result.numPoints++] =
true;
763 result.isTransverse[result.numPoints++] =
false;
768 std::array<Real, 2>
h;
769 h[1] = mE[2] / mD[4];
770 h[0] = (mE[1] - mD[2] * h[1]) / mD[4];
771 std::array<Real, 3>
f =
774 mC[1] + mTwo * h[0] * h[1],
778 std::map<Real, int> rmMap;
781 for (
auto const& rm : rmMap)
783 Real
const&
x = rm.first;
784 translate = mA2Div2 + x * mA4Div2;
785 w = -(h[0] + x * h[1]);
787 result.points[result.numPoints] = {
x, y };
788 result.isTransverse[result.numPoints++] = (rm.second == 1);
792 template <
typename Real>
793 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::D4ZeroD2NotZeroE2NotZero(
796 Real d2d2 = mD[2] * mD[2];
797 std::array<Real, 5>
f =
799 mC[0] * d2d2 + mE[0] * mE[0],
800 mC[1] * d2d2 + mTwo * mE[0] * mE[1],
801 mC[2] * d2d2 + mE[1] * mE[1] + mTwo * mE[0] * mE[2],
802 mTwo * mE[1] * mE[2],
806 std::map<Real, int> rmMap;
809 for (
auto const& rm : rmMap)
811 Real
const&
x = rm.first;
812 Real translate = mA2Div2 + x * mA4Div2;
813 Real
w = -(mE[0] + x * (mE[1] + x * mE[2])) / mD[2];
814 Real
y = w - translate;
815 result.points[result.numPoints] = {
x, y };
816 result.isTransverse[result.numPoints++] = (rm.second == 1);
820 template <
typename Real>
821 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::D4ZeroD2NotZeroE2Zero(
824 Real d2d2 = mD[2] * mD[2];
825 std::array<Real, 3>
f =
827 mC[0] * d2d2 + mE[0] * mE[0],
828 mC[1] * d2d2 + mTwo * mE[0] * mE[1],
829 mC[2] * d2d2 + mE[1] * mE[1]
832 std::map<Real, int> rmMap;
835 for (
auto const& rm : rmMap)
837 Real
const&
x = rm.first;
838 Real translate = mA2Div2 + x * mA4Div2;
839 Real
w = -(mE[0] + x * mE[1]) / mD[2];
840 Real
y = w - translate;
841 result.points[result.numPoints] = {
x, y };
842 result.isTransverse[result.numPoints++] = (rm.second == 1);
846 template <
typename Real>
847 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::D4ZeroD2Zero(
857 std::array<Real, 2>
f = { mE[0] / mE[2], mE[1] / mE[2] };
859 Real mid = -f[1] / mTwo;
860 Real discr = mid * mid - f[0];
872 std::array<Real, 2>
g =
874 mC[0] - mC[2] * f[0],
881 Real
r = -g[0] / g[1] - mid;
889 SpecialIntersection(mid + sqrtDiscr,
true, result);
891 else if (discr == rsqr)
893 SpecialIntersection(mid + sqrtDiscr,
false, result);
900 SpecialIntersection(mid - sqrtDiscr,
true, result);
907 SpecialIntersection(mid - sqrtDiscr,
true, result);
909 else if (discr == rsqr)
911 SpecialIntersection(mid - sqrtDiscr,
false, result);
915 else if (g[1] < mZero)
918 Real
r = -g[0] / g[1] - mid;
926 SpecialIntersection(mid - sqrtDiscr,
true, result);
930 SpecialIntersection(mid - sqrtDiscr,
false, result);
937 SpecialIntersection(mid + sqrtDiscr,
true, result);
944 SpecialIntersection(mid + sqrtDiscr,
true, result);
946 else if (discr == rsqr)
948 SpecialIntersection(mid + sqrtDiscr,
false, result);
959 SpecialIntersection(mid - sqrtDiscr,
true, result);
960 SpecialIntersection(mid + sqrtDiscr,
true, result);
962 else if (g[0] == mZero)
965 SpecialIntersection(mid - sqrtDiscr,
false, result);
966 SpecialIntersection(mid + sqrtDiscr,
false, result);
970 else if (discr == mZero)
973 Real nchat = -(mC[0] + mid * (mC[1] + mid * mC[2]));
976 SpecialIntersection(mid,
true, result);
978 else if (nchat == mZero)
980 SpecialIntersection(mid,
false, result);
984 else if (mE[1] != mZero)
986 Real xhat = -mE[0] / mE[1];
987 Real nchat = -(mC[0] + xhat * (mC[1] + xhat * mC[2]));
990 SpecialIntersection(xhat,
true, result);
992 else if (nchat == mZero)
994 SpecialIntersection(xhat,
false, result);
999 template <
typename Real>
1000 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::SpecialIntersection(
1001 Real
const&
x,
bool transverse, Result&
result)
1005 Real translate = mA2Div2 + x * mA4Div2;
1006 Real nc = -(mC[0] + x * (mC[1] + x * mC[2]));
1015 Real
y = w - translate;
1016 result.points[result.numPoints] = {
x, y };
1017 result.isTransverse[result.numPoints++] =
true;
1020 result.points[result.numPoints] = {
x, y };
1021 result.isTransverse[result.numPoints++] =
true;
1026 Real
y = -(mA2Div2 + x * mA4Div2);
1027 result.points[result.numPoints] = {
x, y };
1028 result.isTransverse[result.numPoints++] =
false;
1036 template <
typename Real>
1037 typename FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::AreaResult
1038 FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::AreaOfIntersection(
1039 Ellipse2<Real>
const& ellipse0, Ellipse2<Real>
const& ellipse1)
1042 E0.center = ellipse0.
center;
1043 E0.axis = ellipse0.
axis;
1044 E0.extent = ellipse0.
extent;
1046 FinishEllipseInfo(E0);
1049 E1.center = ellipse1.
center;
1050 E1.axis = ellipse1.
axis;
1051 E1.extent = ellipse1.
extent;
1053 FinishEllipseInfo(E1);
1056 ar.configuration = 0;
1057 ar.findResult =
operator()(ellipse0, ellipse1);
1059 AreaDispatch(E0, E1, ar);
1063 template <
typename Real>
1064 typename FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::AreaResult
1065 FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::AreaOfIntersection(
1071 E0.center = center0;
1072 E0.axis = { axis0[0], axis0[1] };
1078 E0.sqrExtent = sqrExtent0;
1079 FinishEllipseInfo(E0);
1082 E1.center = center1;
1083 E1.axis = { axis1[0], axis1[1] };
1089 E1.sqrExtent = sqrExtent1;
1090 FinishEllipseInfo(E1);
1093 ar.configuration = 0;
1094 ar.findResult =
operator()(center0, axis0, sqrExtent0, center1, axis1,
1097 AreaDispatch(E0, E1, ar);
1101 template <
typename Real>
1102 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::FinishEllipseInfo(
1106 (E.sqrExtent[0] *
Dot(E.axis[0], E.axis[0]));
1108 (E.sqrExtent[1] *
Dot(E.axis[1], E.axis[1]));
1109 E.AB = E.extent[0] * E.extent[1];
1110 E.halfAB = E.AB / mTwo;
1111 E.BpA = E.extent[1] + E.extent[0];
1112 E.BmA = E.extent[1] - E.extent[0];
1115 template <
typename Real>
1116 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::AreaDispatch(
1117 EllipseInfo
const& E0, EllipseInfo
const& E1, AreaResult& ar)
1119 if (ar.findResult.intersect)
1121 if (ar.findResult.numPoints == 1)
1126 else if (ar.findResult.numPoints == 2)
1128 if (ar.findResult.isTransverse[0])
1131 Area2(E0, E1, 0, 1, ar);
1140 else if (ar.findResult.numPoints == 3)
1144 if (!ar.findResult.isTransverse[0])
1146 Area2(E0, E1, 1, 2, ar);
1148 else if (!ar.findResult.isTransverse[1])
1150 Area2(E0, E1, 2, 0, ar);
1154 Area2(E0, E1, 0, 1, ar);
1169 template <
typename Real>
1170 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::AreaCS(
1171 EllipseInfo
const& E0, EllipseInfo
const& E1, AreaResult& ar)
1173 if (ar.findResult.numPoints <= 1)
1176 Real qform0 =
Dot(diff, E0.M * diff);
1177 Real qform1 =
Dot(diff, E1.M * diff);
1178 if (qform0 > mOne && qform1 > mOne)
1183 ar.configuration = AreaResult::ELLIPSES_ARE_SEPARATED;
1192 ar.configuration = AreaResult::E1_CONTAINS_E0;
1193 ar.area = mPi * E0.AB;
1197 ar.configuration = AreaResult::E0_CONTAINS_E1;
1198 ar.area = mPi * E1.AB;
1204 ar.configuration = AreaResult::ELLIPSES_ARE_EQUAL;
1205 ar.area = mPi * E0.AB;
1209 template <
typename Real>
1210 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::Area2(
1211 EllipseInfo
const& E0, EllipseInfo
const& E1,
int i0,
int i1,
1214 ar.configuration = AreaResult::ONE_CHORD_REGION;
1221 Vector2<Real> P0mC0 = P0 - E0.center, P0mC1 = P0 - E1.center;
1222 Vector2<Real> P1mC0 = P1 - E0.center, P1mC1 = P1 - E1.center;
1227 Real dotperp =
DotPerp(N1, N0);
1230 if (dotperp > mZero)
1234 ComputeAreaChordRegion(E0, P0mC0, P1mC0) +
1235 ComputeAreaChordRegion(E1, P1mC1, P0mC1);
1241 ComputeAreaChordRegion(E0, P1mC0, P0mC0) +
1242 ComputeAreaChordRegion(E1, P0mC1, P1mC1);
1246 template <
typename Real>
1247 void FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::Area4(
1248 EllipseInfo
const& E0, EllipseInfo
const& E1, AreaResult& ar)
1250 ar.configuration = AreaResult::FOUR_CHORD_REGION;
1258 std::multimap<Real, int> ordering;
1260 for (i = 0; i < 4; ++i)
1263 Real
x =
Dot(E0.axis[0], PmC);
1264 Real
y =
Dot(E0.axis[1], PmC);
1266 ordering.insert(std::make_pair(theta, i));
1269 std::array<int, 4> permute;
1271 for (
auto const& element : ordering)
1273 permute[i++] = element.second;
1278 ar.findResult.points[permute[2]] - ar.findResult.points[permute[0]];
1280 ar.findResult.points[permute[3]] - ar.findResult.points[permute[1]];
1286 for (
int i0 = 3, i1 = 0; i1 < 4; i0 = i1++)
1289 Vector2<Real> const& P0 = ar.findResult.points[permute[i0]];
1290 Vector2<Real> const& P1 = ar.findResult.points[permute[i1]];
1293 Vector2<Real> P0mC0 = P0 - E0.center, P0mC1 = P0 - E1.center;
1294 Vector2<Real> P1mC0 = P1 - E0.center, P1mC1 = P1 - E1.center;
1298 Real dotperp =
DotPerp(N1, N0);
1299 if (dotperp > mZero)
1302 ar.area += ComputeAreaChordRegion(E0, P0mC0, P1mC0);
1307 ar.area += ComputeAreaChordRegion(E1, P0mC1, P1mC1);
1312 template <
typename Real>
1313 Real FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::ComputeAreaChordRegion(
1318 Real
x0 =
Dot(E.axis[0], P0mC);
1319 Real
y0 =
Dot(E.axis[1], P0mC);
1321 Real
x1 =
Dot(E.axis[0], P1mC);
1322 Real
y1 =
Dot(E.axis[1], P1mC);
1327 if (theta1 < theta0)
1336 Real dtheta = theta1 - theta0;
1337 Real F0, F1, sectorArea;
1342 F0 = ComputeIntegral(E, theta0);
1343 F1 = ComputeIntegral(E, theta1);
1344 sectorArea = F1 - F0;
1345 return sectorArea - triArea;
1353 F0 = ComputeIntegral(E, theta0);
1354 F1 = ComputeIntegral(E, theta1);
1355 sectorArea = F0 - F1;
1356 return mPi * E.AB - (sectorArea - triArea);
1360 template <
typename Real>
1361 Real FIQuery<Real, Ellipse2<Real>, Ellipse2<Real>>::ComputeIntegral(
1362 EllipseInfo
const& E, Real
const& theta)
1364 Real twoTheta = mTwo * theta;
1367 Real arg = E.BmA * sn / (E.BpA + E.BmA * cs);
static Real Cos(Real const &x)
#define LogAssert(condition, message)
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
static Real Sqrt(Real const &x)
std::array< bool, 4 > isTransverse
GLubyte GLubyte GLubyte GLubyte w
GMatrix< Real > MultiplyATB(GMatrix< Real > const &A, GMatrix< Real > const &B)
static Real FAbs(Real const &x)
std::array< Vector2< Real >, 4 > points
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
Real DotPerp(Vector2< Real > const &v0, Vector2< Real > const &v1)
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
void SetCol(int c, Vector< NumRows, Real > const &vec)
Vector2< Real > sqrExtent
static Real Sin(Real const &x)
GLfloat GLfloat GLfloat GLfloat h
static Real ATan2(Real const &y, Real const &x)
static Real ATan(Real const &x)
GLuint GLfloat GLfloat GLfloat x1
GLuint GLfloat GLfloat y0
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
std::array< Vector2< Real >, 2 > axis
static unsigned int Find(std::function< Real(Real)> const &F, Real t0, Real t1, unsigned int maxIterations, Real &root)
GMatrix< Real > OuterProduct(GVector< Real > const &U, GVector< Real > const &V)
std::array< Vector< N, Real >, N > axis