Browse Source

Function for computing distance of line segment and point.

pull/279/head
Vladimír Vondruš 14 years ago
parent
commit
822d66f380
  1. 58
      src/Math/Geometry/Distance.h
  2. 24
      src/Math/Geometry/Test/DistanceTest.cpp
  3. 1
      src/Math/Geometry/Test/DistanceTest.h

58
src/Math/Geometry/Distance.h

@ -54,6 +54,64 @@ class Distance {
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).lengthSquared()/(b - a).lengthSquared();
}
/**
* @brief %Dístance of point from line segment
* @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 linePoint().
* @f[
* |\boldsymbol b - \boldsymbol a|^2 > |\boldsymbol p - \boldsymbol a|^2 + |\boldsymbol p - \boldsymbol b|^2
* @f]
*
* @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));
}
/**
* @brief %Distance of point from line segment, 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 Vector3<T>& a, const Vector3<T>& b, const Vector3<T>& point) {
Vector3<T> pointMinusA = point - a;
Vector3<T> pointMinusB = point - b;
T pointDistanceA = pointMinusA.lengthSquared();
T pointDistanceB = pointMinusB.lengthSquared();
T bDistanceA = (b - a).lengthSquared();
/* 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 Vector3<T>::cross(pointMinusA, pointMinusB).lengthSquared()/bDistanceA;
}
};
}}}

24
src/Math/Geometry/Test/DistanceTest.cpp

@ -43,4 +43,28 @@ void DistanceTest::linePoint() {
Constants<float>::Sqrt2/Constants<float>::Sqrt3);
}
void DistanceTest::lineSegmentPoint() {
Vector3 a(0.0f);
Vector3 b(1.0f);
/* Point on the line segment */
QCOMPARE((Distance::lineSegmentPoint(a, b, Vector3(0.25f))), 0.0f);
/* Point on the line, outside the segment, closer to A */
QCOMPARE((Distance::lineSegmentPoint(a, b, Vector3(-1.0f))), +Constants<float>::Sqrt3);
/* Point on the line, outside the segment, closer to B */
QCOMPARE((Distance::lineSegmentPoint(a, b, Vector3(1.0f+1.0f/Constants<float>::Sqrt3))), 1.0f);
/* Point next to the line segment */
QCOMPARE((Distance::lineSegmentPoint(a, b, Vector3(1.0f, 0.0f, 1.0f))),
Constants<float>::Sqrt2/Constants<float>::Sqrt3);
/* Point outside the line segment, closer to A */
QCOMPARE((Distance::lineSegmentPoint(a, b, Vector3(1.0f, 0.0f, 1.0f)-Vector3(1.0f))), 1.0f);
/* Point outside the line segment, closer to B */
QCOMPARE((Distance::lineSegmentPoint(a, b, Vector3(1.0f, 0.0f, 1.0f)+Vector3(1.0f))), +Constants<float>::Sqrt2);
}
}}}}

1
src/Math/Geometry/Test/DistanceTest.h

@ -24,6 +24,7 @@ class DistanceTest: public QObject {
private slots:
void linePoint();
void lineSegmentPoint();
};
}}}}

Loading…
Cancel
Save