Browse Source

python: expose new Quaternion reflection APIs.

next
Vladimír Vondruš 2 years ago
parent
commit
8b0dc8ca67
  1. 4
      doc/python/magnum.math.rst
  2. 2
      doc/python/pages/changelog.rst
  3. 9
      src/python/magnum/math.cpp
  4. 8
      src/python/magnum/test/test_math.py

4
doc/python/magnum.math.rst

@ -324,6 +324,10 @@
:raise ValueError: If :p:`normalized_axis` is not normalized
.. py:function:: magnum.Quaterniond.rotation(angle: magnum.Rad, normalized_axis: magnum.Vector3d)
:raise ValueError: If :p:`normalized_axis` is not normalized
.. py:function:: magnum.Quaternion.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Quaterniond.reflection
:raise ValueError: If :p:`normal` is not normalized
.. py:function:: magnum.Quaternion.from_matrix
:raise ValueError: If :p:`matrix` is not a rotation
.. py:function:: magnum.Quaterniond.from_matrix

2
doc/python/pages/changelog.rst

@ -68,6 +68,8 @@ Changelog
- Exposed :ref:`Color3.from_xyz()`, :ref:`Color3.from_linear_rgb_int()`,
:ref:`Color3.to_xyz()`, :ref:`Color3.to_linear_rgb_int()` and equivalent
APIs on :ref:`Color4`
- Exposed new :ref:`Quaternion.reflection()` and
:ref:`Quaternion.reflect_vector()` APIs
- Exposed :ref:`gl.Context` and its platform-specific subclasses for EGL, WGL
and GLX
- Exposed :ref:`gl.Framebuffer.attach_texture()` and missing sRGB, depth

9
src/python/magnum/math.cpp

@ -348,6 +348,13 @@ template<class T> void quaternion(py::module_& m, py::class_<T>& c) {
}
return T::rotation(Math::Rad<typename T::Type>(angle), normalizedAxis);
}, "Rotation quaternion", py::arg("angle"), py::arg("normalized_axis"))
.def_static("reflection", [](const Math::Vector3<typename T::Type>& normal) {
if(!normal.isNormalized()) {
PyErr_Format(PyExc_ValueError, "normal %S is not normalized", py::cast(normal).ptr());
throw py::error_already_set{};
}
return T::reflection(normal);
}, "Reflection quaternion", py::arg("normal"))
.def_static("from_matrix", [](const Math::Matrix3x3<typename T::Type>& matrix) {
/* Same as the check in fromMatrix() */
if(std::abs(matrix.determinant() - typename T::Type(1)) >= typename T::Type(3)*Math::TypeTraits<typename T::Type>::epsilon()) {
@ -459,6 +466,8 @@ template<class T> void quaternion(py::module_& m, py::class_<T>& c) {
}
return self.transformVectorNormalized(vector);
}, "Rotate a vector with a normalized quaternion", py::arg("vector"))
.def("reflect_vector", &T::reflectVector,
"Reflect a vector with a reflection quaternion", py::arg("vector"))
/* Properties */
.def_property("vector",

8
src/python/magnum/test/test_math.py

@ -1454,9 +1454,14 @@ class Quaternion_(unittest.TestCase):
b = Quaternion.from_matrix(Matrix4.rotation_x(Deg(45.0)).rotation_scaling())
self.assertEqual(a, Quaternion((0.382683, 0.0, 0.0), 0.92388))
c = Quaternion.reflection(Vector3.x_axis())
self.assertEqual(c, Quaternion((1.0, 0.0, 0.0), 0.0))
def test_static_methods_invalid(self):
with self.assertRaisesRegex(ValueError, "axis Vector\\(2, 0, 1\\) is not normalized"):
Quaternion.rotation(Deg(35.0), Vector3(2.0, 0.0, 1.0))
with self.assertRaisesRegex(ValueError, "normal Vector\\(2, 0, 1\\) is not normalized"):
Quaternion.reflection(Vector3(2.0, 0.0, 1.0))
with self.assertRaisesRegex(ValueError, """the matrix is not a rotation:
Matrix\\(2, 0, 0,
0, 2, 0,
@ -1483,6 +1488,9 @@ Matrix\\(2, 0, 0,
self.assertEqual(a.transform_vector(Vector3.y_axis()), Vector3(0.0, 0.707107, 0.707107))
self.assertEqual(a.transform_vector_normalized(Vector3.y_axis()), Vector3(0.0, 0.707107, 0.707107))
b = Quaternion.reflection(Vector3.x_axis())
self.assertEqual(b.reflect_vector(Vector3.x_axis()), (-1.0, 0.0, 0.0))
def test_methods_invalid(self):
a = Quaternion.rotation(Deg(45.0), Vector3.x_axis())*3.0

Loading…
Cancel
Save