// 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 #include // The 3D point-circle distance algorithm is described in // https://www.geometrictools.com/Documentation/DistanceToCircle3.pdf // The notation used in the code matches that of the document. namespace WwiseGTE { template class DCPQuery, Circle3> { public: // Either a single point on the circle is closest to 'point', in // which case 'equidistant' is false, or the entire circle is // closest to 'point', in which case 'equidistant' is true. In the // latter case, the query returns the circle point C+r*U, where C is // the circle center, r is the circle radius, and U is a vector // perpendicular to the normal N for the plane of the circle. struct Result { Real distance, sqrDistance; Vector3 circleClosest; bool equidistant; }; Result operator()(Vector3 const& point, Circle3 const& circle) { Result result; // Projection of P-C onto plane is Q-C = P-C - Dot(N,P-C)*N. Vector3 PmC = point - circle.center; Vector3 QmC = PmC - Dot(circle.normal, PmC) * circle.normal; Real lengthQmC = Length(QmC); if (lengthQmC > (Real)0) { result.circleClosest = circle.center + (circle.radius / lengthQmC) * QmC; result.equidistant = false; } else { // All circle points are equidistant from P. Return one of // them. Vector3 basis[3]; basis[0] = circle.normal; ComputeOrthogonalComplement(1, basis); result.circleClosest = circle.center + circle.radius * basis[1]; result.equidistant = true; } Vector3 diff = point - result.circleClosest; result.sqrDistance = Dot(diff, diff); result.distance = std::sqrt(result.sqrDistance); return result; } }; }