From 7f89105a51b2974a6a0bbb474f73cb86ff04bfb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 12 Dec 2016 21:29:49 +0100 Subject: [PATCH] Math: converted Geometry::Distance and Intersection to namespaces. No need for them to be classes, less indentation, less keywords and boilerplate, more space for documentation, better `using` usage. Also revised and fixed various issues in the documentation. --- doc/namespaces.dox | 16 +- src/Magnum/Math/Geometry/Distance.h | 376 ++++++++++++------------ src/Magnum/Math/Geometry/Intersection.h | 241 +++++++-------- 3 files changed, 319 insertions(+), 314 deletions(-) diff --git a/doc/namespaces.dox b/doc/namespaces.dox index 0964b018d..a093e8c6b 100644 --- a/doc/namespaces.dox +++ b/doc/namespaces.dox @@ -94,7 +94,21 @@ and @ref cmake for more information. /** @namespace Magnum::Math::Geometry @brief Geometry library -Functions for computing intersections, distances, areas and volumes. +This library is built as part of Magnum by default. To use it, you need to +find `Magnum` package and link to `Magnum::Magnum` target. See @ref building +and @ref cmake for more information. +*/ + +/** @namespace Magnum::Math::Geometry::Distance +@brief Functions for calculating distances + +This library is built as part of Magnum by default. To use it, you need to +find `Magnum` package and link to `Magnum::Magnum` target. See @ref building +and @ref cmake for more information. +*/ + +/** @namespace Magnum::Math::Geometry::Intersection +@brief Function for calculating intersections This library is built as part of Magnum by default. To use it, you need to find `Magnum` package and link to `Magnum::Magnum` target. See @ref building diff --git a/src/Magnum/Math/Geometry/Distance.h b/src/Magnum/Math/Geometry/Distance.h index cacf5f836..3fc18df52 100644 --- a/src/Magnum/Math/Geometry/Distance.h +++ b/src/Magnum/Math/Geometry/Distance.h @@ -27,202 +27,192 @@ */ /** @file - * @brief Class @ref Magnum::Math::Geometry::Distance + * @brief Namespace @ref Magnum::Math::Geometry::Distance */ #include "Magnum/Math/Functions.h" #include "Magnum/Math/Vector3.h" #include "Magnum/Math/Vector4.h" -namespace Magnum { namespace Math { namespace Geometry { - -/** @brief Functions for computing distances */ -class Distance { - public: - Distance() = delete; - - /** - * @brief Distance of line and point in 2D - * @param a First point of the line - * @param b Second point of the line - * @param point Point - * - * The distance *d* is computed from point **p** and line defined by **a** - * and **b** using @ref cross(const Vector2&, const Vector2&) "perp-dot product": @f[ - * d = \frac{|(\boldsymbol b - \boldsymbol a)_\bot \cdot (\boldsymbol a - \boldsymbol p)|} {|\boldsymbol b - \boldsymbol a|} - * @f] - * Source: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html - * @see @ref linePointSquared(const Vector2&, const Vector2&, const Vector2&) - */ - template static T linePoint(const Vector2& a, const Vector2& b, const Vector2& point) { - const Vector2 bMinusA = b - a; - return std::abs(cross(bMinusA, a - point))/bMinusA.length(); - } - - /** - * @brief Distance of line and point in 2D, squared - * @param a First point of the line - * @param b Second point of the line - * @param point Point - * - * More efficient than - * @ref linePoint(const Vector2&, const Vector2&, const Vector2&) - * for comparing distance with other values, because it doesn't - * compute the square root. - */ - template static T linePointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { - const Vector2 bMinusA = b - a; - return Math::pow<2>(cross(bMinusA, a - point))/bMinusA.dot(); - } - - /** - * @brief Distance of line and point in 3D - * @param a First point of the line - * @param b Second point of the line - * @param point Point - * - * The distance *d* is computed from point **p** and line defined by **a** - * and **b** using @ref cross(const Vector3&, const Vector3&) "cross product": @f[ - * d = \frac{|(\boldsymbol p - \boldsymbol a) \times (\boldsymbol p - \boldsymbol b)|} - * {|\boldsymbol b - \boldsymbol a|} - * @f] - * Source: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html - * @see @ref linePointSquared(const Vector3&, const Vector3&, const Vector3&) - */ - template static T linePoint(const Vector3& a, const Vector3& b, const Vector3& point) { - return std::sqrt(linePointSquared(a, b, point)); - } - - /** - * @brief Distance of line and point in 3D, squared - * - * More efficient than @ref linePoint(const Vector3&, const Vector3&, const Vector3&) - * for comparing distance with other values, because it doesn't - * compute the square root. - */ - template static T linePointSquared(const Vector3& a, const Vector3& b, const Vector3& point) { - return cross(point - a, point - b).dot()/(b - a).dot(); - } - - /** - * @brief Dístance of point from line segment in 2D - * @param a Starting point of the line - * @param b Ending point of the line - * @param point Point - * - * Returns distance of point from line segment or from its - * starting/ending point, depending on where the point lies. - * - * Determining whether the point lies next to line segment or outside - * is done using Pythagorean theorem. If the following equation - * applies, the point **p** lies outside line segment closer to **a**: @f[ - * |\boldsymbol p - \boldsymbol b|^2 > |\boldsymbol b - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol a|^2 - * @f] - * On the other hand, if the following equation applies, the point - * lies outside line segment closer to **b**: @f[ - * |\boldsymbol p - \boldsymbol a|^2 > |\boldsymbol b - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol b|^2 - * @f] - * The last alternative is when the following equation applies. The - * point then lies between **a** and **b** and the distance is - * computed the same way as in @ref linePoint(). @f[ - * |\boldsymbol b - \boldsymbol a|^2 > |\boldsymbol p - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol b|^2 - * @f] - * - * @see @ref lineSegmentPointSquared() - */ - template static T lineSegmentPoint(const Vector2& a, const Vector2& b, const Vector2& point); - - /** - * @brief Distance of point from line segment in 2D, squared - * - * More efficient than @ref lineSegmentPoint() for comparing distance - * with other values, because it doesn't compute the square root. - */ - template static T lineSegmentPointSquared(const Vector2& a, const Vector2& b, const Vector2& point); - - /** - * @brief Dístance of point from line segment in 3D - * @param a Starting point of the line - * @param b Ending point of the line - * @param point Point - * - * Similar to 2D implementation - * @ref lineSegmentPoint(const Vector2&, const Vector2&, const Vector2&). - * - * @see @ref lineSegmentPointSquared(const Vector3&, const Vector3&, const Vector3&) - */ - template static T lineSegmentPoint(const Vector3& a, const Vector3& b, const Vector3& point) { - return std::sqrt(lineSegmentPointSquared(a, b, point)); - } - - /** - * @brief Distance of point from line segment in 3D, squared - * - * More efficient than - * @ref lineSegmentPoint(const Vector3&, const Vector3&, const Vector3&) - * for comparing distance with other values, because it doesn't compute - * the square root. - */ - template static T lineSegmentPointSquared(const Vector3& a, const Vector3& b, const Vector3& point); - - /** - * @brief Distance of point from plane - * - * The distance **d** is computed from point **p** and plane with - * normal **n** and **w** using: @f[ - * d = \frac{p \cdot n + w}{\left| n \right|} - * @f] - * The distance is negative if the point lies behind the plane. - * - * In cases where the planes normal is a unit vector, - * @ref pointPlaneUnnormalized() is more efficient. If merely the sign - * of the distance is of interest, @ref pointPlaneScaled() is more - * efficient. - */ - template static T pointPlane(const Vector3& point, const Vector4& plane) { - return pointPlaneScaled(point, plane)/plane.xyz().length(); - } - - /** - * @brief Distance of point from plane, scaled by the length of the planes normal - * - * The distance **d** is computed from point **p** and plane with - * normal **n** and **w** using: @f[ - * d = p \cdot n + w - * @f] - * The distance is negative if the point lies behind the plane. - * - * More efficient than @ref pointPlane() when merely the sign of the - * distance is of interest, for example when testing on which half - * space of the plane the point lies. - * @see @ref pointPlaneNormalized() - */ - template static T pointPlaneScaled(const Vector3& point, const Vector4& plane) { - return Math::dot(plane.xyz(), point) + plane.w(); - } - - /** - * @brief Distance of point from plane with normalized normal - * - * The distance **d** is computed from point **p** and plane with - * normal **n** and **w** using: @f[ - * d = p \cdot n + w - * @f] - * The distance is negative if the point lies behind the plane. Expects - * that @p plane normal is normalized. - * - * More efficient than @ref pointPlane() in cases where the planes - * normal is normalized. Equivalent to @ref pointPlaneScaled() but with - * assertion added on top. - */ - template static T pointPlaneNormalized(const Vector3& point, const Vector4& plane) { - CORRADE_ASSERT(plane.xyz().isNormalized(), - "Math::Geometry::Distance::pointPlaneNormalized(): plane normal is not an unit vector", {}); - return pointPlaneScaled(point, plane); - } -}; - -template T Distance::lineSegmentPoint(const Vector2& a, const Vector2& b, const Vector2& point) { +namespace Magnum { namespace Math { namespace Geometry { namespace Distance { + +/** +@brief Distance of line and point in 2D, squared +@param a First point of the line +@param b Second point of the line +@param point Point + +More efficient than @ref linePoint(const Vector2&, const Vector2&, const Vector2&) +for comparing distance with other values, because it doesn't calculate the +square root. +*/ +template inline T linePointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { + const Vector2 bMinusA = b - a; + return Math::pow<2>(cross(bMinusA, a - point))/bMinusA.dot(); +} + +/** +@brief Distance of line and point in 2D +@param a First point of the line +@param b Second point of the line +@param point Point + +The distance @f$ d @f$ is calculated from point @f$ \boldsymbol{p} @f$ and line +defined by @f$ \boldsymbol{a} @f$ and @f$ \boldsymbol{b} @f$ using +@ref cross(const Vector2&, const Vector2&) "perp-dot product": @f[ + d = \frac{|(\boldsymbol b - \boldsymbol a)_\bot \cdot (\boldsymbol a - \boldsymbol p)|}{|\boldsymbol b - \boldsymbol a|} +@f] +Source: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html +@see @ref linePointSquared(const Vector2&, const Vector2&, const Vector2&) +*/ +template inline T linePoint(const Vector2& a, const Vector2& b, const Vector2& point) { + const Vector2 bMinusA = b - a; + return std::abs(cross(bMinusA, a - point))/bMinusA.length(); +} + +/** +@brief Distance of line and point in 3D, squared + +More efficient than @ref linePoint(const Vector3&, const Vector3&, const Vector3&) +for comparing distance with other values, because it doesn't calculate the +square root. +*/ +template inline T linePointSquared(const Vector3& a, const Vector3& b, const Vector3& point) { + return cross(point - a, point - b).dot()/(b - a).dot(); +} + +/** +@brief Distance of line and point in 3D +@param a First point of the line +@param b Second point of the line +@param point Point + +The distance @f$ d @f$ is calculated from point @f$ \boldsymbol{p} @f$ and line +defined by @f$ \boldsymbol{a} @f$ and @f$ \boldsymbol{b} @f$ using +@ref cross(const Vector3&, const Vector3&) "cross product": @f[ + d = \frac{|(\boldsymbol p - \boldsymbol a) \times (\boldsymbol p - \boldsymbol b)|}{|\boldsymbol b - \boldsymbol a|} +@f] +Source: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html +@see @ref linePointSquared(const Vector3&, const Vector3&, const Vector3&) +*/ +template inline T linePoint(const Vector3& a, const Vector3& b, const Vector3& point) { + return std::sqrt(linePointSquared(a, b, point)); +} + +/** +@brief Distance of point from line segment in 2D, squared + +More efficient than @ref lineSegmentPoint() for comparing distance with other +values, because it doesn't calculate the square root. +*/ +template T lineSegmentPointSquared(const Vector2& a, const Vector2& b, const Vector2& point); + +/** +@brief Dístance of point from line segment in 2D +@param a Starting point of the line +@param b Ending point of the line +@param point Point + +Returns distance of point from line segment or from its starting/ending point, +depending on where the point lies. + +Determining whether the point lies next to line segment or outside is done +using Pythagorean theorem. If the following equation applies, the point +@f$ \boldsymbol{p} @f$ lies outside line segment closer to @f$ \boldsymbol{a} @f$: @f[ + |\boldsymbol p - \boldsymbol b|^2 > |\boldsymbol b - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol a|^2 +@f] +On the other hand, if the following equation applies, the point lies outside +line segment closer to @f$ \boldsymbol{b} @f$: @f[ + |\boldsymbol p - \boldsymbol a|^2 > |\boldsymbol b - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol b|^2 +@f] +The last alternative is when the following equation applies. The point then +lies between @f$ \boldsymbol{a} @f$ and @f$ \boldsymbol{b} @f$ and the distance +is calculated the same way as in @ref linePoint(). @f[ + |\boldsymbol b - \boldsymbol a|^2 > |\boldsymbol p - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol b|^2 +@f] + +@see @ref lineSegmentPointSquared() +*/ +template T lineSegmentPoint(const Vector2& a, const Vector2& b, const Vector2& point); + +/** +@brief Distance of point from line segment in 3D, squared + +More efficient than @ref lineSegmentPoint(const Vector3&, const Vector3&, const Vector3&) +for comparing distance with other values, because it doesn't calculate the +square root. +*/ +template T lineSegmentPointSquared(const Vector3& a, const Vector3& b, const Vector3& point); + +/** +@brief Dístance of point from line segment in 3D +@param a Starting point of the line +@param b Ending point of the line +@param point Point + +Similar to 2D implementation @ref lineSegmentPoint(const Vector2&, const Vector2&, const Vector2&). +@see @ref lineSegmentPointSquared(const Vector3&, const Vector3&, const Vector3&) +*/ +template inline T lineSegmentPoint(const Vector3& a, const Vector3& b, const Vector3& point) { + return std::sqrt(lineSegmentPointSquared(a, b, point)); +} + +/** +@brief Distance of point from plane, scaled by the length of the planes normal + +The distance @f$ d @f$ is calculated from point @f$ \boldsymbol{p} @f$ and +plane with normal @f$ \boldsymbol{n} @f$ and @f$ w @f$ using: @f[ + d = \boldsymbol{p} \cdot \boldsymbol{n} + w +@f] +The distance is negative if the point lies behind the plane. + +More efficient than @ref pointPlane() when merely the sign of the distance is +of interest, for example when testing on which half space of the plane the +point lies. +@see @ref pointPlaneNormalized() + */ +template inline T pointPlaneScaled(const Vector3& point, const Vector4& plane) { + return dot(plane.xyz(), point) + plane.w(); +} + +/** +@brief Distance of point from plane + +The distance @f$ d @f$ is calculated from point @f$ \boldsymbol{p} @f$ and +plane with normal @f$ \boldsymbol{n} @f$ and @f$ w @f$ using: @f[ + d = \frac{\boldsymbol{p} \cdot \boldsymbol{n} + w}{\left| \boldsymbol{n} \right|} +@f] +The distance is negative if the point lies behind the plane. + +In cases where the planes normal is a unit vector, @ref pointPlaneNormalized() +is more efficient. If merely the sign of the distance is of interest, +@ref pointPlaneScaled() is more efficient. +*/ +template inline T pointPlane(const Vector3& point, const Vector4& plane) { + return pointPlaneScaled(point, plane)/plane.xyz().length(); +} + +/** +@brief Distance of point from plane with normalized normal + +The distance @f$ d @f$ is calculated from point @f$ \boldsymbol{p} @f$ and plane +with normal @f$ \boldsymbol{n} @f$ and @f$ w @f$ using: @f[ + d = \boldsymbol{p} \cdot \boldsymbol{n} + w +@f] +The distance is negative if the point lies behind the plane. Expects that +@p plane normal is normalized. + +More efficient than @ref pointPlane() in cases where the plane's normal is +normalized. Equivalent to @ref pointPlaneScaled() but with assertion added on +top. +*/ +template inline T pointPlaneNormalized(const Vector3& point, const Vector4& plane) { + CORRADE_ASSERT(plane.xyz().isNormalized(), + "Math::Geometry::Distance::pointPlaneNormalized(): plane normal is not an unit vector", {}); + return pointPlaneScaled(point, plane); +} + +template T lineSegmentPoint(const Vector2& a, const Vector2& b, const Vector2& point) { const Vector2 pointMinusA = point - a; const Vector2 pointMinusB = point - b; const Vector2 bMinusA = b - a; @@ -242,7 +232,7 @@ template T Distance::lineSegmentPoint(const Vector2& a, const Vector return std::abs(cross(bMinusA, -pointMinusA))/std::sqrt(bDistanceA); } -template T Distance::lineSegmentPointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { +template T lineSegmentPointSquared(const Vector2& a, const Vector2& b, const Vector2& point) { const Vector2 pointMinusA = point - a; const Vector2 pointMinusB = point - b; const Vector2 bMinusA = b - a; @@ -262,7 +252,7 @@ template T Distance::lineSegmentPointSquared(const Vector2& a, const return Math::pow<2>(cross(bMinusA, -pointMinusA))/bDistanceA; } -template T Distance::lineSegmentPointSquared(const Vector3& a, const Vector3& b, const Vector3& point) { +template T lineSegmentPointSquared(const Vector3& a, const Vector3& b, const Vector3& point) { const Vector3 pointMinusA = point - a; const Vector3 pointMinusB = point - b; const T pointDistanceA = pointMinusA.dot(); @@ -281,6 +271,6 @@ template T Distance::lineSegmentPointSquared(const Vector3& a, const return cross(pointMinusA, pointMinusB).dot()/bDistanceA; } -}}} +}}}} #endif diff --git a/src/Magnum/Math/Geometry/Intersection.h b/src/Magnum/Math/Geometry/Intersection.h index 8d846d3e9..113d9582e 100644 --- a/src/Magnum/Math/Geometry/Intersection.h +++ b/src/Magnum/Math/Geometry/Intersection.h @@ -27,7 +27,7 @@ */ /** @file - * @brief Class @ref Magnum::Math::Geometry::Intersection + * @brief Namespace @ref Magnum::Math::Geometry::Intersection */ #include "Magnum/Math/Frustum.h" @@ -35,126 +35,127 @@ #include "Magnum/Math/Range.h" #include "Magnum/Math/Vector3.h" -namespace Magnum { namespace Math { namespace Geometry { - -/** @brief Functions for computing intersections */ -class Intersection { - public: - Intersection() = delete; - - /** - * @brief Intersection of two line segments in 2D - * @param p Starting point of first line segment - * @param r Direction of first line segment - * @param q Starting point of second line segment - * @param s Direction of second line segment - * @return Intersection point positions `t`, `u` on both lines, NaN if - * the lines are collinear or infinity if they are parallel. - * Intersection point can be then computed with `p + t*r` or - * `q + u*s`. If `t` is in range @f$ [ 0 ; 1 ] @f$, the - * intersection is inside the line segment defined by `p` and - * `p + r`, if `u` is in range @f$ [ 0 ; 1 ] @f$, the intersection - * is inside the line segment defined by `q` and `q + s`. - * - * The two lines intersect if **t** and **u** exist such that: @f[ - * \boldsymbol p + t \boldsymbol r = \boldsymbol q + u \boldsymbol s - * @f] - * Crossing both sides with **s**, distributing the cross product and - * eliminating @f$ \boldsymbol s \times \boldsymbol s = 0 @f$, then - * solving for **t** and similarly for **u**: @f[ - * \begin{array}{rcl} - * (\boldsymbol p + t \boldsymbol r) \times s & = & (\boldsymbol q + u \boldsymbol s) \times s \\ - * t (\boldsymbol r \times s) & = & (\boldsymbol q - \boldsymbol p) \times s \\ - * t & = & \cfrac{(\boldsymbol q - \boldsymbol p) \times s}{\boldsymbol r \times \boldsymbol s} \\ - * u & = & \cfrac{(\boldsymbol q - \boldsymbol p) \times r}{\boldsymbol r \times \boldsymbol s} - * \end{array} - * @f] - * - * See also @ref lineSegmentLine() which computes only **t**, which is - * useful if you don't need to test that the intersection lies inside - * line segment defined by `q` and `q + s`. - */ - template static std::pair lineSegmentLineSegment(const Vector2& p, const Vector2& r, const Vector2& q, const Vector2& s) { - const Vector2 qp = q - p; - const T rs = cross(r, s); - return {cross(qp, s)/rs, cross(qp, r)/rs}; - } +namespace Magnum { namespace Math { namespace Geometry { namespace Intersection { + +/** +@brief Intersection of two line segments in 2D +@param p Starting point of first line segment +@param r Direction of first line segment +@param q Starting point of second line segment +@param s Direction of second line segment + +Returns intersection point positions @f$ t @f$, @f$ u @f$ on both lines, NaN if +the lines are collinear or infinity if they are parallel. Intersection point +can be then calculated with @f$ \boldsymbol{p} + t \boldsymbol{r} @f$ or +@f$ \boldsymbol{q} + u \boldsymbol{s} @f$. If @f$ t @f$ is in range +@f$ [ 0 ; 1 ] @f$, the intersection is inside the line segment defined by +@f$ \boldsymbol{p} @f$ and @f$ \boldsymbol{p} + \boldsymbol{r} @f$, if @f$ u @f$ +is in range @f$ [ 0 ; 1 ] @f$, the intersection is inside the line segment +defined by @f$ \boldsymbol{q} @f$ and @f$ \boldsymbol{q} + \boldsymbol{s} @f$. + +The two lines intersect if @f$ t @f$ and @f$ u @f$ exist such that: @f[ + \boldsymbol p + t \boldsymbol r = \boldsymbol q + u \boldsymbol s +@f] +Crossing both sides with @f$ \boldsymbol{s} @f$, distributing the cross product +and eliminating @f$ \boldsymbol s \times \boldsymbol s = 0 @f$, then solving +for @f$ t @f$ and similarly for @f$ u @f$: @f[ + \begin{array}{rcl} + (\boldsymbol p + t \boldsymbol r) \times s & = & (\boldsymbol q + u \boldsymbol s) \times s \\ + t (\boldsymbol r \times s) & = & (\boldsymbol q - \boldsymbol p) \times s \\ + t & = & \cfrac{(\boldsymbol q - \boldsymbol p) \times s}{\boldsymbol r \times \boldsymbol s} \\ + u & = & \cfrac{(\boldsymbol q - \boldsymbol p) \times r}{\boldsymbol r \times \boldsymbol s} + \end{array} +@f] + +See also @ref lineSegmentLine() which calculates only @f$ t @f$, useful if you +don't need to test that the intersection lies inside line segment defined by +@f$ \boldsymbol{q} @f$ and @f$ \boldsymbol{q} + \boldsymbol{s} @f$. + */ +template inline std::pair lineSegmentLineSegment(const Vector2& p, const Vector2& r, const Vector2& q, const Vector2& s) { + const Vector2 qp = q - p; + const T rs = cross(r, s); + return {cross(qp, s)/rs, cross(qp, r)/rs}; +} - /** - * @brief Intersection of line segment and line in 2D - * @param p Starting point of first line segment - * @param r Direction of first line segment - * @param q Starting point of second line - * @param s Direction of second line - * @return Intersection point position `t` on first line, NaN if the - * lines are collinear or infinity if they are parallel. - * Intersection point can be then 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 `p + r`. - * - * Unlike @ref lineSegmentLineSegment() computes only **t**. - */ - template static T lineSegmentLine(const Vector2& p, const Vector2& r, const Vector2& q, const Vector2& s) { - return cross(q - p, s)/cross(r, s); - } +/** +@brief Intersection of line segment and line in 2D +@param p Starting point of first line segment +@param r Direction of first line segment +@param q Starting point of second line +@param s Direction of second line - /** - * @brief Intersection of a plane and line - * @param planePosition Plane position - * @param planeNormal Plane normal - * @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 line defined by **p** - * and **r**, value of *t* is computed and returned. @f[ - * \begin{array}{rcl} - * 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& p, const Vector3& r) { - const T f = dot(planePosition, planeNormal); - return (f-dot(planeNormal, p))/dot(planeNormal, r); - } +Returns intersection point position @f$ t @f$ on first line, NaN if the lines +are collinear or infinity if they are parallel. Intersection point can be then +calculated with @f$ \boldsymbol{p} + t \boldsymbol{r} @f$. If returned value is +in range @f$ [ 0 ; 1 ] @f$, the intersection is inside the line segment defined +by @f$ \boldsymbol{p} @f$ and @f$ \boldsymbol{p} + \boldsymbol{r} @f$. + +Unlike @ref lineSegmentLineSegment() calculates only @f$ t @f$. +*/ +template inline T lineSegmentLine(const Vector2& p, const Vector2& r, const Vector2& q, const Vector2& s) { + return cross(q - p, s)/cross(r, s); +} + +/** +@brief Intersection of a plane and line +@param planePosition Plane position +@param planeNormal Plane normal +@param p Starting point of the line +@param r Direction of the line + +Returns intersection point position @f$ t @f$ on the line, NaN if the line lies +on the plane or infinity if the intersection doesn't exist. Intersection point +can be then calculated from with @f$ \boldsymbol{p} + t \boldsymbol{r} @f$. If +returned value is in range @f$ [ 0 ; 1 ] @f$, the intersection is inside the +line segment defined by @f$ \boldsymbol{p} @f$ and @f$ \boldsymbol{r} @f$. + +First the parameter @f$ f @f$ of parametric equation of the plane is calculated +from plane normal @f$ \boldsymbol{n} @f$ 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 @f$ \boldsymbol{n} @f$, parameter @f$ f @f$ and line defined +by @f$ \boldsymbol{p} @f$ and @f$ \boldsymbol{r} @f$, value of @f$ t @f$ is +calculated and returned. @f[ + \begin{array}{rcl} + 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 inline T planeLine(const Vector3& planePosition, const Vector3& planeNormal, const Vector3& p, const Vector3& r) { + const T f = dot(planePosition, planeNormal); + return (f - dot(planeNormal, p))/dot(planeNormal, r); +} + +/** +@brief Intersection of a point and a camera frustum +@param point Point +@param frustum Frustum planes with normals pointing outwards + +Returns `true` if the point is on or inside the frustum. + +Checks for each plane of the frustum whether the point is behind the plane (the +points distance from the plane is negative) using @ref Distance::pointPlaneScaled(). +*/ +template bool pointFrustum(const Vector3& point, const Frustum& frustum); + +/** +@brief Intersection of an axis-aligned box and a camera frustum +@param box Axis-aligned box +@param frustum Frustum planes with normals pointing outwards + +Returns `true` if the box intersects with the camera frustum. + +Counts for each plane of the frustum how many points of the box lie in front of +the plane (outside of the frustum). If none, the box must lie entirely outside +of the frustum and there is no intersection. Else, the box is considered as +intersecting, even if it is merely corners of the box overlapping with corners +of the frustum, since checking the corners is less efficient. +*/ +template bool boxFrustum(const Range3D& box, const Frustum& frustum); - /** - * @brief Intersection of a point and a camera frustum - * @param point Point - * @param frustum Frustum planes with normals pointing outwards - * @return `true` if the point is on or inside the frustum. - * - * Checks for each plane of the frustum whether the point is behind the - * plane (the points distance from the plane is negative) using - * @ref Distance::pointPlaneScaled(). - */ - template static bool pointFrustum(const Vector3& point, const Frustum& frustum); - - /** - * @brief Intersection of a range and a camera frustum - * @return `true` if the box intersects with the camera frustum - * - * Counts for each plane of the frustum how many points of the box lie - * in front of the plane (outside of the frustum). If none, the box - * must lie entirely outside of the frustum and there is no - * intersection. Else, the box is considered as intersecting, even if - * it is merely corners of the box overlapping with corners of the - * frustum, since checking the corners is less efficient. - */ - template static bool boxFrustum(const Range3D& box, const Frustum& frustum); -}; - -template bool Intersection::pointFrustum(const Vector3& point, const Frustum& frustum) { +template bool pointFrustum(const Vector3& point, const Frustum& frustum) { for(const Vector4& plane: frustum.planes()) { /* The point is in front of one of the frustum planes (normals point outwards) */ @@ -165,7 +166,7 @@ template bool Intersection::pointFrustum(const Vector3& point, const return true; } -template bool Intersection::boxFrustum(const Range3D& box, const Frustum& frustum) { +template bool boxFrustum(const Range3D& box, const Frustum& frustum) { for(const Vector4& plane: frustum.planes()) { bool cornerHit = 0; @@ -187,6 +188,6 @@ template bool Intersection::boxFrustum(const Range3D& box, const Fru return true; } -}}} +}}}} #endif