21#ifndef MATH_STANDALONE
34 static const char order[][4] = {
"XYZ",
"XZY",
"YXZ",
"YZX",
"ZXY",
"ZYX"};
43#define MAKE_ID3(a, b, c) ((a) | ((b) << 8) | ((c) << 16))
45 switch (*((
const PY_INT32_T *)
str)) {
69 PyErr_Format(PyExc_ValueError,
"%s: invalid euler order '%s'", error_prefix,
str);
90 PyTuple_SET_ITEM(
ret,
i, PyFloat_FromDouble(
self->eul[
i]));
104 PyObject *
const *args,
108 if (
UNLIKELY(kwnames && PyTuple_GET_SIZE(kwnames))) {
109 PyErr_SetString(PyExc_TypeError,
110 "mathutils.Euler(): "
111 "takes no keyword args");
118 const size_t nargs = PyVectorcall_NARGS(nargsf);
124 const char *order_str;
126 if (((order_str = PyUnicode_AsUTF8(args[1])) ==
nullptr) ||
140 PyErr_Format(PyExc_TypeError,
141 "mathutils.Euler(): "
142 "takes at most 2 arguments (%zd given)",
150static PyObject *
Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
153 if (
UNLIKELY(kwds && PyDict_GET_SIZE(kwds))) {
154 PyErr_SetString(PyExc_TypeError,
155 "mathutils.Euler(): "
156 "takes no keyword args");
159 PyObject *
const *args_array = &PyTuple_GET_ITEM(args, 0);
160 const size_t args_array_num = PyTuple_GET_SIZE(args);
161 return Euler_vectorcall(
reinterpret_cast<PyObject *
>(type), args_array, args_array_num,
nullptr);
172 Euler_to_quaternion_doc,
173 ".. method:: to_quaternion()\n"
175 " Return a quaternion representation of the euler.\n"
177 " :return: Quaternion representation of the euler.\n"
178 " :rtype: :class:`Quaternion`\n");
195 ".. method:: to_matrix()\n"
197 " Return a matrix representation of the euler.\n"
199 " :return: A 3x3 rotation matrix representation of the euler.\n"
200 " :rtype: :class:`Matrix`\n");
217 ".. method:: zero()\n"
219 " Set all values to zero.\n");
237 Euler_rotate_axis_doc,
238 ".. method:: rotate_axis(axis, angle, /)\n"
240 " Rotates the euler a certain amount and returning a unique euler rotation\n"
241 " (no 720 degree pitches).\n"
243 " :arg axis: An axis string.\n"
244 " :type axis: Literal['X', 'Y', 'Z']\n"
245 " :arg angle: angle in radians.\n"
246 " :type angle: float\n");
252 if (!PyArg_ParseTuple(args,
"Cf:rotate_axis", &axis, &
angle)) {
253 PyErr_SetString(PyExc_TypeError,
254 "Euler.rotate_axis(): "
255 "expected an axis 'X', 'Y', 'Z' and an angle (float)");
259 if (!
ELEM(axis,
'X',
'Y',
'Z')) {
260 PyErr_SetString(PyExc_ValueError,
261 "Euler.rotate_axis(): "
262 "expected axis to be 'X', 'Y' or 'Z'");
280 ".. method:: rotate(other, /)\n"
282 " Rotates the euler by another mathutils value.\n"
284 " :arg other: rotation component of mathutils value\n"
285 " :type other: :class:`Euler` | :class:`Quaternion` | :class:`Matrix`\n");
288 float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
309 Euler_make_compatible_doc,
310 ".. method:: make_compatible(other, /)\n"
312 " Make this euler compatible with another,\n"
313 " so interpolating between them works as intended.\n"
315 " :arg other: Other euler rotation.\n"
316 " :type other: :class:`Euler`\n"
318 " .. note:: the rotation order is not taken into account for this function.\n");
331 "euler.make_compatible(other), invalid 'other' arg") == -1)
346 ".. function:: copy()\n"
348 " Returns a copy of this euler.\n"
350 " :return: A copy of the euler.\n"
351 " :rtype: :class:`Euler`\n"
353 " .. note:: use this to get a copy of a wrapped euler with\n"
354 " no reference to the original data.\n");
379 PyObject *
ret, *tuple;
393#ifndef MATH_STANDALONE
405 "<Euler (x=%.4f, y=%.4f, z=%.4f), order='%s'>",
438 if ((flags & PyBUF_WRITABLE) == 0) {
441 if (flags & PyBUF_FORMAT) {
442 view->format = (
char *)
"f";
456 if (
view->readonly == 0) {
499 res = ok ? Py_False : Py_True;
506 res = Py_NotImplemented;
515 return Py_NewRef(res);
557 PyErr_SetString(PyExc_IndexError,
559 "array index out of range");
567 return PyFloat_FromDouble(
self->eul[
i]);
579 f = PyFloat_AsDouble(value);
580 if (f == -1 && PyErr_Occurred()) {
581 PyErr_SetString(PyExc_TypeError,
582 "euler[attribute] = x: "
583 "assigned value not a number");
592 PyErr_SetString(PyExc_IndexError,
593 "euler[attribute] = x: "
594 "array assignment index out of range");
624 tuple = PyTuple_New(end -
begin);
656 PyErr_SetString(PyExc_ValueError,
657 "euler[begin:end] = []: "
658 "size mismatch in slice assignment");
673 if (PyIndex_Check(item)) {
675 i = PyNumber_AsSsize_t(item, PyExc_IndexError);
676 if (
i == -1 && PyErr_Occurred()) {
684 if (PySlice_Check(item)) {
685 Py_ssize_t start, stop,
step, slicelength;
687 if (PySlice_GetIndicesEx(item,
EULER_SIZE, &start, &stop, &
step, &slicelength) < 0) {
691 if (slicelength <= 0) {
692 return PyTuple_New(0);
698 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with eulers");
703 PyExc_TypeError,
"euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
710 if (PyIndex_Check(item)) {
711 Py_ssize_t
i = PyNumber_AsSsize_t(item, PyExc_IndexError);
712 if (
i == -1 && PyErr_Occurred()) {
720 if (PySlice_Check(item)) {
721 Py_ssize_t start, stop,
step, slicelength;
723 if (PySlice_GetIndicesEx(item,
EULER_SIZE, &start, &stop, &
step, &slicelength) < 0) {
731 PyErr_SetString(PyExc_IndexError,
"slice steps not supported with euler");
736 PyExc_TypeError,
"euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
776 "Euler axis angle in radians.\n"
794 "Euler rotation order.\n"
796 ":type: Literal['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']\n");
809 const char *order_str;
816 if (((order_str = PyUnicode_AsUTF8(value)) ==
nullptr) ||
859 {
nullptr,
nullptr,
nullptr,
nullptr,
nullptr} };
869# pragma clang diagnostic push
870# pragma clang diagnostic ignored "-Wcast-function-type"
872# pragma GCC diagnostic push
873# pragma GCC diagnostic ignored "-Wcast-function-type"
878 {
"zero", (PyCFunction)
Euler_zero, METH_NOARGS, Euler_zero_doc},
879 {
"to_matrix", (PyCFunction)
Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
881 {
"rotate_axis", (PyCFunction)
Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
882 {
"rotate", (PyCFunction)
Euler_rotate, METH_O, Euler_rotate_doc},
884 {
"copy", (PyCFunction)
Euler_copy, METH_NOARGS, Euler_copy_doc},
885 {
"__copy__", (PyCFunction)
Euler_copy, METH_NOARGS, Euler_copy_doc},
886 {
"__deepcopy__", (PyCFunction)
Euler_deepcopy, METH_VARARGS, Euler_copy_doc},
890 {
nullptr,
nullptr, 0,
nullptr},
895# pragma clang diagnostic pop
897# pragma GCC diagnostic pop
907#ifdef MATH_STANDALONE
908# define Euler_str nullptr
914 ".. class:: Euler(angles=(0.0, 0.0, 0.0), order='XYZ', /)\n"
916 " This object gives access to Eulers in Blender.\n"
918 " .. seealso:: `Euler angles <https://en.wikipedia.org/wiki/Euler_angles>`__ on "
921 " :arg angles: (X, Y, Z) angles in radians.\n"
922 " :type angles: Sequence[float]\n"
923 " :arg order: Euler rotation order.\n"
924 " :type order: Literal['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']\n");
926 PyVarObject_HEAD_INIT(
nullptr, 0)
945 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
977#ifdef MATH_STANDALONE
992 eul_alloc =
static_cast<float *
>(PyMem_Malloc(
EULER_SIZE *
sizeof(
float)));
993 if (
UNLIKELY(eul_alloc ==
nullptr)) {
994 PyErr_SetString(PyExc_MemoryError,
996 "problem allocating data");
1002 self->eul = eul_alloc;
1005 self->cb_user =
nullptr;
1006 self->cb_type =
self->cb_subtype = 0;
1016 self->order = order;
1019 PyMem_Free(eul_alloc);
1022 return (PyObject *)
self;
1032 self->cb_user =
nullptr;
1033 self->cb_type =
self->cb_subtype = 0;
1038 self->order = order;
1041 return (PyObject *)
self;
1052 self->cb_user = cb_user;
1053 self->cb_type = cb_type;
1054 self->cb_subtype = cb_subtype;
1056 PyObject_GC_Track(
self);
1059 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_Prepare_ForBufferAccess(_self, _view, _flags)
#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)
@ BASE_MATH_FLAG_HAS_BUFFER_VIEW
#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 int Euler_getbuffer(PyObject *obj, Py_buffer *view, int flags)
static PyObject * Euler_vectorcall(PyObject *type, PyObject *const *args, const size_t nargsf, PyObject *kwnames)
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 PyBufferProcs Euler_as_buffer
static void Euler_releasebuffer(PyObject *, Py_buffer *view)
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)