Blender  V2.93
mathutils_Euler.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include <Python.h>
22 
23 #include "mathutils.h"
24 
25 #include "../generic/py_capi_utils.h"
26 #include "../generic/python_utildefines.h"
27 #include "BLI_math.h"
28 #include "BLI_utildefines.h"
29 
30 #ifndef MATH_STANDALONE
31 # include "BLI_dynstr.h"
32 #endif
33 
34 #define EULER_SIZE 3
35 
36 /* ----------------------------------mathutils.Euler() ------------------- */
37 /* makes a new euler for you to play with */
38 static PyObject *Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
39 {
40  PyObject *seq = NULL;
41  const char *order_str = NULL;
42 
43  float eul[EULER_SIZE] = {0.0f, 0.0f, 0.0f};
44  short order = EULER_ORDER_XYZ;
45 
46  if (kwds && PyDict_Size(kwds)) {
47  PyErr_SetString(PyExc_TypeError,
48  "mathutils.Euler(): "
49  "takes no keyword args");
50  return NULL;
51  }
52 
53  if (!PyArg_ParseTuple(args, "|Os:mathutils.Euler", &seq, &order_str)) {
54  return NULL;
55  }
56 
57  switch (PyTuple_GET_SIZE(args)) {
58  case 0:
59  break;
60  case 2:
61  if ((order = euler_order_from_string(order_str, "mathutils.Euler()")) == -1) {
62  return NULL;
63  }
65  case 1:
66  if (mathutils_array_parse(eul, EULER_SIZE, EULER_SIZE, seq, "mathutils.Euler()") == -1) {
67  return NULL;
68  }
69  break;
70  }
71  return Euler_CreatePyObject(eul, order, type);
72 }
73 
74 /* internal use, assume read callback is done */
75 static const char *euler_order_str(EulerObject *self)
76 {
77  static const char order[][4] = {"XYZ", "XZY", "YXZ", "YZX", "ZXY", "ZYX"};
78  return order[self->order - EULER_ORDER_XYZ];
79 }
80 
81 short euler_order_from_string(const char *str, const char *error_prefix)
82 {
83  if ((str[0] && str[1] && str[2] && str[3] == '\0')) {
84 
85 #ifdef __LITTLE_ENDIAN__
86 # define MAKE_ID3(a, b, c) (((a)) | ((b) << 8) | ((c) << 16))
87 #else
88 # define MAKE_ID3(a, b, c) (((a) << 24) | ((b) << 16) | ((c) << 8))
89 #endif
90 
91  switch (*((PY_INT32_T *)str)) {
92  case MAKE_ID3('X', 'Y', 'Z'):
93  return EULER_ORDER_XYZ;
94  case MAKE_ID3('X', 'Z', 'Y'):
95  return EULER_ORDER_XZY;
96  case MAKE_ID3('Y', 'X', 'Z'):
97  return EULER_ORDER_YXZ;
98  case MAKE_ID3('Y', 'Z', 'X'):
99  return EULER_ORDER_YZX;
100  case MAKE_ID3('Z', 'X', 'Y'):
101  return EULER_ORDER_ZXY;
102  case MAKE_ID3('Z', 'Y', 'X'):
103  return EULER_ORDER_ZYX;
104  }
105 
106 #undef MAKE_ID3
107  }
108 
109  PyErr_Format(PyExc_ValueError, "%s: invalid euler order '%s'", error_prefix, str);
110  return -1;
111 }
112 
113 /* note: BaseMath_ReadCallback must be called beforehand */
114 static PyObject *Euler_ToTupleExt(EulerObject *self, int ndigits)
115 {
116  PyObject *ret;
117  int i;
118 
119  ret = PyTuple_New(EULER_SIZE);
120 
121  if (ndigits >= 0) {
122  for (i = 0; i < EULER_SIZE; i++) {
123  PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(double_round((double)self->eul[i], ndigits)));
124  }
125  }
126  else {
127  for (i = 0; i < EULER_SIZE; i++) {
128  PyTuple_SET_ITEM(ret, i, PyFloat_FromDouble(self->eul[i]));
129  }
130  }
131 
132  return ret;
133 }
134 
135 /* -----------------------------METHODS----------------------------
136  * return a quaternion representation of the euler */
137 
138 PyDoc_STRVAR(Euler_to_quaternion_doc,
139  ".. method:: to_quaternion()\n"
140  "\n"
141  " Return a quaternion representation of the euler.\n"
142  "\n"
143  " :return: Quaternion representation of the euler.\n"
144  " :rtype: :class:`Quaternion`\n");
145 static PyObject *Euler_to_quaternion(EulerObject *self)
146 {
147  float quat[4];
148 
149  if (BaseMath_ReadCallback(self) == -1) {
150  return NULL;
151  }
152 
153  eulO_to_quat(quat, self->eul, self->order);
154 
155  return Quaternion_CreatePyObject(quat, NULL);
156 }
157 
158 /* return a matrix representation of the euler */
159 PyDoc_STRVAR(Euler_to_matrix_doc,
160  ".. method:: to_matrix()\n"
161  "\n"
162  " Return a matrix representation of the euler.\n"
163  "\n"
164  " :return: A 3x3 rotation matrix representation of the euler.\n"
165  " :rtype: :class:`Matrix`\n");
166 static PyObject *Euler_to_matrix(EulerObject *self)
167 {
168  float mat[9];
169 
170  if (BaseMath_ReadCallback(self) == -1) {
171  return NULL;
172  }
173 
174  eulO_to_mat3((float(*)[3])mat, self->eul, self->order);
175 
176  return Matrix_CreatePyObject(mat, 3, 3, NULL);
177 }
178 
179 PyDoc_STRVAR(Euler_zero_doc,
180  ".. method:: zero()\n"
181  "\n"
182  " Set all values to zero.\n");
183 static PyObject *Euler_zero(EulerObject *self)
184 {
185  if (BaseMath_Prepare_ForWrite(self) == -1) {
186  return NULL;
187  }
188 
189  zero_v3(self->eul);
190 
191  if (BaseMath_WriteCallback(self) == -1) {
192  return NULL;
193  }
194 
195  Py_RETURN_NONE;
196 }
197 
198 PyDoc_STRVAR(Euler_rotate_axis_doc,
199  ".. method:: rotate_axis(axis, angle)\n"
200  "\n"
201  " Rotates the euler a certain amount and returning a unique euler rotation\n"
202  " (no 720 degree pitches).\n"
203  "\n"
204  " :arg axis: single character in ['X, 'Y', 'Z'].\n"
205  " :type axis: string\n"
206  " :arg angle: angle in radians.\n"
207  " :type angle: float\n");
208 static PyObject *Euler_rotate_axis(EulerObject *self, PyObject *args)
209 {
210  float angle = 0.0f;
211  int axis; /* actually a character */
212 
213  if (!PyArg_ParseTuple(args, "Cf:rotate_axis", &axis, &angle)) {
214  PyErr_SetString(PyExc_TypeError,
215  "Euler.rotate_axis(): "
216  "expected an axis 'X', 'Y', 'Z' and an angle (float)");
217  return NULL;
218  }
219 
220  if (!(ELEM(axis, 'X', 'Y', 'Z'))) {
221  PyErr_SetString(PyExc_ValueError,
222  "Euler.rotate_axis(): "
223  "expected axis to be 'X', 'Y' or 'Z'");
224  return NULL;
225  }
226 
227  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
228  return NULL;
229  }
230 
231  rotate_eulO(self->eul, self->order, (char)axis, angle);
232 
233  (void)BaseMath_WriteCallback(self);
234 
235  Py_RETURN_NONE;
236 }
237 
238 PyDoc_STRVAR(Euler_rotate_doc,
239  ".. method:: rotate(other)\n"
240  "\n"
241  " Rotates the euler by another mathutils value.\n"
242  "\n"
243  " :arg other: rotation component of mathutils value\n"
244  " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n");
245 static PyObject *Euler_rotate(EulerObject *self, PyObject *value)
246 {
247  float self_rmat[3][3], other_rmat[3][3], rmat[3][3];
248 
249  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
250  return NULL;
251  }
252 
253  if (mathutils_any_to_rotmat(other_rmat, value, "euler.rotate(value)") == -1) {
254  return NULL;
255  }
256 
257  eulO_to_mat3(self_rmat, self->eul, self->order);
258  mul_m3_m3m3(rmat, other_rmat, self_rmat);
259 
260  mat3_to_compatible_eulO(self->eul, self->eul, self->order, rmat);
261 
262  (void)BaseMath_WriteCallback(self);
263  Py_RETURN_NONE;
264 }
265 
266 PyDoc_STRVAR(Euler_make_compatible_doc,
267  ".. method:: make_compatible(other)\n"
268  "\n"
269  " Make this euler compatible with another,\n"
270  " so interpolating between them works as intended.\n"
271  "\n"
272  " .. note:: the rotation order is not taken into account for this function.\n");
273 static PyObject *Euler_make_compatible(EulerObject *self, PyObject *value)
274 {
275  float teul[EULER_SIZE];
276 
277  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
278  return NULL;
279  }
280 
281  if (mathutils_array_parse(teul,
282  EULER_SIZE,
283  EULER_SIZE,
284  value,
285  "euler.make_compatible(other), invalid 'other' arg") == -1) {
286  return NULL;
287  }
288 
289  compatible_eul(self->eul, teul);
290 
291  (void)BaseMath_WriteCallback(self);
292 
293  Py_RETURN_NONE;
294 }
295 
296 /* ----------------------------Euler.rotate()-----------------------
297  * return a copy of the euler */
298 
299 PyDoc_STRVAR(Euler_copy_doc,
300  ".. function:: copy()\n"
301  "\n"
302  " Returns a copy of this euler.\n"
303  "\n"
304  " :return: A copy of the euler.\n"
305  " :rtype: :class:`Euler`\n"
306  "\n"
307  " .. note:: use this to get a copy of a wrapped euler with\n"
308  " no reference to the original data.\n");
309 static PyObject *Euler_copy(EulerObject *self)
310 {
311  if (BaseMath_ReadCallback(self) == -1) {
312  return NULL;
313  }
314 
315  return Euler_CreatePyObject(self->eul, self->order, Py_TYPE(self));
316 }
317 static PyObject *Euler_deepcopy(EulerObject *self, PyObject *args)
318 {
319  if (!PyC_CheckArgs_DeepCopy(args)) {
320  return NULL;
321  }
322  return Euler_copy(self);
323 }
324 
325 /* ----------------------------print object (internal)--------------
326  * print the object to screen */
327 
328 static PyObject *Euler_repr(EulerObject *self)
329 {
330  PyObject *ret, *tuple;
331 
332  if (BaseMath_ReadCallback(self) == -1) {
333  return NULL;
334  }
335 
336  tuple = Euler_ToTupleExt(self, -1);
337 
338  ret = PyUnicode_FromFormat("Euler(%R, '%s')", tuple, euler_order_str(self));
339 
340  Py_DECREF(tuple);
341  return ret;
342 }
343 
344 #ifndef MATH_STANDALONE
345 static PyObject *Euler_str(EulerObject *self)
346 {
347  DynStr *ds;
348 
349  if (BaseMath_ReadCallback(self) == -1) {
350  return NULL;
351  }
352 
353  ds = BLI_dynstr_new();
354 
356  "<Euler (x=%.4f, y=%.4f, z=%.4f), order='%s'>",
357  self->eul[0],
358  self->eul[1],
359  self->eul[2],
360  euler_order_str(self));
361 
362  return mathutils_dynstr_to_py(ds); /* frees ds */
363 }
364 #endif
365 
366 static PyObject *Euler_richcmpr(PyObject *a, PyObject *b, int op)
367 {
368  PyObject *res;
369  int ok = -1; /* zero is true */
370 
372  EulerObject *eulA = (EulerObject *)a;
373  EulerObject *eulB = (EulerObject *)b;
374 
375  if (BaseMath_ReadCallback(eulA) == -1 || BaseMath_ReadCallback(eulB) == -1) {
376  return NULL;
377  }
378 
379  ok = ((eulA->order == eulB->order) &&
380  EXPP_VectorsAreEqual(eulA->eul, eulB->eul, EULER_SIZE, 1)) ?
381  0 :
382  -1;
383  }
384 
385  switch (op) {
386  case Py_NE:
387  ok = !ok;
389  case Py_EQ:
390  res = ok ? Py_False : Py_True;
391  break;
392 
393  case Py_LT:
394  case Py_LE:
395  case Py_GT:
396  case Py_GE:
397  res = Py_NotImplemented;
398  break;
399  default:
400  PyErr_BadArgument();
401  return NULL;
402  }
403 
404  return Py_INCREF_RET(res);
405 }
406 
407 static Py_hash_t Euler_hash(EulerObject *self)
408 {
409  if (BaseMath_ReadCallback(self) == -1) {
410  return -1;
411  }
412 
413  if (BaseMathObject_Prepare_ForHash(self) == -1) {
414  return -1;
415  }
416 
417  return mathutils_array_hash(self->eul, EULER_SIZE);
418 }
419 
420 /* ---------------------SEQUENCE PROTOCOLS------------------------ */
421 /* ----------------------------len(object)------------------------ */
422 /* sequence length */
423 static int Euler_len(EulerObject *UNUSED(self))
424 {
425  return EULER_SIZE;
426 }
427 /* ----------------------------object[]--------------------------- */
428 /* sequence accessor (get) */
429 static PyObject *Euler_item(EulerObject *self, int i)
430 {
431  if (i < 0) {
432  i = EULER_SIZE - i;
433  }
434 
435  if (i < 0 || i >= EULER_SIZE) {
436  PyErr_SetString(PyExc_IndexError,
437  "euler[attribute]: "
438  "array index out of range");
439  return NULL;
440  }
441 
442  if (BaseMath_ReadIndexCallback(self, i) == -1) {
443  return NULL;
444  }
445 
446  return PyFloat_FromDouble(self->eul[i]);
447 }
448 /* ----------------------------object[]------------------------- */
449 /* sequence accessor (set) */
450 static int Euler_ass_item(EulerObject *self, int i, PyObject *value)
451 {
452  float f;
453 
454  if (BaseMath_Prepare_ForWrite(self) == -1) {
455  return -1;
456  }
457 
458  f = PyFloat_AsDouble(value);
459  if (f == -1 && PyErr_Occurred()) { /* parsed item not a number */
460  PyErr_SetString(PyExc_TypeError,
461  "euler[attribute] = x: "
462  "assigned value not a number");
463  return -1;
464  }
465 
466  if (i < 0) {
467  i = EULER_SIZE - i;
468  }
469 
470  if (i < 0 || i >= EULER_SIZE) {
471  PyErr_SetString(PyExc_IndexError,
472  "euler[attribute] = x: "
473  "array assignment index out of range");
474  return -1;
475  }
476 
477  self->eul[i] = f;
478 
479  if (BaseMath_WriteIndexCallback(self, i) == -1) {
480  return -1;
481  }
482 
483  return 0;
484 }
485 /* ----------------------------object[z:y]------------------------ */
486 /* sequence slice (get) */
487 static PyObject *Euler_slice(EulerObject *self, int begin, int end)
488 {
489  PyObject *tuple;
490  int count;
491 
492  if (BaseMath_ReadCallback(self) == -1) {
493  return NULL;
494  }
495 
496  CLAMP(begin, 0, EULER_SIZE);
497  if (end < 0) {
498  end = (EULER_SIZE + 1) + end;
499  }
500  CLAMP(end, 0, EULER_SIZE);
501  begin = MIN2(begin, end);
502 
503  tuple = PyTuple_New(end - begin);
504  for (count = begin; count < end; count++) {
505  PyTuple_SET_ITEM(tuple, count - begin, PyFloat_FromDouble(self->eul[count]));
506  }
507 
508  return tuple;
509 }
510 /* ----------------------------object[z:y]------------------------ */
511 /* sequence slice (set) */
512 static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
513 {
514  int i, size;
515  float eul[EULER_SIZE];
516 
517  if (BaseMath_ReadCallback_ForWrite(self) == -1) {
518  return -1;
519  }
520 
521  CLAMP(begin, 0, EULER_SIZE);
522  if (end < 0) {
523  end = (EULER_SIZE + 1) + end;
524  }
525  CLAMP(end, 0, EULER_SIZE);
526  begin = MIN2(begin, end);
527 
528  if ((size = mathutils_array_parse(eul, 0, EULER_SIZE, seq, "mathutils.Euler[begin:end] = []")) ==
529  -1) {
530  return -1;
531  }
532 
533  if (size != (end - begin)) {
534  PyErr_SetString(PyExc_ValueError,
535  "euler[begin:end] = []: "
536  "size mismatch in slice assignment");
537  return -1;
538  }
539 
540  for (i = 0; i < EULER_SIZE; i++) {
541  self->eul[begin + i] = eul[i];
542  }
543 
544  (void)BaseMath_WriteCallback(self);
545  return 0;
546 }
547 
548 static PyObject *Euler_subscript(EulerObject *self, PyObject *item)
549 {
550  if (PyIndex_Check(item)) {
551  Py_ssize_t i;
552  i = PyNumber_AsSsize_t(item, PyExc_IndexError);
553  if (i == -1 && PyErr_Occurred()) {
554  return NULL;
555  }
556  if (i < 0) {
557  i += EULER_SIZE;
558  }
559  return Euler_item(self, i);
560  }
561  if (PySlice_Check(item)) {
562  Py_ssize_t start, stop, step, slicelength;
563 
564  if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) {
565  return NULL;
566  }
567 
568  if (slicelength <= 0) {
569  return PyTuple_New(0);
570  }
571  if (step == 1) {
572  return Euler_slice(self, start, stop);
573  }
574 
575  PyErr_SetString(PyExc_IndexError, "slice steps not supported with eulers");
576  return NULL;
577  }
578 
579  PyErr_Format(
580  PyExc_TypeError, "euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
581  return NULL;
582 }
583 
584 static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
585 {
586  if (PyIndex_Check(item)) {
587  Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
588  if (i == -1 && PyErr_Occurred()) {
589  return -1;
590  }
591  if (i < 0) {
592  i += EULER_SIZE;
593  }
594  return Euler_ass_item(self, i, value);
595  }
596  if (PySlice_Check(item)) {
597  Py_ssize_t start, stop, step, slicelength;
598 
599  if (PySlice_GetIndicesEx(item, EULER_SIZE, &start, &stop, &step, &slicelength) < 0) {
600  return -1;
601  }
602 
603  if (step == 1) {
604  return Euler_ass_slice(self, start, stop, value);
605  }
606 
607  PyErr_SetString(PyExc_IndexError, "slice steps not supported with euler");
608  return -1;
609  }
610 
611  PyErr_Format(
612  PyExc_TypeError, "euler indices must be integers, not %.200s", Py_TYPE(item)->tp_name);
613  return -1;
614 }
615 
616 /* -----------------PROTCOL DECLARATIONS-------------------------- */
617 static PySequenceMethods Euler_SeqMethods = {
618  (lenfunc)Euler_len, /* sq_length */
619  (binaryfunc)NULL, /* sq_concat */
620  (ssizeargfunc)NULL, /* sq_repeat */
621  (ssizeargfunc)Euler_item, /* sq_item */
622  (ssizessizeargfunc)NULL, /* sq_slice, deprecated */
623  (ssizeobjargproc)Euler_ass_item, /* sq_ass_item */
624  (ssizessizeobjargproc)NULL, /* sq_ass_slice, deprecated */
625  (objobjproc)NULL, /* sq_contains */
626  (binaryfunc)NULL, /* sq_inplace_concat */
627  (ssizeargfunc)NULL, /* sq_inplace_repeat */
628 };
629 
630 static PyMappingMethods Euler_AsMapping = {
631  (lenfunc)Euler_len,
632  (binaryfunc)Euler_subscript,
633  (objobjargproc)Euler_ass_subscript,
634 };
635 
636 /* euler axis, euler.x/y/z */
637 
638 PyDoc_STRVAR(Euler_axis_doc, "Euler axis angle in radians.\n\n:type: float");
639 static PyObject *Euler_axis_get(EulerObject *self, void *type)
640 {
641  return Euler_item(self, POINTER_AS_INT(type));
642 }
643 
644 static int Euler_axis_set(EulerObject *self, PyObject *value, void *type)
645 {
646  return Euler_ass_item(self, POINTER_AS_INT(type), value);
647 }
648 
649 /* rotation order */
650 
652  Euler_order_doc,
653  "Euler rotation order.\n\n:type: string in ['XYZ', 'XZY', 'YXZ', 'YZX', 'ZXY', 'ZYX']");
654 static PyObject *Euler_order_get(EulerObject *self, void *UNUSED(closure))
655 {
656  if (BaseMath_ReadCallback(self) == -1) {
657  /* can read order too */
658  return NULL;
659  }
660 
661  return PyUnicode_FromString(euler_order_str(self));
662 }
663 
664 static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(closure))
665 {
666  const char *order_str;
667  short order;
668 
669  if (BaseMath_Prepare_ForWrite(self) == -1) {
670  return -1;
671  }
672 
673  if (((order_str = PyUnicode_AsUTF8(value)) == NULL) ||
674  ((order = euler_order_from_string(order_str, "euler.order")) == -1)) {
675  return -1;
676  }
677 
678  self->order = order;
679  (void)BaseMath_WriteCallback(self); /* order can be written back */
680  return 0;
681 }
682 
683 /*****************************************************************************/
684 /* Python attributes get/set structure: */
685 /*****************************************************************************/
686 static PyGetSetDef Euler_getseters[] = {
687  {"x", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)0},
688  {"y", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)1},
689  {"z", (getter)Euler_axis_get, (setter)Euler_axis_set, Euler_axis_doc, (void *)2},
690  {"order", (getter)Euler_order_get, (setter)Euler_order_set, Euler_order_doc, (void *)NULL},
691 
692  {"is_wrapped",
694  (setter)NULL,
696  NULL},
697  {"is_frozen",
699  (setter)NULL,
701  NULL},
702  {"owner", (getter)BaseMathObject_owner_get, (setter)NULL, BaseMathObject_owner_doc, NULL},
703  {NULL, NULL, NULL, NULL, NULL} /* Sentinel */
704 };
705 
706 /* -----------------------METHOD DEFINITIONS ---------------------- */
707 static struct PyMethodDef Euler_methods[] = {
708  {"zero", (PyCFunction)Euler_zero, METH_NOARGS, Euler_zero_doc},
709  {"to_matrix", (PyCFunction)Euler_to_matrix, METH_NOARGS, Euler_to_matrix_doc},
710  {"to_quaternion", (PyCFunction)Euler_to_quaternion, METH_NOARGS, Euler_to_quaternion_doc},
711  {"rotate_axis", (PyCFunction)Euler_rotate_axis, METH_VARARGS, Euler_rotate_axis_doc},
712  {"rotate", (PyCFunction)Euler_rotate, METH_O, Euler_rotate_doc},
713  {"make_compatible", (PyCFunction)Euler_make_compatible, METH_O, Euler_make_compatible_doc},
714  {"copy", (PyCFunction)Euler_copy, METH_NOARGS, Euler_copy_doc},
715  {"__copy__", (PyCFunction)Euler_copy, METH_NOARGS, Euler_copy_doc},
716  {"__deepcopy__", (PyCFunction)Euler_deepcopy, METH_VARARGS, Euler_copy_doc},
717 
718  /* base-math methods */
719  {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc},
720  {NULL, NULL, 0, NULL},
721 };
722 
723 /* ------------------PY_OBECT DEFINITION-------------------------- */
725  euler_doc,
726  ".. class:: Euler(angles, order='XYZ')\n"
727  "\n"
728  " This object gives access to Eulers in Blender.\n"
729  "\n"
730  " .. seealso:: `Euler angles <https://en.wikipedia.org/wiki/Euler_angles>`__ on Wikipedia.\n"
731  "\n"
732  " :param angles: Three angles, in radians.\n"
733  " :type angles: 3d vector\n"
734  " :param order: Optional order of the angles, a permutation of ``XYZ``.\n"
735  " :type order: str\n");
736 PyTypeObject euler_Type = {
737  PyVarObject_HEAD_INIT(NULL, 0) "Euler", /* tp_name */
738  sizeof(EulerObject), /* tp_basicsize */
739  0, /* tp_itemsize */
740  (destructor)BaseMathObject_dealloc, /* tp_dealloc */
741  (printfunc)NULL, /* tp_print */
742  NULL, /* tp_getattr */
743  NULL, /* tp_setattr */
744  NULL, /* tp_compare */
745  (reprfunc)Euler_repr, /* tp_repr */
746  NULL, /* tp_as_number */
747  &Euler_SeqMethods, /* tp_as_sequence */
748  &Euler_AsMapping, /* tp_as_mapping */
749  (hashfunc)Euler_hash, /* tp_hash */
750  NULL, /* tp_call */
751 #ifndef MATH_STANDALONE
752  (reprfunc)Euler_str, /* tp_str */
753 #else
754  NULL, /* tp_str */
755 #endif
756  NULL, /* tp_getattro */
757  NULL, /* tp_setattro */
758  NULL, /* tp_as_buffer */
759  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /* tp_flags */
760  euler_doc, /* tp_doc */
761  (traverseproc)BaseMathObject_traverse, /* tp_traverse */
762  (inquiry)BaseMathObject_clear, /* tp_clear */
763  (richcmpfunc)Euler_richcmpr, /* tp_richcompare */
764  0, /* tp_weaklistoffset */
765  NULL, /* tp_iter */
766  NULL, /* tp_iternext */
767  Euler_methods, /* tp_methods */
768  NULL, /* tp_members */
769  Euler_getseters, /* tp_getset */
770  NULL, /* tp_base */
771  NULL, /* tp_dict */
772  NULL, /* tp_descr_get */
773  NULL, /* tp_descr_set */
774  0, /* tp_dictoffset */
775  NULL, /* tp_init */
776  NULL, /* tp_alloc */
777  Euler_new, /* tp_new */
778  NULL, /* tp_free */
779  NULL, /* tp_is_gc */
780  NULL, /* tp_bases */
781  NULL, /* tp_mro */
782  NULL, /* tp_cache */
783  NULL, /* tp_subclasses */
784  NULL, /* tp_weaklist */
785  NULL, /* tp_del */
786 };
787 
788 PyObject *Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type)
789 {
790  EulerObject *self;
791  float *eul_alloc;
792 
793  eul_alloc = PyMem_Malloc(EULER_SIZE * sizeof(float));
794  if (UNLIKELY(eul_alloc == NULL)) {
795  PyErr_SetString(PyExc_MemoryError,
796  "Euler(): "
797  "problem allocating data");
798  return NULL;
799  }
800 
801  self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
802  if (self) {
803  self->eul = eul_alloc;
804 
805  /* init callbacks as NULL */
806  self->cb_user = NULL;
807  self->cb_type = self->cb_subtype = 0;
808 
809  if (eul) {
810  copy_v3_v3(self->eul, eul);
811  }
812  else {
813  zero_v3(self->eul);
814  }
815 
816  self->flag = BASE_MATH_FLAG_DEFAULT;
817  self->order = order;
818  }
819  else {
820  PyMem_Free(eul_alloc);
821  }
822 
823  return (PyObject *)self;
824 }
825 
826 PyObject *Euler_CreatePyObject_wrap(float eul[3], const short order, PyTypeObject *base_type)
827 {
828  EulerObject *self;
829 
830  self = BASE_MATH_NEW(EulerObject, euler_Type, base_type);
831  if (self) {
832  /* init callbacks as NULL */
833  self->cb_user = NULL;
834  self->cb_type = self->cb_subtype = 0;
835 
836  self->eul = eul;
838 
839  self->order = order;
840  }
841 
842  return (PyObject *)self;
843 }
844 
845 PyObject *Euler_CreatePyObject_cb(PyObject *cb_user,
846  const short order,
847  uchar cb_type,
848  uchar cb_subtype)
849 {
851  if (self) {
852  Py_INCREF(cb_user);
853  self->cb_user = cb_user;
854  self->cb_type = cb_type;
855  self->cb_subtype = cb_subtype;
856  PyObject_GC_Track(self);
857  }
858 
859  return (PyObject *)self;
860 }
#define ATTR_FALLTHROUGH
A dynamically sized string ADT.
DynStr * BLI_dynstr_new(void) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition: BLI_dynstr.c:71
void BLI_dynstr_appendf(DynStr *__restrict ds, const char *__restrict format,...) ATTR_PRINTF_FORMAT(2
double double_round(double x, int ndigits)
Definition: math_base.c:47
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
Definition: math_matrix.c:391
void eulO_to_quat(float quat[4], const float eul[3], const short order)
void rotate_eulO(float eul[3], const short order, char axis, float angle)
@ EULER_ORDER_ZXY
@ EULER_ORDER_XZY
@ EULER_ORDER_XYZ
@ EULER_ORDER_YZX
@ EULER_ORDER_ZYX
@ EULER_ORDER_YXZ
void eulO_to_mat3(float mat[3][3], const float eul[3], const short order)
void compatible_eul(float eul[3], const float old[3])
void mat3_to_compatible_eulO(float eul[3], const float old[3], const short order, const float mat[3][3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
unsigned char uchar
Definition: BLI_sys_types.h:86
#define UNUSED(x)
#define POINTER_AS_INT(i)
#define UNLIKELY(x)
#define ELEM(...)
#define MIN2(a, b)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint order
Group RGB to Bright Vector Camera CLAMP
PyObject * self
Definition: bpy_driver.c:185
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
#define str(s)
int count
PyObject * BaseMathObject_freeze(BaseMathObject *self)
Definition: mathutils.c:698
PyObject * BaseMathObject_is_frozen_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:685
PyObject * BaseMathObject_is_wrapped_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:678
PyObject * mathutils_dynstr_to_py(struct DynStr *ds)
Definition: mathutils.c:564
Py_hash_t mathutils_array_hash(const float *array, size_t array_len)
Definition: mathutils.c:85
void BaseMathObject_dealloc(BaseMathObject *self)
Definition: mathutils.c:722
int EXPP_VectorsAreEqual(const float *vecA, const float *vecB, int size, int floatSteps)
Definition: mathutils.c:551
PyObject * BaseMathObject_owner_get(BaseMathObject *self, void *UNUSED(closure))
Definition: mathutils.c:670
char BaseMathObject_is_wrapped_doc[]
Definition: mathutils.c:676
char BaseMathObject_is_frozen_doc[]
Definition: mathutils.c:683
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
Definition: mathutils.c:118
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
Definition: mathutils.c:471
char BaseMathObject_owner_doc[]
Definition: mathutils.c:669
char BaseMathObject_freeze_doc[]
Definition: mathutils.c:690
int BaseMathObject_clear(BaseMathObject *self)
Definition: mathutils.c:716
int BaseMathObject_traverse(BaseMathObject *self, visitproc visit, void *arg)
Definition: mathutils.c:710
#define BaseMath_ReadCallback_ForWrite(_self)
Definition: mathutils.h:138
#define BaseMath_ReadIndexCallback(_self, _index)
Definition: mathutils.h:132
#define BaseMath_WriteCallback(_self)
Definition: mathutils.h:130
#define BASE_MATH_NEW(struct_name, root_type, base_type)
Definition: mathutils.h:33
#define BaseMathObject_Prepare_ForHash(_self)
Definition: mathutils.h:153
@ BASE_MATH_FLAG_IS_WRAP
Definition: mathutils.h:44
#define BASE_MATH_FLAG_DEFAULT
Definition: mathutils.h:51
#define BaseMath_Prepare_ForWrite(_self)
Definition: mathutils.h:148
#define BaseMath_ReadCallback(_self)
Definition: mathutils.h:128
#define BaseMath_WriteIndexCallback(_self, _index)
Definition: mathutils.h:134
static PySequenceMethods Euler_SeqMethods
PyObject * Euler_CreatePyObject_wrap(float eul[3], const short order, PyTypeObject *base_type)
static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq)
PyObject * Euler_CreatePyObject_cb(PyObject *cb_user, const short order, uchar cb_type, uchar cb_subtype)
short euler_order_from_string(const char *str, const char *error_prefix)
static PyObject * Euler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
static PyObject * Euler_repr(EulerObject *self)
static PyObject * Euler_axis_get(EulerObject *self, void *type)
static PyObject * Euler_zero(EulerObject *self)
static Py_hash_t Euler_hash(EulerObject *self)
static PyObject * Euler_ToTupleExt(EulerObject *self, int ndigits)
static const char * euler_order_str(EulerObject *self)
static int Euler_len(EulerObject *UNUSED(self))
static PyObject * Euler_rotate_axis(EulerObject *self, PyObject *args)
PyTypeObject euler_Type
#define MAKE_ID3(a, b, c)
static PyObject * Euler_slice(EulerObject *self, int begin, int end)
static PyObject * Euler_subscript(EulerObject *self, PyObject *item)
static int Euler_axis_set(EulerObject *self, PyObject *value, void *type)
static PyObject * Euler_to_quaternion(EulerObject *self)
static int Euler_order_set(EulerObject *self, PyObject *value, void *UNUSED(closure))
static int Euler_ass_subscript(EulerObject *self, PyObject *item, PyObject *value)
static PyObject * Euler_to_matrix(EulerObject *self)
static PyObject * Euler_item(EulerObject *self, int i)
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_copy(EulerObject *self)
PyObject * Euler_CreatePyObject(const float eul[3], const short order, PyTypeObject *base_type)
static PyObject * Euler_rotate(EulerObject *self, PyObject *value)
static PyObject * Euler_str(EulerObject *self)
static int Euler_ass_item(EulerObject *self, int i, PyObject *value)
#define EULER_SIZE
static PyGetSetDef Euler_getseters[]
static PyObject * Euler_richcmpr(PyObject *a, PyObject *b, int op)
static PyObject * Euler_make_compatible(EulerObject *self, PyObject *value)
static PyMappingMethods Euler_AsMapping
static struct PyMethodDef Euler_methods[]
static PyObject * Euler_order_get(EulerObject *self, void *UNUSED(closure))
static PyObject * Euler_deepcopy(EulerObject *self, PyObject *args)
#define EulerObject_Check(v)
PyObject * Matrix_CreatePyObject(const float *mat, const ushort num_col, const ushort num_row, PyTypeObject *base_type)
PyObject * Quaternion_CreatePyObject(const float quat[4], PyTypeObject *base_type)
static unsigned a[3]
Definition: RandGen.cpp:92
int PyC_CheckArgs_DeepCopy(PyObject *args)
return ret
unsigned char order