123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- // David Eberly, Geometric Tools, Redmond WA 98052
- // Copyright (c) 1998-2020
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
- // Version: 4.0.2019.08.13
- #pragma once
- #include <Mathematics/IntrCircle2Circle2.h>
- #include <Mathematics/Arc2.h>
- namespace WwiseGTE
- {
- template <typename Real>
- class FIQuery<Real, Arc2<Real>, Arc2<Real>>
- {
- public:
- // The possible 'configuration' in Result are listed as an
- // enumeration. The valid array elements are listed in the comments.
- enum
- {
- NO_INTERSECTION,
- NONCOCIRCULAR_ONE_POINT, // point[0]
- NONCOCIRCULAR_TWO_POINTS, // point[0], point[1]
- COCIRCULAR_ONE_POINT, // point[0]
- COCIRCULAR_TWO_POINTS, // point[0], point[1]
- COCIRCULAR_ONE_POINT_ONE_ARC, // point[0], arc[0]
- COCIRCULAR_ONE_ARC, // arc[0]
- COCIRCULAR_TWO_ARCS // arc[0], arc[1]
- };
- struct Result
- {
- // 'true' iff configuration != NO_INTERSECTION
- bool intersect;
- // one of the enumerations listed previously
- int configuration;
- Vector2<Real> point[2];
- Arc2<Real> arc[2];
- };
- Result operator()(Arc2<Real> const& arc0, Arc2<Real> const& arc1)
- {
- // Assume initially there are no intersections. If we find at
- // least one intersection, we will set result.intersect to 'true'.
- Result result;
- result.intersect = false;
- result.configuration = NO_INTERSECTION;
- result.point[0] = { (Real)0, (Real)0 };
- result.point[1] = { (Real)0, (Real)0 };
- Circle2<Real> circle0(arc0.center, arc0.radius);
- Circle2<Real> circle1(arc1.center, arc1.radius);
- FIQuery<Real, Circle2<Real>, Circle2<Real>> ccQuery;
- auto ccResult = ccQuery(circle0, circle1);
- if (!ccResult.intersect)
- {
- // The arcs do not intersect.
- result.configuration = NO_INTERSECTION;
- return result;
- }
- if (ccResult.numIntersections == std::numeric_limits<int>::max())
- {
- // The arcs are cocircular. Determine whether they overlap.
- // Let arc0 be <A0,A1> and arc1 be <B0,B1>. The points are
- // ordered counterclockwise around the circle of the arc.
- if (arc1.Contains(arc0.end[0]))
- {
- result.intersect = true;
- if (arc1.Contains(arc0.end[1]))
- {
- if (arc0.Contains(arc1.end[0]) && arc0.Contains(arc1.end[1]))
- {
- if (arc0.end[0] == arc1.end[0] && arc0.end[1] == arc1.end[1])
- {
- // The arcs are the same.
- result.configuration = COCIRCULAR_ONE_ARC;
- result.arc[0] = arc0;
- }
- else
- {
- // arc0 and arc1 overlap in two disjoint
- // subsets.
- if (arc0.end[0] != arc1.end[1])
- {
- if (arc1.end[0] != arc0.end[1])
- {
- // The arcs overlap in two disjoint
- // subarcs, each of positive subtended
- // angle: <A0,B1>, <A1,B0>
- result.configuration = COCIRCULAR_TWO_ARCS;
- result.arc[0] = Arc2<Real>(arc0.center, arc0.radius, arc0.end[0], arc1.end[1]);
- result.arc[1] = Arc2<Real>(arc0.center, arc0.radius, arc1.end[0], arc0.end[1]);
- }
- else // B0 = A1
- {
- // The intersection is a point {A1}
- // and an arc <A0,B1>.
- result.configuration = COCIRCULAR_ONE_POINT_ONE_ARC;
- result.point[0] = arc0.end[1];
- result.arc[0] = Arc2<Real>(arc0.center, arc0.radius, arc0.end[0], arc1.end[1]);
- }
- }
- else // A0 = B1
- {
- if (arc1.end[0] != arc0.end[1])
- {
- // The intersection is a point {A0}
- // and an arc <A1,B0>.
- result.configuration = COCIRCULAR_ONE_POINT_ONE_ARC;
- result.point[0] = arc0.end[0];
- result.arc[0] = Arc2<Real>(arc0.center, arc0.radius, arc1.end[0], arc0.end[1]);
- }
- else
- {
- // The arcs shared endpoints, so the
- // union is a circle.
- result.configuration = COCIRCULAR_TWO_POINTS;
- result.point[0] = arc0.end[0];
- result.point[1] = arc0.end[1];
- }
- }
- }
- }
- else
- {
- // Arc0 inside arc1, <B0,A0,A1,B1>.
- result.configuration = COCIRCULAR_ONE_ARC;
- result.arc[0] = arc0;
- }
- }
- else
- {
- if (arc0.end[0] != arc1.end[1])
- {
- // Arc0 and arc1 overlap, <B0,A0,B1,A1>.
- result.configuration = COCIRCULAR_ONE_ARC;
- result.arc[0] = Arc2<Real>(arc0.center, arc0.radius, arc0.end[0], arc1.end[1]);
- }
- else
- {
- // Arc0 and arc1 share endpoint, <B0,A0,B1,A1>
- // with A0 = B1.
- result.configuration = COCIRCULAR_ONE_POINT;
- result.point[0] = arc0.end[0];
- }
- }
- return result;
- }
- if (arc1.Contains(arc0.end[1]))
- {
- result.intersect = true;
- if (arc0.end[1] != arc1.end[0])
- {
- // Arc0 and arc1 overlap in a single arc,
- // <A0,B0,A1,B1>.
- result.configuration = COCIRCULAR_ONE_ARC;
- result.arc[0] = Arc2<Real>(arc0.center, arc0.radius, arc1.end[0], arc0.end[1]);
- }
- else
- {
- // Arc0 and arc1 share endpoint, <A0,B0,A1,B1>
- // with B0 = A1.
- result.configuration = COCIRCULAR_ONE_POINT;
- result.point[0] = arc1.end[0];
- }
- return result;
- }
- if (arc0.Contains(arc1.end[0]))
- {
- // Arc1 inside arc0, <A0,B0,B1,A1>.
- result.intersect = true;
- result.configuration = COCIRCULAR_ONE_ARC;
- result.arc[0] = arc1;
- }
- else
- {
- // Arcs do not overlap, <A0,A1,B0,B1>.
- result.configuration = NO_INTERSECTION;
- }
- return result;
- }
- // Test whether circle-circle intersection points are on the arcs.
- int numIntersections = 0;
- for (int i = 0; i < ccResult.numIntersections; ++i)
- {
- if (arc0.Contains(ccResult.point[i]) && arc1.Contains(ccResult.point[i]))
- {
- result.point[numIntersections++] = ccResult.point[i];
- result.intersect = true;
- }
- }
- if (numIntersections == 2)
- {
- result.configuration = NONCOCIRCULAR_TWO_POINTS;
- }
- else if (numIntersections == 1)
- {
- result.configuration = NONCOCIRCULAR_ONE_POINT;
- }
- else
- {
- result.configuration = NO_INTERSECTION;
- }
- return result;
- }
- };
- }
|