21#ifndef MATH_STANDALONE
34 static const char order[][4] = {
"XYZ",
"XZY",
"YXZ",
"YZX",
"ZXY",
"ZYX"};
42#ifdef __LITTLE_ENDIAN__
43# define MAKE_ID3(a, b, c) ((a) | ((b) << 8) | ((c) << 16))
45# define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8))
48 switch (*((
const PY_INT32_T *)
str)) {
66 PyErr_Format(PyExc_ValueError,
"%s: invalid euler order '%s'", error_prefix,
str);
87 PyTuple_SET_ITEM(
ret,
i, PyFloat_FromDouble(
self->eul[
i]));
100static PyObject *
Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
102 PyObject *seq =
nullptr;
103 const char *order_str =
nullptr;
108 if (kwds && PyDict_Size(kwds)) {
109 PyErr_SetString(PyExc_TypeError,
110 "mathutils.Euler(): "
111 "takes no keyword args");
115 if (!PyArg_ParseTuple(args,
"|Os:mathutils.Euler", &seq, &order_str)) {
119 switch (PyTuple_GET_SIZE(args)) {
144 Euler_to_quaternion_doc,
145 ".. method:: to_quaternion()\n"
147 " Return a quaternion representation of the euler.\n"
149 " :return: Quaternion representation of the euler.\n"
150 " :rtype: :class:`Quaternion`\n");
167 ".. method:: to_matrix()\n"
169 " Return a matrix representation of the euler.\n"
171 " :return: A 3x3 rotation matrix representation of the euler.\n"
172 " :rtype: :class:`Matrix`\n");
189 ".. method:: zero()\n"
191 " Set all values to zero.\n");
209 Euler_rotate_axis_doc,
210 ".. method:: rotate_axis(axis, angle)\n"
212 " Rotates the euler a certain amount and returning a unique euler rotation\n"
213 " (no 720 degree pitches).\n"
215 " :arg axis: single character in ['X, 'Y', 'Z'].\n"
217 " :arg angle: angle in radians.\n"
218 " :type angle: float\n");
224 if (!PyArg_ParseTuple(args,
"Cf:rotate_axis", &axis, &
angle)) {
225 PyErr_SetString(PyExc_TypeError,
226 "Euler.rotate_axis(): "
227 "expected an axis 'X', 'Y', 'Z' and an angle (float)");
231 if (!
ELEM(axis,
'X',
'Y',
'Z')) {
232 PyErr_SetString(PyExc_ValueError,
233 "Euler.rotate_axis(): "
234 "expected axis to be 'X', 'Y' or 'Z'");
252 ".. method:: rotate(other)\n"
254 " Rotates the euler by another mathutils value.\n"
256 " :arg other: rotation component of mathutils value\n"
257 " :type other: :class:`Euler` | :class:`Quaternion` | :class:`Matrix`\n");
260 float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
281 Euler_make_compatible_doc,
282 ".. method:: make_compatible(other)\n"
284 " Make this euler compatible with another,\n"
285 " so interpolating between them works as intended.\n"
287 " .. note:: the rotation order is not taken into account for this function.\n");
300 "euler.make_compatible(other), invalid 'other' arg") == -1)
315 ".. function:: copy()\n"
317 " Returns a copy of this euler.\n"
319 " :return: A copy of the euler.\n"
320 " :rtype: :class:`Euler`\n"
322 " .. note:: use this to get a copy of a wrapped euler with\n"
323 " no reference to the original data.\n");
348 PyObject *
ret, *tuple;
362#ifndef MATH_STANDALONE
374 "<Euler (x=%.4f, y=%.4f, z=%.4f), order='%s'>",
414 res = ok ? Py_False : Py_True;
421 res = Py_NotImplemented;
428 return Py_NewRef(res);
470 PyErr_SetString(PyExc_IndexError,
472 "array index out of range");
480 return PyFloat_FromDouble(
self->eul[
i]);
492 f = PyFloat_AsDouble(value);
493 if (f == -1 && PyErr_Occurred()) {
494 PyErr_SetString(PyExc_TypeError,
495 "euler[attribute] = x: "
496 "assigned value not a number");
505 PyErr_SetString(PyExc_IndexError,
506 "euler[attribute] = x: "
507 "array assignment index out of range");
537 tuple = PyTuple_New(end -
begin);
569 PyErr_SetString(PyExc_ValueError,
570 "euler[begin:end] = []: "
571 "size mismatch in slice assignment");
586 if (PyIndex_Check(item)) {
588 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
589 if (
i == -1 && PyErr_Occurred()) {
597 if (PySlice_Check(item)) {
598 Py_ssize_t start,
stop,
step, slicelength;
604 if (slicelength <= 0) {
605 return PyTuple_New(0);
611 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with eulers");
616 PyExc_TypeError,
"euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
623 if (PyIndex_Check(item)) {
624 Py_ssize_t
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
625 if (
i == -1 && PyErr_Occurred()) {
633 if (PySlice_Check(item)) {
634 Py_ssize_t start,
stop,
step, slicelength;
644 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with euler");
649 PyExc_TypeError,
"euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
689 "Euler axis angle in radians.\n"
707 "Euler rotation order.\n"
709 ":type: str in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']");
722 const char *order_str;
729 if (((order_str = PyUnicode_AsUTF8(value)) ==
nullptr) ||
772 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr}
783# pragma clang diagnostic push
784# pragma clang diagnostic ignored "-Wcast-function-type"
786# pragma GCC diagnostic push
787# pragma GCC diagnostic ignored "-Wcast-function-type"
792 {
"zero", (PyCFunction)
Euler_zero, METH_NOARGS, Euler_zero_doc},
793 {
"to_matrix", (PyCFunction)
Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
795 {
"rotate_axis", (PyCFunction)
Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
796 {
"rotate", (PyCFunction)
Euler_rotate, METH_O, Euler_rotate_doc},
798 {
"copy", (PyCFunction)
Euler_copy, METH_NOARGS, Euler_copy_doc},
799 {
"__copy__", (PyCFunction)
Euler_copy, METH_NOARGS, Euler_copy_doc},
800 {
"__deepcopy__", (PyCFunction)
Euler_deepcopy, METH_VARARGS, Euler_copy_doc},
804 {
nullptr,
nullptr, 0,
nullptr},
809# pragma clang diagnostic pop
811# pragma GCC diagnostic pop
821#ifdef MATH_STANDALONE
822# define Euler_str nullptr
828 ".. class:: Euler(angles, order='XYZ')\n"
830 " This object gives access to Eulers in Blender.\n"
832 " .. seealso:: `Euler angles <https://en.wikipedia.org/wiki/Euler_angles>`__ on Wikipedia.\n"
834 " :arg angles: (X, Y, Z) angles in radians.\n"
835 " :type angles: Sequence[float]\n"
836 " :arg order: Optional order of the angles, a permutation of ``XYZ``.\n"
837 " :type order: str\n");
839 PyVarObject_HEAD_INIT(
nullptr, 0)
858 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
890#ifdef MATH_STANDALONE
905 eul_alloc =
static_cast<float *
>(PyMem_Malloc(
EULER_SIZE *
sizeof(
float)));
906 if (
UNLIKELY(eul_alloc ==
nullptr)) {
907 PyErr_SetString(PyExc_MemoryError,
909 "problem allocating data");
915 self->eul = eul_alloc;
918 self->cb_user =
nullptr;
919 self->cb_type =
self->cb_subtype = 0;
932 PyMem_Free(eul_alloc);
935 return (PyObject *)
self;
945 self->cb_user =
nullptr;
946 self->cb_type =
self->cb_subtype = 0;
954 return (PyObject *)
self;
965 self->cb_user = cb_user;
966 self->cb_type = cb_type;
967 self->cb_subtype = cb_subtype;
969 PyObject_GC_Track(
self);
972 return (PyObject *)
self;
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
double double_round(double x, int ndigits)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void rotate_eulO(float beul[3], short order, char axis, float angle)
void eulO_to_quat(float q[4], const float e[3], short order)
void mat3_to_compatible_eulO(float eul[3], const float oldrot[3], short order, const float mat[3][3])
void compatible_eul(float eul[3], const float oldrot[3])
void eulO_to_mat3(float M[3][3], const float e[3], short order)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
VecBase< float, D > step(VecOp< float, D >, VecOp< float, D >) RET
int BaseMathObject_is_gc(BaseMathObject *self)
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
void BaseMathObject_dealloc(BaseMathObject *self)
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
int mathutils_array_parse(float *array, int array_num_min, int array_num_max, PyObject *value, const char *error_prefix)
char BaseMathObject_is_valid_doc[]
char BaseMathObject_is_wrapped_doc[]
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *)
char BaseMathObject_is_frozen_doc[]
PyObject * mathutils_dynstr_to_py(DynStr *ds)
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *)
PyObject * BaseMathObject_freeze(BaseMathObject *self)
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *)
char BaseMathObject_owner_doc[]
char BaseMathObject_freeze_doc[]
PyObject * BaseMathObject_is_valid_get(BaseMathObject *self, void *)
int BaseMathObject_clear(BaseMathObject *self)
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
#define BaseMath_ReadCallback_ForWrite(_self)
#define BaseMath_ReadIndexCallback(_self, _index)
#define BaseMath_WriteCallback(_self)
#define BASE_MATH_NEW(struct_name, root_type, base_type)
#define BaseMathObject_Prepare_ForHash(_self)
#define BASE_MATH_FLAG_DEFAULT
#define BaseMath_Prepare_ForWrite(_self)
#define BaseMath_ReadCallback(_self)
#define BaseMath_WriteIndexCallback(_self, _index)
static PyObject * Euler_copy(EulerObject *self)
static PyObject * Euler_to_tuple_ex(EulerObject *self, int ndigits)
static PySequenceMethods Euler_SeqMethods
static PyObject * Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
PyObject * Euler_CreatePyObject_wrap(float eul[3], const short order, PyTypeObject *base_type)
static PyObject * Euler_item(EulerObject *self, Py_ssize_t i)
static PyObject * Euler_zero(EulerObject *self)
short euler_order_from_string(const char *str, const char *error_prefix)
static PyObject * Euler_subscript(EulerObject *self, PyObject *item)
static PyObject * Euler_rotate(EulerObject *self, PyObject *value)
static const char * euler_order_str(EulerObject *self)
static Py_hash_t Euler_hash(EulerObject *self)
static PyObject * Euler_order_get(EulerObject *self, void *)
#define MAKE_ID3(a, b, c)
PyObject * Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type)
static int Euler_axis_set(EulerObject *self, PyObject *value, void *type)
static PyObject * Euler_repr(EulerObject *self)
static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
static int Euler_order_set(EulerObject *self, PyObject *value, void *)
static PyObject * Euler_str(EulerObject *self)
PyDoc_STRVAR(Euler_to_quaternion_doc, ".. method:: to_quaternion()\n" "\n" " Return a quaternion representation of the euler.\n" "\n" " :return: Quaternion representation of the euler.\n" " :rtype: :class:`Quaternion`\n")
static PyObject * Euler_richcmpr(PyObject *a, PyObject *b, int op)
static PyObject * Euler_deepcopy(EulerObject *self, PyObject *args)
static PyObject * Euler_make_compatible(EulerObject *self, PyObject *value)
static PyGetSetDef Euler_getseters[]
static Py_ssize_t Euler_len(EulerObject *)
static int Euler_ass_item(EulerObject *self, Py_ssize_t i, PyObject *value)
static PyObject * Euler_rotate_axis(EulerObject *self, PyObject *args)
static PyMappingMethods Euler_AsMapping
static PyObject * Euler_axis_get(EulerObject *self, void *type)
PyObject * Euler_CreatePyObject_cb(PyObject *cb_user, const short order, uchar cb_type, uchar cb_subtype)
static PyObject * Euler_slice(EulerObject *self, int begin, int end)
static PyMethodDef Euler_methods[]
static PyObject * Euler_to_matrix(EulerObject *self)
static PyObject * Euler_to_quaternion(EulerObject *self)
#define EulerObject_Check(v)
PyObject * Matrix_CreatePyObject(const float *mat, const ushort col_num, const ushort row_num, PyTypeObject *base_type)
PyObject * Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type)
int PyC_CheckArgs_DeepCopy(PyObject *args)