From cefb76426980b763bbf68f022fc0df8aec8a25bd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 30 Dec 2014 22:47:56 +1100 Subject: PyAPI: geometry.normal, support polygons Previously this only supported tri/quads, now arbitrary size poly lines are supported. --- source/blender/python/mathutils/mathutils.c | 7 +- source/blender/python/mathutils/mathutils.h | 2 + .../blender/python/mathutils/mathutils_geometry.c | 90 ++++++---------------- 3 files changed, 30 insertions(+), 69 deletions(-) (limited to 'source') diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 5c3f38e2c12..8aaf47f090f 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -72,7 +72,7 @@ int mathutils_array_parse(float *array, int array_min, int array_max, PyObject * const int flag = array_max; int size; - array_max &= ~(MU_ARRAY_ZERO | MU_ARRAY_SPILL); + array_max &= ~MU_ARRAY_FLAGS; #if 1 /* approx 6x speedup for mathutils types */ @@ -217,6 +217,7 @@ 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) { PyObject *value_fast = NULL; + const int array_dim_flag = array_dim; int i, size; /* non list/tuple cases */ @@ -230,12 +231,14 @@ int mathutils_array_parse_alloc_v(float **array, int array_dim, PyObject *value, if (size != 0) { float *fp; + array_dim &= ~MU_ARRAY_FLAGS; + fp = *array = PyMem_Malloc(size * array_dim * sizeof(float)); for (i = 0; i < size; i++, fp += array_dim) { PyObject *item = PySequence_Fast_GET_ITEM(value, i); - if (mathutils_array_parse(fp, array_dim, array_dim, item, error_prefix) == -1) { + if (mathutils_array_parse(fp, array_dim, array_dim_flag, item, error_prefix) == -1) { PyMem_Free(*array); *array = NULL; size = -1; diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index 5f89c78b9cd..be2b45d349f 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -115,6 +115,8 @@ int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error * handy when using 3d vectors as 2d */ #define MU_ARRAY_SPILL (1 << 31) +#define MU_ARRAY_FLAGS (MU_ARRAY_ZERO | MU_ARRAY_SPILL) + 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 2a570edce93..49f1253af95 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -293,86 +293,42 @@ static PyObject *M_Geometry_intersect_sphere_sphere_2d(PyObject *UNUSED(self), P } PyDoc_STRVAR(M_Geometry_normal_doc, -".. function:: normal(v1, v2, v3, v4=None)\n" +".. function:: normal(vectors)\n" "\n" -" Returns the normal of the 3D tri or quad.\n" +" Returns the normal of a 3D polygon.\n" "\n" -" :arg v1: Point1\n" -" :type v1: :class:`mathutils.Vector`\n" -" :arg v2: Point2\n" -" :type v2: :class:`mathutils.Vector`\n" -" :arg v3: Point3\n" -" :type v3: :class:`mathutils.Vector`\n" -" :arg v4: Point4 (optional)\n" -" :type v4: :class:`mathutils.Vector`\n" +" :arg vectors: Vectors to calculate normals with\n" +" :type vectors: sequence of 3 or more 3d vector\n" " :rtype: :class:`mathutils.Vector`\n" ); static PyObject *M_Geometry_normal(PyObject *UNUSED(self), PyObject *args) { - VectorObject *vec1, *vec2, *vec3, *vec4; + float (*coords)[3]; + int coords_len; float n[3]; + PyObject *ret = NULL; - if (PyTuple_GET_SIZE(args) == 3) { - if (!PyArg_ParseTuple(args, "O!O!O!:normal", - &vector_Type, &vec1, - &vector_Type, &vec2, - &vector_Type, &vec3)) - { - 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 (vec1->size < 3) { - PyErr_SetString(PyExc_ValueError, - "2D vectors unsupported"); - return NULL; - } - - if (BaseMath_ReadCallback(vec1) == -1 || - BaseMath_ReadCallback(vec2) == -1 || - BaseMath_ReadCallback(vec3) == -1) - { - return NULL; - } - - normal_tri_v3(n, vec1->vec, vec2->vec, vec3->vec); + /* use */ + if (PyTuple_GET_SIZE(args) == 1) { + args = PyTuple_GET_ITEM(args, 0); } - else { - if (!PyArg_ParseTuple(args, "O!O!O!O!:normal", - &vector_Type, &vec1, - &vector_Type, &vec2, - &vector_Type, &vec3, - &vector_Type, &vec4)) - { - return NULL; - } - if (vec1->size != vec2->size || vec1->size != vec3->size || vec1->size != vec4->size) { - PyErr_SetString(PyExc_ValueError, - "vectors must be of the same size"); - return NULL; - } - if (vec1->size < 3) { - PyErr_SetString(PyExc_ValueError, - "2D vectors unsupported"); - return NULL; - } - if (BaseMath_ReadCallback(vec1) == -1 || - BaseMath_ReadCallback(vec2) == -1 || - BaseMath_ReadCallback(vec3) == -1 || - BaseMath_ReadCallback(vec4) == -1) - { - return NULL; - } + if ((coords_len = mathutils_array_parse_alloc_v((float **)&coords, 3 | MU_ARRAY_SPILL, args, "normal")) == -1) { + return NULL; + } - normal_quad_v3(n, vec1->vec, vec2->vec, vec3->vec, vec4->vec); + if (coords_len < 3) { + PyErr_SetString(PyExc_ValueError, + "Expected 3 or more vectors"); + goto finally; } - return Vector_CreatePyObject(n, 3, Py_NEW, NULL); + normal_poly_v3(n, (const float (*)[3])coords, coords_len); + ret = Vector_CreatePyObject(n, 3, Py_NEW, NULL); + +finally: + PyMem_Free(coords); + return ret; } /* --------------------------------- AREA FUNCTIONS-------------------- */ -- cgit v1.2.3