From 1bb5b4a74e89eb501e288a238d116abf4e4b2388 Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de> Date: Sat, 28 May 2022 22:12:07 +0200 Subject: [PATCH] provide and use RotMatrix::angleAroundCoordAxis --- Base/Vector/RotMatrix.cpp | 11 ++++ Base/Vector/RotMatrix.h | 3 ++ Sample/Scattering/Rotations.cpp | 34 +++++------- Sim/Export/SampleToPython.cpp | 47 ++++++++--------- auto/Wrap/doxygenBase.i | 3 ++ auto/Wrap/libBornAgainBase.py | 8 +++ auto/Wrap/libBornAgainBase_wrap.cpp | 80 +++++++++++++++++++++-------- 7 files changed, 117 insertions(+), 69 deletions(-) diff --git a/Base/Vector/RotMatrix.cpp b/Base/Vector/RotMatrix.cpp index 2dd4f744f35..bfd9dbf02c2 100644 --- a/Base/Vector/RotMatrix.cpp +++ b/Base/Vector/RotMatrix.cpp @@ -163,3 +163,14 @@ bool RotMatrix::isZRotation() const { return x == 0 && y == 0; } + +std::optional<double> RotMatrix::angleAroundCoordAxis(int iAxis) const +{ + if (iAxis==0 && y == 0 && z == 0) + return 2 * atan2(x, s); + if (iAxis==1 && x == 0 && z == 0) + return 2 * atan2(y, s); + if (iAxis==2 && x == 0 && y == 0) + return 2 * atan2(z, s); + return {}; +} diff --git a/Base/Vector/RotMatrix.h b/Base/Vector/RotMatrix.h index 2e44b75175a..dc8f5e255e5 100644 --- a/Base/Vector/RotMatrix.h +++ b/Base/Vector/RotMatrix.h @@ -17,6 +17,7 @@ #include <heinz/Vectors3D.h> #include <array> +#include <optional> //! Rotation matrix in three dimensions. @@ -87,6 +88,8 @@ public: bool isYRotation() const; bool isZRotation() const; + std::optional<double> angleAroundCoordAxis(int iAxis) const; + private: RotMatrix(double x_, double y_, double z_, double s_); diff --git a/Sample/Scattering/Rotations.cpp b/Sample/Scattering/Rotations.cpp index 8f60252e12c..e584ce4af4f 100644 --- a/Sample/Scattering/Rotations.cpp +++ b/Sample/Scattering/Rotations.cpp @@ -25,28 +25,18 @@ IRotation::IRotation(const std::vector<double>& PValues) { } -IRotation* IRotation::createRotation(const RotMatrix& transform) -{ - auto rot_type = transform.getRotationType(); - switch (rot_type) { - case RotMatrix::XAXIS: { - double angle = transform.calculateRotateXAngle(); - return new RotationX(angle); - } - case RotMatrix::YAXIS: { - double angle = transform.calculateRotateYAngle(); - return new RotationY(angle); - } - case RotMatrix::ZAXIS: { - double angle = transform.calculateRotateZAngle(); - return new RotationZ(angle); - } - case RotMatrix::EULER: { - auto angles = transform.zxzEulerAngles(); - return new RotationEuler(angles[0], angles[1], angles[2]); - } - } - ASSERT(0); // impossible case +IRotation* IRotation::createRotation(const RotMatrix& matrix) +{ + if (matrix.isIdentity()) + return new IdentityRotation; + if (std::optional<double> angle = matrix.angleAroundCoordAxis(0)) + return new RotationX(angle.value()); + if (std::optional<double> angle = matrix.angleAroundCoordAxis(1)) + return new RotationY(angle.value()); + if (std::optional<double> angle = matrix.angleAroundCoordAxis(2)) + return new RotationZ(angle.value()); + auto angles = matrix.zxzEulerAngles(); + return new RotationEuler(angles[0], angles[1], angles[2]); } R3 IRotation::transformed(const R3& v) const diff --git a/Sim/Export/SampleToPython.cpp b/Sim/Export/SampleToPython.cpp index cf492590ec6..3947633e652 100644 --- a/Sim/Export/SampleToPython.cpp +++ b/Sim/Export/SampleToPython.cpp @@ -39,6 +39,8 @@ using Py::Fmt::indent; +static const std::map<int, char> axisChar {{0,'X'}, {1,'Y'}, {2,'Z'}}; + namespace { void setRotationInformation(const IParticle* particle, std::string name, std::ostringstream& result) @@ -46,34 +48,25 @@ void setRotationInformation(const IParticle* particle, std::string name, std::os if (!particle->rotation()) return; const RotMatrix matrix = particle->rotation()->rotMatrix(); - switch (matrix.getRotationType()) { - case RotMatrix::EULER: { - auto angles = matrix.zxzEulerAngles(); - result << indent() << name << "_rotation = ba.RotationEuler(" - << Py::Fmt::printDegrees(angles[0]) << ", " - << Py::Fmt::printDegrees(angles[1]) << ", " - << Py::Fmt::printDegrees(angles[2]) << ")\n"; - break; - } - case RotMatrix::XAXIS: { - double alpha = matrix.calculateRotateXAngle(); - result << indent() << name << "_rotation = ba.RotationX(" - << Py::Fmt::printDegrees(alpha) << ")\n"; - break; - } - case RotMatrix::YAXIS: { - double alpha = matrix.calculateRotateYAngle(); - result << indent() << name << "_rotation = ba.RotationY(" - << Py::Fmt::printDegrees(alpha) << ")\n"; - break; - } - case RotMatrix::ZAXIS: { - double alpha = matrix.calculateRotateZAngle(); - result << indent() << name << "_rotation = ba.RotationZ(" - << Py::Fmt::printDegrees(alpha) << ")\n"; - break; - } + // Identity matrix? + if (matrix.isIdentity()) + return; + // Rotation around coordinate axis? + for (int iAxis = 0; iAxis<3; ++iAxis) { + std::optional<double> angle = matrix.angleAroundCoordAxis(iAxis); + if (angle) { + result << indent() << name << "_rotation = ba.Rotation" << axisChar.at(iAxis) << "(" + << Py::Fmt::printDegrees(angle.value()) << ")\n"; + result << indent() << name << ".setRotation(" << name << "_rotation)\n"; + return; + } } + // Generic rotation. + auto angles = matrix.zxzEulerAngles(); + result << indent() << name << "_rotation = ba.RotationEuler(" + << Py::Fmt::printDegrees(angles[0]) << ", " + << Py::Fmt::printDegrees(angles[1]) << ", " + << Py::Fmt::printDegrees(angles[2]) << ")\n"; result << indent() << name << ".setRotation(" << name << "_rotation)\n"; } diff --git a/auto/Wrap/doxygenBase.i b/auto/Wrap/doxygenBase.i index b7b0d2443a9..6fa6bd525c4 100644 --- a/auto/Wrap/doxygenBase.i +++ b/auto/Wrap/doxygenBase.i @@ -1067,6 +1067,9 @@ Determine if the transformation is trivial (identity) %feature("docstring") RotMatrix::isZRotation "bool RotMatrix::isZRotation() const "; +%feature("docstring") RotMatrix::angleAroundCoordAxis "std::optional< double > RotMatrix::angleAroundCoordAxis(int iAxis) const +"; + // File: classSphericalPixel.xml %feature("docstring") SphericalPixel " diff --git a/auto/Wrap/libBornAgainBase.py b/auto/Wrap/libBornAgainBase.py index 90136aa54d0..1ce6b0abdd3 100644 --- a/auto/Wrap/libBornAgainBase.py +++ b/auto/Wrap/libBornAgainBase.py @@ -2038,6 +2038,14 @@ class RotMatrix(object): """ return _libBornAgainBase.RotMatrix_isZRotation(self) + def angleAroundCoordAxis(self, iAxis): + r""" + angleAroundCoordAxis(RotMatrix self, int iAxis) -> std::optional< double > + std::optional< double > RotMatrix::angleAroundCoordAxis(int iAxis) const + + """ + return _libBornAgainBase.RotMatrix_angleAroundCoordAxis(self, iAxis) + # Register RotMatrix in _libBornAgainBase: _libBornAgainBase.RotMatrix_swigregister(RotMatrix) diff --git a/auto/Wrap/libBornAgainBase_wrap.cpp b/auto/Wrap/libBornAgainBase_wrap.cpp index 87c9cc88a22..eff906328eb 100644 --- a/auto/Wrap/libBornAgainBase_wrap.cpp +++ b/auto/Wrap/libBornAgainBase_wrap.cpp @@ -3139,26 +3139,27 @@ namespace Swig { #define SWIGTYPE_p_std__invalid_argument swig_types[39] #define SWIGTYPE_p_std__lessT_std__string_t swig_types[40] #define SWIGTYPE_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t swig_types[41] -#define SWIGTYPE_p_std__pairT_double_double_t swig_types[42] -#define SWIGTYPE_p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t swig_types[43] -#define SWIGTYPE_p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t swig_types[44] -#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[45] -#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[46] -#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[47] -#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[48] -#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[49] -#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[50] -#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[51] -#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[52] -#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[53] -#define SWIGTYPE_p_swig__SwigPyIterator swig_types[54] -#define SWIGTYPE_p_unsigned_char swig_types[55] -#define SWIGTYPE_p_unsigned_int swig_types[56] -#define SWIGTYPE_p_unsigned_long_long swig_types[57] -#define SWIGTYPE_p_unsigned_short swig_types[58] -#define SWIGTYPE_p_value_type swig_types[59] -static swig_type_info *swig_types[61]; -static swig_module_info swig_module = {swig_types, 60, 0, 0, 0, 0}; +#define SWIGTYPE_p_std__optionalT_double_t swig_types[42] +#define SWIGTYPE_p_std__pairT_double_double_t swig_types[43] +#define SWIGTYPE_p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t swig_types[44] +#define SWIGTYPE_p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t swig_types[45] +#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[46] +#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[47] +#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[48] +#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[49] +#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[50] +#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[51] +#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[52] +#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[53] +#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[54] +#define SWIGTYPE_p_swig__SwigPyIterator swig_types[55] +#define SWIGTYPE_p_unsigned_char swig_types[56] +#define SWIGTYPE_p_unsigned_int swig_types[57] +#define SWIGTYPE_p_unsigned_long_long swig_types[58] +#define SWIGTYPE_p_unsigned_short swig_types[59] +#define SWIGTYPE_p_value_type swig_types[60] +static swig_type_info *swig_types[62]; +static swig_module_info swig_module = {swig_types, 61, 0, 0, 0, 0}; #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -25073,6 +25074,36 @@ fail: } +SWIGINTERN PyObject *_wrap_RotMatrix_angleAroundCoordAxis(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + RotMatrix *arg1 = (RotMatrix *) 0 ; + int arg2 ; + void *argp1 = 0 ; + int res1 = 0 ; + int val2 ; + int ecode2 = 0 ; + PyObject *swig_obj[2] ; + std::optional< double > result; + + if (!SWIG_Python_UnpackTuple(args, "RotMatrix_angleAroundCoordAxis", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_RotMatrix, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "RotMatrix_angleAroundCoordAxis" "', argument " "1"" of type '" "RotMatrix const *""'"); + } + arg1 = reinterpret_cast< RotMatrix * >(argp1); + ecode2 = SWIG_AsVal_int(swig_obj[1], &val2); + if (!SWIG_IsOK(ecode2)) { + SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "RotMatrix_angleAroundCoordAxis" "', argument " "2"" of type '" "int""'"); + } + arg2 = static_cast< int >(val2); + result = ((RotMatrix const *)arg1)->angleAroundCoordAxis(arg2); + resultobj = SWIG_NewPointerObj((new std::optional< double >(static_cast< const std::optional< double >& >(result))), SWIGTYPE_p_std__optionalT_double_t, SWIG_POINTER_OWN | 0 ); + return resultobj; +fail: + return NULL; +} + + SWIGINTERN PyObject *RotMatrix_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *obj; if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL; @@ -30177,6 +30208,11 @@ static PyMethodDef SwigMethods[] = { "bool RotMatrix::isZRotation() const\n" "\n" ""}, + { "RotMatrix_angleAroundCoordAxis", _wrap_RotMatrix_angleAroundCoordAxis, METH_VARARGS, "\n" + "RotMatrix_angleAroundCoordAxis(RotMatrix self, int iAxis) -> std::optional< double >\n" + "std::optional< double > RotMatrix::angleAroundCoordAxis(int iAxis) const\n" + "\n" + ""}, { "RotMatrix_swigregister", RotMatrix_swigregister, METH_O, NULL}, { "RotMatrix_swiginit", RotMatrix_swiginit, METH_VARARGS, NULL}, { "new_Bin1D", _wrap_new_Bin1D, METH_VARARGS, "\n" @@ -30945,6 +30981,7 @@ static swig_type_info _swigt__p_std__complexT_double_t = {"_p_std__complexT_doub static swig_type_info _swigt__p_std__invalid_argument = {"_p_std__invalid_argument", "std::invalid_argument *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__lessT_std__string_t = {"_p_std__lessT_std__string_t", "std::less< std::string > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t = {"_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t", "std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > *|std::map< std::string,double > *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_std__optionalT_double_t = {"_p_std__optionalT_double_t", "std::optional< double > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__pairT_double_double_t = {"_p_std__pairT_double_double_t", "std::pair< double,double > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t = {"_p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t", "std::vector< IAxis const *,std::allocator< IAxis const * > > *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t = {"_p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t", "std::vector< IAxis *,std::allocator< IAxis * > > *", 0, 0, (void*)0, 0}; @@ -31007,6 +31044,7 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_std__invalid_argument, &_swigt__p_std__lessT_std__string_t, &_swigt__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t, + &_swigt__p_std__optionalT_double_t, &_swigt__p_std__pairT_double_double_t, &_swigt__p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t, &_swigt__p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t, @@ -31069,6 +31107,7 @@ static swig_cast_info _swigc__p_std__complexT_double_t[] = { {&_swigt__p_std__c static swig_cast_info _swigc__p_std__invalid_argument[] = { {&_swigt__p_std__invalid_argument, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__lessT_std__string_t[] = { {&_swigt__p_std__lessT_std__string_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t[] = { {&_swigt__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_std__optionalT_double_t[] = { {&_swigt__p_std__optionalT_double_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__pairT_double_double_t[] = { {&_swigt__p_std__pairT_double_double_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t[] = { {&_swigt__p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t[] = { {&_swigt__p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t, 0, 0, 0},{0, 0, 0, 0}}; @@ -31131,6 +31170,7 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_std__invalid_argument, _swigc__p_std__lessT_std__string_t, _swigc__p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t, + _swigc__p_std__optionalT_double_t, _swigc__p_std__pairT_double_double_t, _swigc__p_std__vectorT_IAxis_const_p_std__allocatorT_IAxis_const_p_t_t, _swigc__p_std__vectorT_IAxis_p_std__allocatorT_IAxis_p_t_t, -- GitLab