You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

217 lines
9.1 KiB

// David Eberly, Geometric Tools, Redmond WA 98052
// Copyright (c) 1998-2021
// 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 gte
{
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;
}
};
}