Browse Source

New class Math::GeometryUtils.

GeometryUtils::intersection() computes intersection of a plane and a
line.
vectorfields
Vladimír Vondruš 15 years ago
parent
commit
32a7f6d082
  1. 81
      src/Math/GeometryUtils.h
  2. 2
      src/Math/Test/CMakeLists.txt
  3. 71
      src/Math/Test/GeometryUtilsTest.cpp
  4. 32
      src/Math/Test/GeometryUtilsTest.h

81
src/Math/GeometryUtils.h

@ -0,0 +1,81 @@
#ifndef Magnum_Math_GeometryUtils_h
#define Magnum_Math_GeometryUtils_h
/*
Copyright © 2010, 2011 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
/** @file
* @brief Class Magnum::Math::GeometryUtils
*/
#include "Matrix3.h"
namespace Magnum { namespace Math {
/**
@brief Geometry utils
*/
template<class T> 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 <tt>a+intersection(...)*b</tt>. If returned value is in range
* @f$ [ 0 ; 1 ] @f$, the intersection is inside the line segment
* defined by @c a and @c 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.
* @f[
* \begin{array}{lcl}
* (g, h, i) & = & plane \\
* (c, d, e) & = & (h - g) \times (i - g) \\
* f & = & (c, d, e) \cdot g
* \end{array}
* @f]
*
* Using parametric equation and points @f$ a @f$ and @f$ b @f$, value
* of @f$ t @f$ 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}
* \end{array}
* @f]
*/
static T intersection(const Matrix3<T>& plane, const Vector3<T>& a, const Vector3<T>& b) {
/* Cross product of two vectors defining the plane */
Vector3<T> crossProduct = Vector3<T>::cross(plane.at(1)-plane.at(0), plane.at(2)-plane.at(0));
/* Compute f with cross product and one of the points defining the
plane */
T f = crossProduct*plane.at(0);
/* Compute t */
return (f-crossProduct*a)/(crossProduct*(b-a));
}
};
}}
#endif

2
src/Math/Test/CMakeLists.txt

@ -4,3 +4,5 @@ magnum_add_test(Vector4Test Vector4Test.h Vector4Test.cpp)
magnum_add_test(MatrixTest MatrixTest.h MatrixTest.cpp)
magnum_add_test(Matrix4Test Matrix4Test.h Matrix4Test.cpp)
magnum_add_test(GeometryUtilsTest GeometryUtilsTest.h GeometryUtilsTest.cpp)

71
src/Math/Test/GeometryUtilsTest.cpp

@ -0,0 +1,71 @@
/*
Copyright © 2010, 2011 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include "GeometryUtilsTest.h"
#include <limits>
#include <QtTest/QTest>
#include "Matrix3.h"
#include "GeometryUtils.h"
QTEST_APPLESS_MAIN(Magnum::Math::Test::GeometryUtilsTest)
typedef Magnum::Math::Matrix3<float> Matrix3;
typedef Magnum::Math::Vector3<float> 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<Matrix3>("plane");
QTest::addColumn<Vector3>("a");
QTest::addColumn<Vector3>("b");
QTest::addColumn<float>("expected");
float plane[] = {
0, 0, 0,
1, 0, 0,
0, 1, 0
};
QTest::newRow("inside") << Matrix3(plane) << Vector3(0, 0, -1) << Vector3(0, 0, 1) << 0.5f;
QTest::newRow("outside") << Matrix3(plane) << Vector3(0, 0, 1) << Vector3(0, 0, 2) << -1.0f;
QTest::newRow("NaN") << Matrix3(plane) << Vector3(1, 0, 0) << Vector3(0, 1, 0) << numeric_limits<float>::quiet_NaN();
QTest::newRow("inf") << Matrix3(plane) << Vector3(1, 0, 1) << Vector3(0, 0, 1) << numeric_limits<float>::infinity();
}
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<float>::intersection(plane, a, b);
/* All possible workarounds for comparing to inf and NaN */
if(expected > numeric_limits<float>::max()) QCOMPARE(actual, expected);
else if(expected != expected) QVERIFY(actual != actual);
else QVERIFY(actual == expected);
}
}}}

32
src/Math/Test/GeometryUtilsTest.h

@ -0,0 +1,32 @@
#ifndef Magnum_Math_Test_GeometryUtilsTest_h
#define Magnum_Math_Test_GeometryUtilsTest_h
/*
Copyright © 2010, 2011 Vladimír Vondruš <mosra@centrum.cz>
This file is part of Magnum.
Magnum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License version 3
only, as published by the Free Software Foundation.
Magnum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License version 3 for more details.
*/
#include <QtCore/QObject>
namespace Magnum { namespace Math { namespace Test {
class GeometryUtilsTest: public QObject {
Q_OBJECT
private slots:
void intersection_data();
void intersection();
};
}}}
#endif
Loading…
Cancel
Save