diff --git a/src/Math/GeometryUtils.h b/src/Math/GeometryUtils.h index eecf9b77d..cd895b2b5 100644 --- a/src/Math/GeometryUtils.h +++ b/src/Math/GeometryUtils.h @@ -19,60 +19,49 @@ * @brief Class Magnum::Math::GeometryUtils */ -#include "Matrix3.h" +#include "Vector3.h" namespace Magnum { namespace Math { /** @brief Geometry utils */ -template class GeometryUtils { +class GeometryUtils { public: /** * @brief Intersection of a plane and line - * @param plane Plane defined by three points - * @param a Starting point of the line - * @param b Ending point of the line - * @return Value, NaN if the line lies on the plane or infinity if the - * intersection doesn't exist. Intersection point can be then computed - * 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 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`. * - * First the parametric equation of the plane is computed, - * @f$ cx + dy + ez = f @f$. Parameters @f$ (c, d, e) @f$ are cross - * product of two vectors defining the plane, parameter @f$ f @f$ is - * computed using @f$ (c, d, e) @f$ and one of points defining the - * plane. + * First the parameter *f* of parametric equation of the plane + * is computed from plane normal **n** and plane position: * @f[ - * \begin{array}{lcl} - * (g, h, i) & = & plane \\ - * (c, d, e) & = & (h - g) \times (i - g) \\ - * f & = & (c, d, e) \cdot g - * \end{array} + * \begin{pmatrix} n_0 \\ n_1 \\ n_2 \end{pmatrix} \cdot + * \begin{pmatrix} x \\ y \\ z \end{pmatrix} - f = 0 * @f] - * - * Using parametric equation and points @f$ a @f$ and @f$ b @f$, value - * of @f$ t @f$ is computed and returned. + * Using plane normal **n**, parameter *f* and points **a** and **b**, + * value of *t* is computed and returned. * @f[ - * \begin{array}{lcl} - * \Delta b & = & b - a \\ - * f & = & (c, d, e) \cdot (a + \Delta b \cdot t) \\ - * t & = & \frac{f - (c, d, e) \cdot a} - * {(c, d, e) \cdot \Delta b} + * \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} * \end{array} * @f] */ - static T intersection(const Matrix3& plane, const Vector3& a, const Vector3& b) { - /* Cross product of two vectors defining the plane */ - Vector3 crossProduct = Vector3::cross(plane[1]-plane[0], plane[2]-plane[0]); - - /* Compute f with cross product and one of the points defining the - plane */ - T f = Vector3::dot(crossProduct, plane[0]); + template static T intersection(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(crossProduct, a)/Vector3::dot(crossProduct, b-a)); + return (f-Vector3::dot(planeNormal, a)/Vector3::dot(planeNormal, b-a)); } }; diff --git a/src/Math/Test/GeometryUtilsTest.cpp b/src/Math/Test/GeometryUtilsTest.cpp index e5624fc86..a26c88239 100644 --- a/src/Math/Test/GeometryUtilsTest.cpp +++ b/src/Math/Test/GeometryUtilsTest.cpp @@ -18,52 +18,36 @@ #include #include -#include "Matrix3.h" #include "GeometryUtils.h" QTEST_APPLESS_MAIN(Magnum::Math::Test::GeometryUtilsTest) -typedef Magnum::Math::Matrix3 Matrix3; -typedef Magnum::Math::Vector3 Vector3; - -Q_DECLARE_METATYPE(Matrix3) -Q_DECLARE_METATYPE(Vector3) - using namespace std; namespace Magnum { namespace Math { namespace Test { -using ::Matrix3; -using ::Vector3; - -void GeometryUtilsTest::intersection_data() { - QTest::addColumn("plane"); - QTest::addColumn("a"); - QTest::addColumn("b"); - QTest::addColumn("expected"); - - Matrix3 plane(0.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f); - QTest::newRow("inside") << plane << Vector3(0, 0, -1) << Vector3(0, 0, 1) << 0.5f; - QTest::newRow("outside") << plane << Vector3(0, 0, 1) << Vector3(0, 0, 2) << -1.0f; - QTest::newRow("NaN") << plane << Vector3(1, 0, 0) << Vector3(0, 1, 0) << numeric_limits::quiet_NaN(); - QTest::newRow("inf") << plane << Vector3(1, 0, 1) << Vector3(0, 0, 1) << numeric_limits::infinity(); -} +typedef Magnum::Math::Vector3 Vector3; void GeometryUtilsTest::intersection() { - QFETCH(Matrix3, plane); - QFETCH(Vector3, a); - QFETCH(Vector3, b); - QFETCH(float, expected); - - /* Handling also NaN, which cannot be fuzzy compared */ - float actual = GeometryUtils::intersection(plane, a, b); - - /* All possible workarounds for comparing to inf and NaN */ - if(expected > numeric_limits::max()) QCOMPARE(actual, expected); - else if(expected != expected) QVERIFY(actual != actual); - else QVERIFY(actual == expected); + Vector3 planePosition; + Vector3 planeNormal(0.0f, 0.0f, 1.0f); + + /* Inside line segment */ + QCOMPARE((GeometryUtils::intersection(planePosition, planeNormal, + Vector3(0, 0, -1), Vector3(0, 0, 1))), 0.5f); + + /* Outside line segment */ + QCOMPARE((GeometryUtils::intersection(planePosition, planeNormal, + Vector3(0, 0, 1), Vector3(0, 0, 2))), -1.0f); + + /* Line lies on the plane */ + float nan = GeometryUtils::intersection(planePosition, planeNormal, + Vector3(1, 0, 0), Vector3(0, 1, 0)); + QVERIFY(nan != nan); + + /* Line is parallell to the plane */ + QCOMPARE((GeometryUtils::intersection(planePosition, planeNormal, + Vector3(1, 0, 1), Vector3(0, 0, 1))), numeric_limits::infinity()); } }}} diff --git a/src/Math/Test/GeometryUtilsTest.h b/src/Math/Test/GeometryUtilsTest.h index 82919065a..bd25c1a79 100644 --- a/src/Math/Test/GeometryUtilsTest.h +++ b/src/Math/Test/GeometryUtilsTest.h @@ -23,7 +23,6 @@ class GeometryUtilsTest: public QObject { Q_OBJECT private slots: - void intersection_data(); void intersection(); };