Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2014-12-30 13:50:47 +0300
committerCampbell Barton <ideasman42@gmail.com>2014-12-30 14:05:34 +0300
commit68600920ced198eaa1524993f988f26118402e50 (patch)
tree6f6c6c7228cf683eeb77b7cdf471c9c1b334d4bb /source
parentd993bad5e7adc35ad984dec1bbf0a57d99000712 (diff)
PyAPI: allow non-vector args for geometry module
Previously only vector args were accepted, now allow generic sequence of numbers. Was annoying to create vectors just to pass in args.
Diffstat (limited to 'source')
-rw-r--r--source/blender/python/mathutils/mathutils.c25
-rw-r--r--source/blender/python/mathutils/mathutils.h6
-rw-r--r--source/blender/python/mathutils/mathutils_geometry.c638
3 files changed, 278 insertions, 391 deletions
diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c
index 349f8483fb0..5c3f38e2c12 100644
--- a/source/blender/python/mathutils/mathutils.c
+++ b/source/blender/python/mathutils/mathutils.c
@@ -69,8 +69,11 @@ static int mathutils_array_parse_fast(float *array,
/* helper functionm returns length of the 'value', -1 on error */
int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix)
{
+ const int flag = array_max;
int size;
+ array_max &= ~(MU_ARRAY_ZERO | MU_ARRAY_SPILL);
+
#if 1 /* approx 6x speedup for mathutils types */
if ((size = VectorObject_Check(value) ? ((VectorObject *)value)->size : 0) ||
@@ -82,6 +85,10 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
return -1;
}
+ if (flag & MU_ARRAY_SPILL) {
+ CLAMP_MAX(size, array_max);
+ }
+
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
@@ -97,7 +104,6 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
}
memcpy(array, ((BaseMathObject *)value)->data, size * sizeof(float));
- return size;
}
else
#endif
@@ -112,6 +118,10 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
size = PySequence_Fast_GET_SIZE(value_fast);
+ if (flag & MU_ARRAY_SPILL) {
+ CLAMP_MAX(size, array_max);
+ }
+
if (size > array_max || size < array_min) {
if (array_max == array_min) {
PyErr_Format(PyExc_ValueError,
@@ -127,8 +137,19 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *
return -1;
}
- return mathutils_array_parse_fast(array, size, value_fast, error_prefix);
+ size = mathutils_array_parse_fast(array, size, value_fast, error_prefix);
}
+
+ if (size != -1) {
+ if (flag & MU_ARRAY_ZERO) {
+ int size_left = array_max - size;
+ if (size_left) {
+ memset(&array[size], 0, sizeof(float) * size_left);
+ }
+ }
+ }
+
+ return size;
}
/* on error, -1 is returned and no allocation is made */
diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h
index eb25d9bff07..5f89c78b9cd 100644
--- a/source/blender/python/mathutils/mathutils.h
+++ b/source/blender/python/mathutils/mathutils.h
@@ -109,6 +109,12 @@ int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, c
int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, const char *error_prefix);
int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
+/* zero remaining unused elements of the array */
+#define MU_ARRAY_ZERO (1 << 30)
+/* ignore larger py sequences than requested (just use first elements),
+ * handy when using 3d vectors as 2d */
+#define MU_ARRAY_SPILL (1 << 31)
+
int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat);
#ifndef MATH_STANDALONE
diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c
index 013c87427b3..2a570edce93 100644
--- a/source/blender/python/mathutils/mathutils_geometry.c
+++ b/source/blender/python/mathutils/mathutils_geometry.c
@@ -72,48 +72,37 @@ PyDoc_STRVAR(M_Geometry_intersect_ray_tri_doc,
);
static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *ray, *ray_off, *vec1, *vec2, *vec3;
- float dir[3], orig[3], v1[3], v2[3], v3[3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
+ const char *error_prefix = "intersect_ray_tri";
+ PyObject *py_ray, *py_ray_off, *py_tri[3];
+ float dir[3], orig[3], tri[3][3], e1[3], e2[3], pvec[3], tvec[3], qvec[3];
float det, inv_det, u, v, t;
int clip = 1;
+ int i;
- if (!PyArg_ParseTuple(args,
- "O!O!O!O!O!|i:intersect_ray_tri",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &ray,
- &vector_Type, &ray_off, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOOO|i:intersect_ray_tri",
+ UNPACK3_EX(&, py_tri, ), &py_ray, &py_ray_off, &clip))
{
return NULL;
}
- if (vec1->size != 3 || vec2->size != 3 || vec3->size != 3 || ray->size != 3 || ray_off->size != 3) {
- PyErr_SetString(PyExc_ValueError,
- "only 3D vectors for all parameters");
- return NULL;
- }
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(ray) == -1 ||
- BaseMath_ReadCallback(ray_off) == -1)
+ if (((mathutils_array_parse(dir, 3, 3, py_ray, error_prefix) != -1) &&
+ (mathutils_array_parse(orig, 3, 3, py_ray_off, error_prefix) != -1)) == 0)
{
return NULL;
}
- copy_v3_v3(v1, vec1->vec);
- copy_v3_v3(v2, vec2->vec);
- copy_v3_v3(v3, vec3->vec);
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 2, 2 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- copy_v3_v3(dir, ray->vec);
normalize_v3(dir);
- copy_v3_v3(orig, ray_off->vec);
-
/* find vectors for two edges sharing v1 */
- sub_v3_v3v3(e1, v2, v1);
- sub_v3_v3v3(e2, v3, v1);
+ sub_v3_v3v3(e1, tri[1], tri[0]);
+ sub_v3_v3v3(e2, tri[2], tri[0]);
/* begin calculating determinant - also used to calculated U parameter */
cross_v3_v3v3(pvec, dir, e2);
@@ -128,7 +117,7 @@ static PyObject *M_Geometry_intersect_ray_tri(PyObject *UNUSED(self), PyObject *
inv_det = 1.0f / det;
/* calculate distance from v1 to ray origin */
- sub_v3_v3v3(tvec, orig, v1);
+ sub_v3_v3v3(tvec, orig, tri[0]);
/* calculate U parameter and test bounds */
u = dot_v3v3(tvec, pvec) * inv_det;
@@ -179,82 +168,48 @@ PyDoc_STRVAR(M_Geometry_intersect_line_line_doc,
);
static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_line_line";
PyObject *tuple;
- VectorObject *vec1, *vec2, *vec3, *vec4;
- float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3];
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
+ PyObject *py_lines[4];
+ float lines[4][3], i1[3], i2[3];
+ int len;
+ int result;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_line_line",
+ UNPACK4_EX(&, py_lines, )))
{
return NULL;
}
- if (vec1->size != vec2->size || vec1->size != vec3->size || vec3->size != vec2->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
+ if ((((len = mathutils_array_parse(lines[0], 2, 3, py_lines[0], error_prefix)) != -1) &&
+ (mathutils_array_parse(lines[1], len, len, py_lines[1], error_prefix) != -1) &&
+ (mathutils_array_parse(lines[2], len, len, py_lines[2], error_prefix) != -1) &&
+ (mathutils_array_parse(lines[3], len, len, py_lines[3], error_prefix) != -1)) == 0)
{
return NULL;
}
- if (vec1->size == 3 || vec1->size == 2) {
- int result;
-
- if (vec1->size == 3) {
- copy_v3_v3(v1, vec1->vec);
- copy_v3_v3(v2, vec2->vec);
- copy_v3_v3(v3, vec3->vec);
- copy_v3_v3(v4, vec4->vec);
- }
- else {
- v1[0] = vec1->vec[0];
- v1[1] = vec1->vec[1];
- v1[2] = 0.0f;
-
- v2[0] = vec2->vec[0];
- v2[1] = vec2->vec[1];
- v2[2] = 0.0f;
-
- v3[0] = vec3->vec[0];
- v3[1] = vec3->vec[1];
- v3[2] = 0.0f;
-
- v4[0] = vec4->vec[0];
- v4[1] = vec4->vec[1];
- v4[2] = 0.0f;
- }
+ if (len == 2) {
+ lines[0][2] = lines[1][2] = lines[2][2] = lines[3][2] = 0.0f;
+ }
- result = isect_line_line_v3(v1, v2, v3, v4, i1, i2);
- /* The return-code isnt exposed,
- * this way we can check know how close the lines are. */
- if (result == 1) {
- closest_to_line_v3(i2, i1, v3, v4);
- }
+ result = isect_line_line_v3(UNPACK4(lines), i1, i2);
+ /* The return-code isnt exposed,
+ * this way we can check know how close the lines are. */
+ if (result == 1) {
+ closest_to_line_v3(i2, i1, lines[2], lines[3]);
+ }
- if (result == 0) {
- /* colinear */
- Py_RETURN_NONE;
- }
- else {
- tuple = PyTuple_New(2);
- PyTuple_SET_ITEM(tuple, 0, Vector_CreatePyObject(i1, vec1->size, Py_NEW, NULL));
- PyTuple_SET_ITEM(tuple, 1, Vector_CreatePyObject(i2, vec1->size, Py_NEW, NULL));
- return tuple;
- }
+ if (result == 0) {
+ /* colinear */
+ Py_RETURN_NONE;
}
else {
- PyErr_SetString(PyExc_ValueError,
- "2D/3D vectors only");
- return NULL;
+ tuple = PyTuple_New(2);
+ PyTuple_SET_ITEM(tuple, 0, Vector_CreatePyObject(i1, len, Py_NEW, NULL));
+ PyTuple_SET_ITEM(tuple, 1, Vector_CreatePyObject(i2, len, Py_NEW, NULL));
+ return tuple;
}
}
@@ -277,31 +232,30 @@ PyDoc_STRVAR(M_Geometry_intersect_sphere_sphere_2d_doc,
);
static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_sphere_sphere_2d";
PyObject *ret;
- VectorObject *vec_a, *vec_b;
- const float *v_a, *v_b;
+ PyObject *py_v_a, *py_v_b;
+ float v_a[2], v_b[2];
float rad_a, rad_b;
float v_ab[2];
float dist;
- if (!PyArg_ParseTuple(args, "O!fO!f:intersect_sphere_sphere_2d",
- &vector_Type, &vec_a, &rad_a,
- &vector_Type, &vec_b, &rad_b))
+ if (!PyArg_ParseTuple(
+ args, "OfOf:intersect_sphere_sphere_2d",
+ &py_v_a, &rad_a,
+ &py_v_b, &rad_b))
{
return NULL;
}
- if (BaseMath_ReadCallback(vec_a) == -1 ||
- BaseMath_ReadCallback(vec_b) == -1)
+ if (((mathutils_array_parse(v_a, 2, 2, py_v_a, error_prefix) != -1) &&
+ (mathutils_array_parse(v_b, 2, 2, py_v_b, error_prefix) != -1)) == 0)
{
return NULL;
}
ret = PyTuple_New(2);
- v_a = vec_a->vec;
- v_b = vec_b->vec;
-
sub_v2_v2v2(v_ab, v_b, v_a);
dist = len_v2(v_ab);
@@ -438,40 +392,26 @@ PyDoc_STRVAR(M_Geometry_area_tri_doc,
);
static PyObject *M_Geometry_area_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3;
-
- if (!PyArg_ParseTuple(args, "O!O!O!:area_tri",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3))
+ const char *error_prefix = "area_tri";
+ PyObject *py_tri[3];
+ float tri[3][3];
+ int len;
+
+ if (!PyArg_ParseTuple(
+ args, "OOO:area_tri",
+ UNPACK3_EX(&, py_tri, )))
{
return NULL;
}
- if (vec1->size != vec2->size || vec1->size != vec3->size) {
- PyErr_SetString(PyExc_ValueError,
- "vectors must be of the same size");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1)
+ if ((((len = mathutils_array_parse(tri[0], 2, 3, py_tri[0], error_prefix)) != -1) &&
+ (mathutils_array_parse(tri[1], len, len, py_tri[1], error_prefix) != -1) &&
+ (mathutils_array_parse(tri[2], len, len, py_tri[2], error_prefix) != -1)) == 0)
{
return NULL;
}
- if (vec1->size == 3) {
- return PyFloat_FromDouble(area_tri_v3(vec1->vec, vec2->vec, vec3->vec));
- }
- else if (vec1->size == 2) {
- return PyFloat_FromDouble(area_tri_v2(vec1->vec, vec2->vec, vec3->vec));
- }
- else {
- PyErr_SetString(PyExc_ValueError,
- "only 2D,3D vectors are supported");
- return NULL;
- }
+ return PyFloat_FromDouble((len == 3 ? area_tri_v3 : area_tri_v2)(UNPACK3(tri)));
}
PyDoc_STRVAR(M_Geometry_volume_tetrahedron_doc,
@@ -491,33 +431,25 @@ PyDoc_STRVAR(M_Geometry_volume_tetrahedron_doc,
);
static PyObject *M_Geometry_volume_tetrahedron(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec1, *vec2, *vec3, *vec4;
+ const char *error_prefix = "volume_tetrahedron";
+ PyObject *py_tet[4];
+ float tet[4][3];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!:volume_tetrahedron",
- &vector_Type, &vec1,
- &vector_Type, &vec2,
- &vector_Type, &vec3,
- &vector_Type, &vec4))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:volume_tetrahedron",
+ UNPACK4_EX(&, py_tet, )))
{
return NULL;
}
- if (vec1->size < 3 || vec2->size < 3 || vec3->size < 3 || vec4->size < 3) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.volume_tetrahedron(...): "
- " can't use 2D Vectors");
- return NULL;
- }
-
- if (BaseMath_ReadCallback(vec1) == -1 ||
- BaseMath_ReadCallback(vec2) == -1 ||
- BaseMath_ReadCallback(vec3) == -1 ||
- BaseMath_ReadCallback(vec4) == -1)
- {
- return NULL;
+ for (i = 0; i < ARRAY_SIZE(tet); i++) {
+ if (mathutils_array_parse(tet[i], 3, 3 | MU_ARRAY_SPILL, py_tet[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- return PyFloat_FromDouble(volume_tetrahedron_v3(vec1->vec, vec2->vec, vec3->vec, vec4->vec));
+ return PyFloat_FromDouble(volume_tetrahedron_v3(UNPACK4(tet)));
}
PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
@@ -538,26 +470,26 @@ PyDoc_STRVAR(M_Geometry_intersect_line_line_2d_doc,
);
static PyObject *M_Geometry_intersect_line_line_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a1, *line_a2, *line_b1, *line_b2;
+ const char *error_prefix = "intersect_line_line_2d";
+ PyObject *py_lines[4];
+ float lines[4][2];
float vi[2];
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_line_line_2d",
- &vector_Type, &line_a1,
- &vector_Type, &line_a2,
- &vector_Type, &line_b1,
- &vector_Type, &line_b2))
+ int i;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_line_line_2d",
+ UNPACK4_EX(&, py_lines, )))
{
return NULL;
}
-
- if (BaseMath_ReadCallback(line_a1) == -1 ||
- BaseMath_ReadCallback(line_a2) == -1 ||
- BaseMath_ReadCallback(line_b1) == -1 ||
- BaseMath_ReadCallback(line_b2) == -1)
- {
- return NULL;
+
+ for (i = 0; i < ARRAY_SIZE(lines); i++) {
+ if (mathutils_array_parse(lines[i], 2, 2 | MU_ARRAY_SPILL, py_lines[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- if (isect_seg_seg_v2_point(line_a1->vec, line_a2->vec, line_b1->vec, line_b2->vec, vi) == 1) {
+ if (isect_seg_seg_v2_point(UNPACK4(lines), vi) == 1) {
return Vector_CreatePyObject(vi, 2, Py_NEW, NULL);
}
else {
@@ -585,37 +517,30 @@ PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc,
);
static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *plane_co, *plane_no;
+ const char *error_prefix = "intersect_line_plane";
+ PyObject *py_line_a, *py_line_b, *py_plane_co, *py_plane_no;
+ float line_a[3], line_b[3], plane_co[3], plane_no[3];
float isect[3];
int no_flip = false;
- if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &plane_co,
- &vector_Type, &plane_no,
- &no_flip))
+ if (!PyArg_ParseTuple(
+ args, "OOOO|i:intersect_line_plane",
+ &py_line_a, &py_line_b, &py_plane_co, &py_plane_no,
+ &no_flip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(plane_co) == -1 ||
- BaseMath_ReadCallback(plane_no) == -1)
+ if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- if (ELEM(2, line_a->size, line_b->size, plane_co->size, plane_no->size)) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.intersect_line_plane(...): "
- " can't use 2D Vectors");
- return NULL;
- }
-
/* TODO: implements no_flip */
- if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec) == 1) {
+ if (isect_line_plane_v3(isect, line_a, line_b, plane_co, plane_no) == 1) {
return Vector_CreatePyObject(isect, 3, Py_NEW, NULL);
}
else {
@@ -641,39 +566,32 @@ PyDoc_STRVAR(M_Geometry_intersect_plane_plane_doc,
);
static PyObject *M_Geometry_intersect_plane_plane(PyObject *UNUSED(self), PyObject *args)
{
+ const char *error_prefix = "intersect_plane_plane";
PyObject *ret, *ret_co, *ret_no;
- VectorObject *plane_a_co, *plane_a_no, *plane_b_co, *plane_b_no;
+ PyObject *py_plane_a_co, *py_plane_a_no, *py_plane_b_co, *py_plane_b_no;
+ float plane_a_co[3], plane_a_no[3], plane_b_co[3], plane_b_no[3];
float isect_co[3];
float isect_no[3];
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_plane_plane",
- &vector_Type, &plane_a_co,
- &vector_Type, &plane_a_no,
- &vector_Type, &plane_b_co,
- &vector_Type, &plane_b_no))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_plane_plane",
+ &plane_a_co, &plane_a_no, &plane_b_co, &plane_b_no))
{
return NULL;
}
- if (BaseMath_ReadCallback(plane_a_co) == -1 ||
- BaseMath_ReadCallback(plane_a_no) == -1 ||
- BaseMath_ReadCallback(plane_b_co) == -1 ||
- BaseMath_ReadCallback(plane_b_no) == -1)
+ if (((mathutils_array_parse(plane_a_co, 3, 3 | MU_ARRAY_SPILL, py_plane_a_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_a_no, 3, 3 | MU_ARRAY_SPILL, py_plane_a_no, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_b_co, 3, 3 | MU_ARRAY_SPILL, py_plane_b_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_b_no, 3, 3 | MU_ARRAY_SPILL, py_plane_b_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- if (ELEM(2, plane_a_co->size, plane_a_no->size, plane_b_co->size, plane_b_no->size)) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.intersect_plane_plane(...): "
- " can't use 2D Vectors");
- return NULL;
- }
-
if (isect_plane_plane_v3(isect_co, isect_no,
- plane_a_co->vec, plane_a_no->vec,
- plane_b_co->vec, plane_b_no->vec))
+ plane_a_co, plane_a_no,
+ plane_b_co, plane_b_no))
{
normalize_v3(isect_no);
@@ -713,35 +631,28 @@ PyDoc_STRVAR(M_Geometry_intersect_line_sphere_doc,
);
static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *sphere_co;
+ const char *error_prefix = "intersect_line_sphere";
+ PyObject *py_line_a, *py_line_b, *py_sphere_co;
+ float line_a[3], line_b[3], sphere_co[3];
float sphere_radius;
int clip = true;
float isect_a[3];
float isect_b[3];
- if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &sphere_co,
- &sphere_radius, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOf|i:intersect_line_sphere",
+ &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius, &clip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(sphere_co) == -1)
+ if (((mathutils_array_parse(line_a, 3, 3 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(sphere_co, 3, 3 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0)
{
return NULL;
}
-
- if (ELEM(2, line_a->size, line_b->size, sphere_co->size)) {
- PyErr_SetString(PyExc_ValueError,
- "geometry.intersect_line_sphere(...): "
- " can't use 2D Vectors");
- return NULL;
- }
else {
bool use_a = true;
bool use_b = true;
@@ -749,14 +660,14 @@ static PyObject *M_Geometry_intersect_line_sphere(PyObject *UNUSED(self), PyObje
PyObject *ret = PyTuple_New(2);
- switch (isect_line_sphere_v3(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
+ switch (isect_line_sphere_v3(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) {
case 1:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
use_b = false;
break;
case 2:
- if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
- if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v3(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
break;
default:
use_a = false;
@@ -794,25 +705,25 @@ PyDoc_STRVAR(M_Geometry_intersect_line_sphere_2d_doc,
);
static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *line_a, *line_b, *sphere_co;
+ const char *error_prefix = "intersect_line_sphere_2d";
+ PyObject *py_line_a, *py_line_b, *py_sphere_co;
+ float line_a[2], line_b[2], sphere_co[2];
float sphere_radius;
int clip = true;
float isect_a[2];
float isect_b[2];
- if (!PyArg_ParseTuple(args, "O!O!O!f|i:intersect_line_sphere_2d",
- &vector_Type, &line_a,
- &vector_Type, &line_b,
- &vector_Type, &sphere_co,
- &sphere_radius, &clip))
+ if (!PyArg_ParseTuple(
+ args, "OOOf|i:intersect_line_sphere_2d",
+ &py_line_a, &py_line_b, &py_sphere_co, &sphere_radius, &clip))
{
return NULL;
}
- if (BaseMath_ReadCallback(line_a) == -1 ||
- BaseMath_ReadCallback(line_b) == -1 ||
- BaseMath_ReadCallback(sphere_co) == -1)
+ if (((mathutils_array_parse(line_a, 2, 2 | MU_ARRAY_SPILL, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 2, 2 | MU_ARRAY_SPILL, py_line_b, error_prefix) != -1) &&
+ (mathutils_array_parse(sphere_co, 2, 2 | MU_ARRAY_SPILL, py_sphere_co, error_prefix) != -1)) == 0)
{
return NULL;
}
@@ -823,14 +734,14 @@ static PyObject *M_Geometry_intersect_line_sphere_2d(PyObject *UNUSED(self), PyO
PyObject *ret = PyTuple_New(2);
- switch (isect_line_sphere_v2(line_a->vec, line_b->vec, sphere_co->vec, sphere_radius, isect_a, isect_b)) {
+ switch (isect_line_sphere_v2(line_a, line_b, sphere_co, sphere_radius, isect_a, isect_b)) {
case 1:
- if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
use_b = false;
break;
case 2:
- if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
- if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a->vec, line_b->vec)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_a, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_a = false;
+ if (!(!clip || (((lambda = line_point_factor_v2(isect_b, line_a, line_b)) >= 0.0f) && (lambda <= 1.0f)))) use_b = false;
break;
default:
use_a = false;
@@ -863,39 +774,30 @@ PyDoc_STRVAR(M_Geometry_intersect_point_line_doc,
);
static PyObject *M_Geometry_intersect_point_line(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt, *line_1, *line_2;
- float pt_in[3], pt_out[3], l1[3], l2[3];
+ const char *error_prefix = "intersect_point_line";
+ PyObject *py_pt, *py_line_a, *py_line_b;
+ float pt[3], pt_out[3], line_a[3], line_b[3];
float lambda;
PyObject *ret;
int size = 2;
- if (!PyArg_ParseTuple(args, "O!O!O!:intersect_point_line",
- &vector_Type, &pt,
- &vector_Type, &line_1,
- &vector_Type, &line_2))
+ if (!PyArg_ParseTuple(
+ args, "OOO:intersect_point_line",
+ &py_pt, &py_line_a, &py_line_b))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt) == -1 ||
- BaseMath_ReadCallback(line_1) == -1 ||
- BaseMath_ReadCallback(line_2) == -1)
+ /* accept 2d verts */
+ if (((mathutils_array_parse(pt, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_pt, error_prefix) != -1) &&
+ (mathutils_array_parse(line_a, 2, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_a, error_prefix) != -1) &&
+ (mathutils_array_parse(line_b, 3, 3 | MU_ARRAY_SPILL | MU_ARRAY_ZERO, py_line_b, error_prefix) != -1)) == 0)
{
return NULL;
}
- /* accept 2d verts */
- if (pt->size >= 3) { copy_v3_v3(pt_in, pt->vec); size = 3; }
- else { copy_v2_v2(pt_in, pt->vec); pt_in[2] = 0.0f; }
-
- if (line_1->size >= 3) { copy_v3_v3(l1, line_1->vec); size = 3; }
- else { copy_v2_v2(l1, line_1->vec); l1[2] = 0.0f; }
-
- if (line_2->size >= 3) { copy_v3_v3(l2, line_2->vec); size = 3; }
- else { copy_v2_v2(l2, line_2->vec); l2[2] = 0.0f; }
-
/* do the calculation */
- lambda = closest_to_line_v3(pt_out, pt_in, l1, l2);
+ lambda = closest_to_line_v3(pt_out, pt, line_a, line_b);
ret = PyTuple_New(2);
PyTuple_SET_ITEM(ret, 0, Vector_CreatePyObject(pt_out, size, Py_NEW, NULL));
@@ -921,37 +823,29 @@ PyDoc_STRVAR(M_Geometry_intersect_point_tri_doc,
);
static PyObject *M_Geometry_intersect_point_tri(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
+ const char *error_prefix = "intersect_point_tri";
+ PyObject *py_pt, *py_tri[3];
+ float pt[3], tri[3][3];
float vi[3];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri",
- &vector_Type, &pt_vec,
- &vector_Type, &tri_p1,
- &vector_Type, &tri_p2,
- &vector_Type, &tri_p3))
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_point_tri",
+ &py_pt, UNPACK3_EX(&, py_tri,)))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(tri_p1) == -1 ||
- BaseMath_ReadCallback(tri_p2) == -1 ||
- BaseMath_ReadCallback(tri_p3) == -1)
- {
+ if (mathutils_array_parse(pt, 3, 3 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) {
return NULL;
}
-
- if (pt_vec->size < 3 ||
- tri_p1->size < 3 ||
- tri_p2->size < 3 ||
- tri_p3->size < 3)
- {
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
- return NULL;
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 3, 3 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
}
- if (isect_point_tri_v3(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec, vi)) {
+ if (isect_point_tri_v3(pt, UNPACK3(tri), vi)) {
return Vector_CreatePyObject(vi, 3, Py_NEW, NULL);
}
else {
@@ -976,26 +870,28 @@ PyDoc_STRVAR(M_Geometry_intersect_point_tri_2d_doc,
);
static PyObject *M_Geometry_intersect_point_tri_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *tri_p1, *tri_p2, *tri_p3;
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!:intersect_point_tri_2d",
- &vector_Type, &pt_vec,
- &vector_Type, &tri_p1,
- &vector_Type, &tri_p2,
- &vector_Type, &tri_p3))
+ const char *error_prefix = "intersect_point_tri_2d";
+ PyObject *py_pt, *py_tri[3];
+ float pt[2], tri[3][2];
+ int i;
+
+ if (!PyArg_ParseTuple(
+ args, "OOOO:intersect_point_tri_2d",
+ &py_pt, UNPACK3_EX(&, py_tri,)))
{
return NULL;
}
-
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(tri_p1) == -1 ||
- BaseMath_ReadCallback(tri_p2) == -1 ||
- BaseMath_ReadCallback(tri_p3) == -1)
- {
+
+ if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(tri); i++) {
+ if (mathutils_array_parse(tri[i], 2, 2 | MU_ARRAY_SPILL, py_tri[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- return PyLong_FromLong(isect_point_tri_v2(pt_vec->vec, tri_p1->vec, tri_p2->vec, tri_p3->vec));
+ return PyLong_FromLong(isect_point_tri_v2(pt, UNPACK3(tri)));
}
PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
@@ -1019,28 +915,28 @@ PyDoc_STRVAR(M_Geometry_intersect_point_quad_2d_doc,
);
static PyObject *M_Geometry_intersect_point_quad_2d(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt_vec, *quad_p1, *quad_p2, *quad_p3, *quad_p4;
+ const char *error_prefix = "intersect_point_quad_2d";
+ PyObject *py_pt, *py_quad[4];
+ float pt[2], quad[4][2];
+ int i;
- if (!PyArg_ParseTuple(args, "O!O!O!O!O!:intersect_point_quad_2d",
- &vector_Type, &pt_vec,
- &vector_Type, &quad_p1,
- &vector_Type, &quad_p2,
- &vector_Type, &quad_p3,
- &vector_Type, &quad_p4))
+ if (!PyArg_ParseTuple(
+ args, "OOOOO:intersect_point_quad_2d",
+ &py_pt, UNPACK4_EX(&, py_quad,)))
{
return NULL;
}
- if (BaseMath_ReadCallback(pt_vec) == -1 ||
- BaseMath_ReadCallback(quad_p1) == -1 ||
- BaseMath_ReadCallback(quad_p2) == -1 ||
- BaseMath_ReadCallback(quad_p3) == -1 ||
- BaseMath_ReadCallback(quad_p4) == -1)
- {
+ if (mathutils_array_parse(pt, 2, 2 | MU_ARRAY_SPILL, py_pt, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(quad); i++) {
+ if (mathutils_array_parse(quad[i], 2, 2 | MU_ARRAY_SPILL, py_quad[i], error_prefix) == -1) {
+ return NULL;
+ }
+ }
- return PyLong_FromLong(isect_point_quad_v2(pt_vec->vec, quad_p1->vec, quad_p2->vec, quad_p3->vec, quad_p4->vec));
+ return PyLong_FromLong(isect_point_quad_v2(pt, UNPACK4(quad)));
}
PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
@@ -1059,35 +955,27 @@ PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc,
);
static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *pt, *plane_co, *plane_no;
+ const char *error_prefix = "distance_point_to_plane";
+ PyObject *py_pt, *py_plane_co, *py_plane_no;
+ float pt[3], plane_co[3], plane_no[3];
float plane[4];
- if (!PyArg_ParseTuple(args, "O!O!O!:distance_point_to_plane",
- &vector_Type, &pt,
- &vector_Type, &plane_co,
- &vector_Type, &plane_no))
- {
- return NULL;
- }
-
- if (pt->size != 3 ||
- plane_co->size != 3 ||
- plane_no->size != 3)
+ if (!PyArg_ParseTuple(
+ args, "OOO:distance_point_to_plane",
+ &py_pt, &py_plane_co, &py_plane_no))
{
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
return NULL;
}
- if (BaseMath_ReadCallback(pt) == -1 ||
- BaseMath_ReadCallback(plane_co) == -1 ||
- BaseMath_ReadCallback(plane_no) == -1)
+ if (((mathutils_array_parse(pt, 3, 3 | MU_ARRAY_SPILL, py_pt, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_co, 3, 3 | MU_ARRAY_SPILL, py_plane_co, error_prefix) != -1) &&
+ (mathutils_array_parse(plane_no, 3, 3 | MU_ARRAY_SPILL, py_plane_no, error_prefix) != -1)) == 0)
{
return NULL;
}
- plane_from_point_normal_v3(plane, plane_co->vec, plane_no->vec);
- return PyFloat_FromDouble(dist_signed_to_plane_v3(pt->vec, plane));
+ plane_from_point_normal_v3(plane, plane_co, plane_no);
+ return PyFloat_FromDouble(dist_signed_to_plane_v3(pt, plane));
}
PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
@@ -1114,53 +1002,37 @@ PyDoc_STRVAR(M_Geometry_barycentric_transform_doc,
);
static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec_pt;
- VectorObject *vec_t1_tar, *vec_t2_tar, *vec_t3_tar;
- VectorObject *vec_t1_src, *vec_t2_src, *vec_t3_src;
- float vec[3];
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!O!O!O!::barycentric_transform",
- &vector_Type, &vec_pt,
- &vector_Type, &vec_t1_src,
- &vector_Type, &vec_t2_src,
- &vector_Type, &vec_t3_src,
- &vector_Type, &vec_t1_tar,
- &vector_Type, &vec_t2_tar,
- &vector_Type, &vec_t3_tar))
- {
- return NULL;
- }
+ const char *error_prefix = "barycentric_transform";
+ PyObject *py_pt_src, *py_tri_src[3], *py_tri_dst[3];
+ float pt_src[3], pt_dst[3], tri_src[3][3], tri_dst[3][3];
+ int i;
- if (vec_pt->size != 3 ||
- vec_t1_src->size != 3 ||
- vec_t2_src->size != 3 ||
- vec_t3_src->size != 3 ||
- vec_t1_tar->size != 3 ||
- vec_t2_tar->size != 3 ||
- vec_t3_tar->size != 3)
+ if (!PyArg_ParseTuple(
+ args, "OOOOOOO:barycentric_transform",
+ &py_pt_src,
+ UNPACK3_EX(&, py_tri_src, ),
+ UNPACK3_EX(&, py_tri_dst, )))
{
- PyErr_SetString(PyExc_ValueError,
- "One of more of the vector arguments wasn't a 3D vector");
return NULL;
}
- if (BaseMath_ReadCallback(vec_pt) == -1 ||
- BaseMath_ReadCallback(vec_t1_src) == -1 ||
- BaseMath_ReadCallback(vec_t2_src) == -1 ||
- BaseMath_ReadCallback(vec_t3_src) == -1 ||
- BaseMath_ReadCallback(vec_t1_tar) == -1 ||
- BaseMath_ReadCallback(vec_t2_tar) == -1 ||
- BaseMath_ReadCallback(vec_t3_tar) == -1)
- {
+ if (mathutils_array_parse(pt_src, 2, 2 | MU_ARRAY_SPILL, py_pt_src, error_prefix) == -1) {
return NULL;
}
+ for (i = 0; i < ARRAY_SIZE(tri_src); i++) {
+ if (((mathutils_array_parse(tri_src[i], 3, 3 | MU_ARRAY_SPILL, py_tri_src[i], error_prefix) != -1) &&
+ (mathutils_array_parse(tri_dst[i], 3, 3 | MU_ARRAY_SPILL, py_tri_dst[i], error_prefix) != -1)) == 0)
+ {
+ return NULL;
+ }
+ }
transform_point_by_tri_v3(
- vec, vec_pt->vec,
- vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec,
- vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec);
+ pt_dst, pt_src,
+ UNPACK3(tri_dst),
+ UNPACK3(tri_src));
- return Vector_CreatePyObject(vec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(pt_dst, 3, Py_NEW, NULL);
}
PyDoc_STRVAR(M_Geometry_points_in_planes_doc,
@@ -1180,8 +1052,9 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a
float (*planes)[4];
unsigned int planes_len;
- if (!PyArg_ParseTuple(args, "O:points_in_planes",
- &py_planes))
+ if (!PyArg_ParseTuple(
+ args, "O:points_in_planes",
+ &py_planes))
{
return NULL;
}
@@ -1290,52 +1163,39 @@ PyDoc_STRVAR(M_Geometry_interpolate_bezier_doc,
);
static PyObject *M_Geometry_interpolate_bezier(PyObject *UNUSED(self), PyObject *args)
{
- VectorObject *vec_k1, *vec_h1, *vec_k2, *vec_h2;
+ const char *error_prefix = "interpolate_bezier";
+ PyObject *py_data[4];
+ float data[4][4] = {{0.0f}};
int resolu;
- int dims;
+ int dims = 0;
int i;
float *coord_array, *fp;
PyObject *list;
- float k1[4] = {0.0, 0.0, 0.0, 0.0};
- float h1[4] = {0.0, 0.0, 0.0, 0.0};
- float k2[4] = {0.0, 0.0, 0.0, 0.0};
- float h2[4] = {0.0, 0.0, 0.0, 0.0};
-
-
- if (!PyArg_ParseTuple(args, "O!O!O!O!i:interpolate_bezier",
- &vector_Type, &vec_k1,
- &vector_Type, &vec_h1,
- &vector_Type, &vec_h2,
- &vector_Type, &vec_k2, &resolu))
+ if (!PyArg_ParseTuple(
+ args, "OOOOi:interpolate_bezier",
+ UNPACK4_EX(&, py_data, ), &resolu))
{
return NULL;
}
+ for (i = 0; i < 4; i++) {
+ int dims_tmp;
+ if ((((dims_tmp = mathutils_array_parse(data[i], 2, 2 | MU_ARRAY_SPILL, py_data[i], error_prefix)) == -1))) {
+ return NULL;
+ }
+ dims = max_ii(dims, dims_tmp);
+ }
+
if (resolu <= 1) {
PyErr_SetString(PyExc_ValueError,
"resolution must be 2 or over");
return NULL;
}
- if (BaseMath_ReadCallback(vec_k1) == -1 ||
- BaseMath_ReadCallback(vec_h1) == -1 ||
- BaseMath_ReadCallback(vec_k2) == -1 ||
- BaseMath_ReadCallback(vec_h2) == -1)
- {
- return NULL;
- }
-
- dims = max_iiii(vec_k1->size, vec_h1->size, vec_h2->size, vec_k2->size);
-
- for (i = 0; i < vec_k1->size; i++) k1[i] = vec_k1->vec[i];
- for (i = 0; i < vec_h1->size; i++) h1[i] = vec_h1->vec[i];
- for (i = 0; i < vec_k2->size; i++) k2[i] = vec_k2->vec[i];
- for (i = 0; i < vec_h2->size; i++) h2[i] = vec_h2->vec[i];
-
- coord_array = MEM_callocN(dims * (resolu) * sizeof(float), "interpolate_bezier");
+ coord_array = MEM_callocN(dims * (resolu) * sizeof(float), error_prefix);
for (i = 0; i < dims; i++) {
- BKE_curve_forward_diff_bezier(k1[i], h1[i], h2[i], k2[i], coord_array + i, resolu - 1, sizeof(float) * dims);
+ BKE_curve_forward_diff_bezier(UNPACK4_EX(, data, [i]), coord_array + i, resolu - 1, sizeof(float) * dims);
}
list = PyList_New(resolu);