From fd531b5101374f5e8980a782eafb5f21de3fda6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sun, 14 Apr 2013 21:19:35 +0200 Subject: [PATCH] Math: cleaned up plane/line intersection. The function now accepts starting point and direction of the line (not starting and ending point). Also improved the documentation and test a bit. --- src/Math/Geometry/Intersection.h | 32 +++++++++------------ src/Math/Geometry/Test/CMakeLists.txt | 2 +- src/Math/Geometry/Test/IntersectionTest.cpp | 8 +++--- src/Physics/Plane.cpp | 4 +-- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/Math/Geometry/Intersection.h b/src/Math/Geometry/Intersection.h index 9d3bff5c7..35100ed86 100644 --- a/src/Math/Geometry/Intersection.h +++ b/src/Math/Geometry/Intersection.h @@ -41,34 +41,30 @@ class Intersection { * @brief %Intersection of a plane and line * @param planePosition Plane position * @param planeNormal Plane normal - * @param a Starting point of the line - * @param b Ending point of the line - * @return %Intersection point position, NaN if the line lies on the - * plane or infinity if the intersection doesn't exist. %Intersection - * point can be computed from the position with `a+intersection(...)*b`. - * If returned value is in range @f$ [ 0 ; 1 ] @f$, the intersection - * is inside the line segment defined by `a` and `b`. + * @param p Starting point of the line + * @param r Direction of the line + * @return %Intersection point position `t` on the line, NaN if the + * line lies on the plane or infinity if the intersection doesn't + * exist. %Intersection point can be then computed from with + * `p + t*r`. If returned value is in range @f$ [ 0 ; 1 ] @f$, the + * intersection is inside the line segment defined by `p` and `r`. * * First the parameter *f* of parametric equation of the plane * is computed from plane normal **n** and plane position: @f[ * \begin{pmatrix} n_0 \\ n_1 \\ n_2 \end{pmatrix} \cdot * \begin{pmatrix} x \\ y \\ z \end{pmatrix} - f = 0 * @f] - * Using plane normal **n**, parameter *f* and points **a** and **b**, - * value of *t* is computed and returned. @f[ + * Using plane normal **n**, parameter *f* and line defined by **p** + * and **r**, value of *t* is computed and returned. @f[ * \begin{array}{rcl} - * \Delta \boldsymbol b & = & \boldsymbol b - \boldsymbol a \\ - * f & = & \boldsymbol n \cdot (\boldsymbol a + \Delta \boldsymbol b \cdot t) \\ - * \Rightarrow t & = & \cfrac{f - \boldsymbol n \cdot \boldsymbol a}{\boldsymbol n \cdot \Delta \boldsymbol b} + * f & = & \boldsymbol n \cdot (\boldsymbol p + t \boldsymbol r) \\ + * \Rightarrow t & = & \cfrac{f - \boldsymbol n \cdot \boldsymbol p}{\boldsymbol n \cdot \boldsymbol r} * \end{array} * @f] */ - template static T planeLine(const Vector3& planePosition, const Vector3& planeNormal, const Vector3& a, const Vector3& b) { - /* Compute f from normal and plane position */ - T f = Vector3::dot(planePosition, planeNormal); - - /* Compute t */ - return (f-Vector3::dot(planeNormal, a))/Vector3::dot(planeNormal, b-a); + template static T planeLine(const Vector3& planePosition, const Vector3& planeNormal, const Vector3& p, const Vector3& r) { + const T f = Vector3::dot(planePosition, planeNormal); + return (f-Vector3::dot(planeNormal, p))/Vector3::dot(planeNormal, r); } }; diff --git a/src/Math/Geometry/Test/CMakeLists.txt b/src/Math/Geometry/Test/CMakeLists.txt index e60e23aa3..21fcaedb2 100644 --- a/src/Math/Geometry/Test/CMakeLists.txt +++ b/src/Math/Geometry/Test/CMakeLists.txt @@ -23,5 +23,5 @@ # corrade_add_test(MathGeometryDistanceTest DistanceTest.cpp) -corrade_add_test(MathGeometryIntersectionTest IntersectionTest.cpp) +corrade_add_test(MathGeometryIntersectionTest IntersectionTest.cpp LIBRARIES MagnumMathTestLib) corrade_add_test(MathGeometryRectangleTest RectangleTest.cpp LIBRARIES MagnumMathTestLib) diff --git a/src/Math/Geometry/Test/IntersectionTest.cpp b/src/Math/Geometry/Test/IntersectionTest.cpp index c70f48747..0b30b760c 100644 --- a/src/Math/Geometry/Test/IntersectionTest.cpp +++ b/src/Math/Geometry/Test/IntersectionTest.cpp @@ -48,19 +48,19 @@ void IntersectionTest::planeLine() { /* Inside line segment */ CORRADE_COMPARE((Intersection::planeLine(planePosition, planeNormal, - Vector3(0.0f, 0.0f, -1.0f), Vector3(0.0f, 0.0f, 1.0f))), 0.75f); + Vector3(0.0f, 0.0f, -1.0f), Vector3(0.0f, 0.0f, 2.0f))), 0.75f); /* Outside line segment */ CORRADE_COMPARE((Intersection::planeLine(planePosition, planeNormal, - Vector3(0.0f, 0.0f, 1.0f), Vector3(0.0f, 0.0f, 2.0f))), -0.5f); + Vector3(0.0f, 0.0f, 1.0f), Vector3(0.0f, 0.0f, 1.0f))), -0.5f); /* Line lies on the plane */ CORRADE_COMPARE(Intersection::planeLine(planePosition, planeNormal, - Vector3(1.0f, 0.5f, 0.5f), Vector3(0.0f, 1.0f, 0.5f)), std::numeric_limits::quiet_NaN()); + Vector3(1.0f, 0.5f, 0.5f), Vector3(-1.0f, 0.5f, 0.0f)), std::numeric_limits::quiet_NaN()); /* Line is parallell to the plane */ CORRADE_COMPARE((Intersection::planeLine(planePosition, planeNormal, - Vector3(1.0f, 0.0f, 1.0f), Vector3(0.0f, 0.0f, 1.0f))), -std::numeric_limits::infinity()); + Vector3(1.0f, 0.0f, 1.0f), Vector3(-1.0f, 0.0f, 0.0f))), -std::numeric_limits::infinity()); } }}}} diff --git a/src/Physics/Plane.cpp b/src/Physics/Plane.cpp index 8c3ae2b50..047e22773 100644 --- a/src/Physics/Plane.cpp +++ b/src/Physics/Plane.cpp @@ -49,12 +49,12 @@ bool Plane::collides(const AbstractShape<3>* other) const { } bool Plane::operator%(const Line3D& other) const { - Float t = Intersection::planeLine(transformedPosition(), transformedNormal(), other.transformedA(), other.transformedB()); + Float t = Intersection::planeLine(transformedPosition(), transformedNormal(), other.transformedA(), other.transformedB()-other.transformedA()); return t != t || (t != std::numeric_limits::infinity() && t != -std::numeric_limits::infinity()); } bool Plane::operator%(const LineSegment3D& other) const { - Float t = Intersection::planeLine(transformedPosition(), transformedNormal(), other.transformedA(), other.transformedB()); + Float t = Intersection::planeLine(transformedPosition(), transformedNormal(), other.transformedA(), other.transformedB()-other.transformedA()); return t > 0.0f && t < 1.0f; }