// 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 #include namespace WwiseGTE { template class TIQuery, Segment2> { public: struct Result { bool intersect; // The number is 0 (no intersection), 1 (segments intersect in a // single point), or 2 (segments are collinear and intersect in a // segment). int numIntersections; }; Result operator()(Segment2 const& segment0, Segment2 const& segment1) { Result result; Vector2 seg0Origin, seg0Direction, seg1Origin, seg1Direction; Real seg0Extent, seg1Extent; segment0.GetCenteredForm(seg0Origin, seg0Direction, seg0Extent); segment1.GetCenteredForm(seg1Origin, seg1Direction, seg1Extent); FIQuery, Line2> llQuery; Line2 line0(seg0Origin, seg0Direction); Line2 line1(seg1Origin, seg1Direction); auto llResult = llQuery(line0, line1); if (llResult.numIntersections == 1) { // Test whether the line-line intersection is on the segments. if (std::fabs(llResult.line0Parameter[0]) <= seg0Extent && std::fabs(llResult.line1Parameter[0]) <= seg1Extent) { result.intersect = true; result.numIntersections = 1; } else { result.intersect = false; result.numIntersections = 0; } } else if (llResult.numIntersections == std::numeric_limits::max()) { // Compute the location of segment1 endpoints relative to // segment0. Vector2 diff = seg1Origin - seg0Origin; Real t = Dot(seg0Direction, diff); // Get the parameter intervals of the segments relative to // segment0. std::array interval0 = { -seg0Extent, seg0Extent }; std::array interval1 = { t - seg1Extent, t + seg1Extent }; // Compute the intersection of the intervals. FIQuery, std::array> iiQuery; auto iiResult = iiQuery(interval0, interval1); result.intersect = iiResult.intersect; result.numIntersections = iiResult.numIntersections; } else { result.intersect = false; result.numIntersections = 0; } return result; } }; template class FIQuery, Segment2> { public: struct Result { bool intersect; // The number is 0 (no intersection), 1 (segments intersect in a // a single point), or 2 (segments are collinear and intersect // in a segment). int numIntersections; // If numIntersections is 1, the intersection is // point[0] // = segment0.origin + segment0Parameter[0] * segment0.direction // = segment1.origin + segment1Parameter[0] * segment1.direction // If numIntersections is 2, the endpoints of the segment of // intersection are // point[i] // = segment0.origin + segment0Parameter[i] * segment0.direction // = segment1.origin + segment1Parameter[i] * segment1.direction // with segment0Parameter[0] <= segment0Parameter[1] and // segment1Parameter[0] <= segment1Parameter[1]. Real segment0Parameter[2], segment1Parameter[2]; Vector2 point[2]; }; Result operator()(Segment2 const& segment0, Segment2 const& segment1) { Result result; Vector2 seg0Origin, seg0Direction, seg1Origin, seg1Direction; Real seg0Extent, seg1Extent; segment0.GetCenteredForm(seg0Origin, seg0Direction, seg0Extent); segment1.GetCenteredForm(seg1Origin, seg1Direction, seg1Extent); FIQuery, Line2> llQuery; Line2 line0(seg0Origin, seg0Direction); Line2 line1(seg1Origin, seg1Direction); auto llResult = llQuery(line0, line1); if (llResult.numIntersections == 1) { // Test whether the line-line intersection is on the segments. if (std::fabs(llResult.line0Parameter[0]) <= seg0Extent && std::fabs(llResult.line1Parameter[0]) <= seg1Extent) { result.intersect = true; result.numIntersections = 1; result.segment0Parameter[0] = llResult.line0Parameter[0]; result.segment1Parameter[0] = llResult.line1Parameter[0]; result.point[0] = llResult.point; } else { result.intersect = false; result.numIntersections = 0; } } else if (llResult.numIntersections == std::numeric_limits::max()) { // Compute the location of segment1 endpoints relative to // segment0. Vector2 diff = seg1Origin - seg0Origin; Real t = Dot(seg0Direction, diff); // Get the parameter intervals of the segments relative to // segment0. std::array interval0 = { -seg0Extent, seg0Extent }; std::array interval1 = { t - seg1Extent, t + seg1Extent }; // Compute the intersection of the intervals. FIQuery, std::array> iiQuery; auto iiResult = iiQuery(interval0, interval1); if (iiResult.intersect) { result.intersect = true; result.numIntersections = iiResult.numIntersections; for (int i = 0; i < iiResult.numIntersections; ++i) { result.segment0Parameter[i] = iiResult.overlap[i]; result.segment1Parameter[i] = iiResult.overlap[i] - t; result.point[i] = seg0Origin + result.segment0Parameter[i] * seg0Direction; } } else { result.intersect = false; result.numIntersections = 0; } } else { result.intersect = false; result.numIntersections = 0; } return result; } }; }