|
|
|
|
@ -19,6 +19,8 @@
|
|
|
|
|
* @brief Class Magnum::Math::Geometry::Distance |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include "Math/Math.h" |
|
|
|
|
#include "Math/Matrix.h" |
|
|
|
|
#include "Math/Vector3.h" |
|
|
|
|
|
|
|
|
|
namespace Magnum { namespace Math { namespace Geometry { |
|
|
|
|
@ -27,7 +29,39 @@ namespace Magnum { namespace Math { namespace Geometry {
|
|
|
|
|
class Distance { |
|
|
|
|
public: |
|
|
|
|
/**
|
|
|
|
|
* @brief %Distance of line and point |
|
|
|
|
* @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 Matrix::determinant() "determinant": @f[ |
|
|
|
|
* d = \frac{|det(b - a a - point)|} {|b - a|} |
|
|
|
|
* @f] |
|
|
|
|
* Source: http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
|
|
|
|
|
* @see linePointSquared(const Vector2&, const Vector2&, const Vector2&) |
|
|
|
|
*/ |
|
|
|
|
template<class T> inline static T linePoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) { |
|
|
|
|
return std::abs(Matrix<2, T>::from(b - a, a - point).determinant())/(b - a).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 linePoint(const Vector2&, const Vector2&, const Vector2&) |
|
|
|
|
* for comparing distance with other values, because it doesn't |
|
|
|
|
* compute the square root. |
|
|
|
|
*/ |
|
|
|
|
template<class T> inline static T linePointSquared(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) { |
|
|
|
|
Vector2<T> bMinusA = b - a; |
|
|
|
|
return Math::pow<2>(Matrix<2, T>::from(bMinusA, a - point).determinant())/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 |
|
|
|
|
@ -37,25 +71,26 @@ class Distance {
|
|
|
|
|
* d = \frac{|(\boldsymbol p - \boldsymbol a) \times (\boldsymbol p - \boldsymbol b)|} |
|
|
|
|
* {|\boldsymbol b - \boldsymbol a|} |
|
|
|
|
* @f] |
|
|
|
|
* |
|
|
|
|
* @see linePointSquared() |
|
|
|
|
* Source: http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
|
|
|
|
|
* @see linePointSquared(const Vector3&, const Vector3&, const Vector3&) |
|
|
|
|
*/ |
|
|
|
|
template<class T> inline static T linePoint(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) { |
|
|
|
|
return sqrt(linePointSquared(a, b, point)); |
|
|
|
|
return std::sqrt(linePointSquared(a, b, point)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief %Distance of line and point, squared |
|
|
|
|
* @brief %Distance of line and point in 3D, squared |
|
|
|
|
* |
|
|
|
|
* More efficient than linePoint() for comparing distance with other |
|
|
|
|
* values, because it doesn't compute the square root. |
|
|
|
|
* More efficient than linePoint(const Vector3&, const Vector3&, const Vector3&) |
|
|
|
|
* for comparing distance with other values, because it doesn't |
|
|
|
|
* compute the square root. |
|
|
|
|
*/ |
|
|
|
|
template<class T> static T linePointSquared(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) { |
|
|
|
|
return Vector3<T>::cross(point - a, point - b).dot()/(b - a).dot(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief %Dístance of point from line segment |
|
|
|
|
* @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 |
|
|
|
|
@ -80,16 +115,73 @@ class Distance {
|
|
|
|
|
* |
|
|
|
|
* @see lineSegmentPointSquared() |
|
|
|
|
*/ |
|
|
|
|
template<class T> inline static T lineSegmentPoint(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) { |
|
|
|
|
return sqrt(lineSegmentPointSquared(a, b, point)); |
|
|
|
|
template<class T> inline static T lineSegmentPoint(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) { |
|
|
|
|
Vector2<T> pointMinusA = point - a; |
|
|
|
|
Vector2<T> pointMinusB = point - b; |
|
|
|
|
Vector2<T> bMinusA = b - a; |
|
|
|
|
T pointDistanceA = pointMinusA.dot(); |
|
|
|
|
T pointDistanceB = pointMinusB.dot(); |
|
|
|
|
T bDistanceA = bMinusA.dot(); |
|
|
|
|
|
|
|
|
|
/* Point is before A */ |
|
|
|
|
if(pointDistanceB > bDistanceA + pointDistanceA) |
|
|
|
|
return std::sqrt(pointDistanceA); |
|
|
|
|
|
|
|
|
|
/* Point is after B */ |
|
|
|
|
if(pointDistanceA > bDistanceA + pointDistanceB) |
|
|
|
|
return std::sqrt(pointDistanceB); |
|
|
|
|
|
|
|
|
|
/* Between A and B */ |
|
|
|
|
return std::abs(Matrix<2, T>::from(bMinusA, -pointMinusA).determinant())/std::sqrt(bDistanceA); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief %Distance of point from line segment, squared |
|
|
|
|
* @brief %Distance of point from line segment in 2D, squared |
|
|
|
|
* |
|
|
|
|
* More efficient than lineSegmentPoint() for comparing distance with |
|
|
|
|
* other values, because it doesn't compute the square root. |
|
|
|
|
*/ |
|
|
|
|
template<class T> static T lineSegmentPointSquared(const Vector2<T>& a, const Vector2<T>& b, const Vector2<T>& point) { |
|
|
|
|
Vector2<T> pointMinusA = point - a; |
|
|
|
|
Vector2<T> pointMinusB = point - b; |
|
|
|
|
Vector2<T> bMinusA = b - a; |
|
|
|
|
T pointDistanceA = pointMinusA.dot(); |
|
|
|
|
T pointDistanceB = pointMinusB.dot(); |
|
|
|
|
T bDistanceA = bMinusA.dot(); |
|
|
|
|
|
|
|
|
|
/* Point is before A */ |
|
|
|
|
if(pointDistanceB > bDistanceA + pointDistanceA) |
|
|
|
|
return pointDistanceA; |
|
|
|
|
|
|
|
|
|
/* Point is after B */ |
|
|
|
|
if(pointDistanceA > bDistanceA + pointDistanceB) |
|
|
|
|
return pointDistanceB; |
|
|
|
|
|
|
|
|
|
/* Between A and B */ |
|
|
|
|
return Math::pow<2>(Matrix<2, T>::from(bMinusA, -pointMinusA).determinant())/bDistanceA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @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 |
|
|
|
|
* lineSegmentPoint(const Vector2&, const Vector2&, const Vector2&). |
|
|
|
|
* |
|
|
|
|
* @see lineSegmentPointSquared(const Vector3&, const Vector3&, const Vector3&) |
|
|
|
|
*/ |
|
|
|
|
template<class T> inline static T lineSegmentPoint(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) { |
|
|
|
|
return std::sqrt(lineSegmentPointSquared(a, b, point)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief %Distance of point from line segment in 3D, squared |
|
|
|
|
* |
|
|
|
|
* More efficient than lineSegmentPoint(const Vector3&, const Vector3&, const Vector3&) for comparing distance with |
|
|
|
|
* other values, because it doesn't compute the square root. |
|
|
|
|
*/ |
|
|
|
|
template<class T> static T lineSegmentPointSquared(const Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) { |
|
|
|
|
Vector3<T> pointMinusA = point - a; |
|
|
|
|
Vector3<T> pointMinusB = point - b; |
|
|
|
|
|