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.
138 lines
4.5 KiB
138 lines
4.5 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/FIQuery.h>
|
|
#include <Mathematics/TIQuery.h>
|
|
#include <Mathematics/Hypersphere.h>
|
|
#include <Mathematics/Circle3.h>
|
|
|
|
// The queries consider the spheres to be solids.
|
|
|
|
namespace gte
|
|
{
|
|
template <typename Real>
|
|
class TIQuery<Real, Sphere3<Real>, Sphere3<Real>>
|
|
{
|
|
public:
|
|
struct Result
|
|
{
|
|
bool intersect;
|
|
};
|
|
|
|
Result operator()(Sphere3<Real> const& sphere0, Sphere3<Real> const& sphere1)
|
|
{
|
|
Result result;
|
|
Vector3<Real> diff = sphere1.center - sphere0.center;
|
|
Real rSum = sphere0.radius + sphere1.radius;
|
|
result.intersect = (Dot(diff, diff) <= rSum * rSum);
|
|
return result;
|
|
}
|
|
};
|
|
|
|
template <typename Real>
|
|
class FIQuery<Real, Sphere3<Real>, Sphere3<Real>>
|
|
{
|
|
public:
|
|
struct Result
|
|
{
|
|
bool intersect;
|
|
|
|
// The type of intersection.
|
|
// 0: spheres are disjoint and separated
|
|
// 1: spheres touch at point, each sphere outside the other
|
|
// 2: spheres intersect in a circle
|
|
// 3: sphere0 strictly contained in sphere1
|
|
// 4: sphere0 contained in sphere1, share common point
|
|
// 5: sphere1 strictly contained in sphere0
|
|
// 6: sphere1 contained in sphere0, share common point
|
|
int type;
|
|
Vector3<Real> point; // types 1, 4, 6
|
|
Circle3<Real> circle; // type 2
|
|
};
|
|
|
|
Result operator()(Sphere3<Real> const& sphere0, Sphere3<Real> const& sphere1)
|
|
{
|
|
Result result;
|
|
|
|
// The plane of intersection must have C1-C0 as its normal
|
|
// direction.
|
|
Vector3<Real> C1mC0 = sphere1.center - sphere0.center;
|
|
Real sqrLen = Dot(C1mC0, C1mC0);
|
|
Real r0 = sphere0.radius, r1 = sphere1.radius;
|
|
Real rSum = r0 + r1;
|
|
Real rSumSqr = rSum * rSum;
|
|
|
|
if (sqrLen > rSumSqr)
|
|
{
|
|
// The spheres are disjoint/separated.
|
|
result.intersect = false;
|
|
result.type = 0;
|
|
return result;
|
|
}
|
|
|
|
if (sqrLen == rSumSqr)
|
|
{
|
|
// The spheres are just touching with each sphere outside the
|
|
// other.
|
|
Normalize(C1mC0);
|
|
result.intersect = true;
|
|
result.type = 1;
|
|
result.point = sphere0.center + r0 * C1mC0;
|
|
return result;
|
|
}
|
|
|
|
Real rDif = r0 - r1;
|
|
Real rDifSqr = rDif * rDif;
|
|
if (sqrLen < rDifSqr)
|
|
{
|
|
// One sphere is strictly contained in the other. Compute a
|
|
// point in the intersection set.
|
|
result.intersect = true;
|
|
result.type = (rDif <= (Real)0 ? 3 : 5);
|
|
result.point = ((Real)0.5) * (sphere0.center + sphere1.center);
|
|
return result;
|
|
}
|
|
if (sqrLen == rDifSqr)
|
|
{
|
|
// One sphere is contained in the other sphere but with a
|
|
// single point of contact.
|
|
Normalize(C1mC0);
|
|
result.intersect = true;
|
|
if (rDif <= (Real)0)
|
|
{
|
|
result.type = 4;
|
|
result.point = sphere1.center + r1 * C1mC0;
|
|
}
|
|
else
|
|
{
|
|
result.type = 6;
|
|
result.point = sphere0.center + r0 * C1mC0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Compute t for which the circle of intersection has center
|
|
// K = C0 + t*(C1 - C0).
|
|
Real t = ((Real)0.5) * ((Real)1 + rDif * rSum / sqrLen);
|
|
|
|
// Compute the center and radius of the circle of intersection.
|
|
result.circle.center = sphere0.center + t * C1mC0;
|
|
result.circle.radius = std::sqrt(std::max(r0 * r0 - t * t * sqrLen, (Real)0));
|
|
|
|
// Compute the normal for the plane of the circle.
|
|
Normalize(C1mC0);
|
|
result.circle.normal = C1mC0;
|
|
|
|
// The intersection is a circle.
|
|
result.intersect = true;
|
|
result.type = 2;
|
|
return result;
|
|
}
|
|
};
|
|
}
|
|
|