[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [42702] trunk/blender/source/blender: Support for arbitrary sized vectors - (was limited by 2-4 previously)

Campbell Barton ideasman42 at gmail.com
Sun Dec 18 08:27:28 CET 2011


Revision: 42702
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=42702
Author:   campbellbarton
Date:     2011-12-18 07:27:11 +0000 (Sun, 18 Dec 2011)
Log Message:
-----------
Support for arbitrary sized vectors - (was limited by 2-4 previously)

patch http://codereview.appspot.com/5482043
from Andrew Hale

* Text from the submission *

This patch adds the ability to use arbitrary sized vectors from mathutils.
Currently vectors are only of size 2, 3 or 4 since they are generally restricted
to geometric applications. However, we can use arbitrary sized vectors for
efficient calculations and data manipulation.

Modified Paths:
--------------
    trunk/blender/source/blender/blenlib/BLI_math_vector.h
    trunk/blender/source/blender/blenlib/intern/math_vector.c
    trunk/blender/source/blender/python/mathutils/mathutils.c
    trunk/blender/source/blender/python/mathutils/mathutils.h
    trunk/blender/source/blender/python/mathutils/mathutils_Vector.c
    trunk/blender/source/blender/python/mathutils/mathutils_Vector.h

Modified: trunk/blender/source/blender/blenlib/BLI_math_vector.h
===================================================================
--- trunk/blender/source/blender/blenlib/BLI_math_vector.h	2011-12-18 07:11:18 UTC (rev 42701)
+++ trunk/blender/source/blender/blenlib/BLI_math_vector.h	2011-12-18 07:27:11 UTC (rev 42702)
@@ -198,6 +198,7 @@
 float normalize_vn_vn(float *array_tar, const float *array_src, const int size);
 float normalize_vn(float *array_tar, const int size);
 void range_vn_i(int *array_tar, const int size, const int start);
+void range_vn_fl(float *array_tar, const int size, const float start, const float step);
 void negate_vn(float *array_tar, const int size);
 void negate_vn_vn(float *array_tar, const float *array_src, const int size);
 void mul_vn_fl(float *array_tar, const int size, const float f);

Modified: trunk/blender/source/blender/blenlib/intern/math_vector.c
===================================================================
--- trunk/blender/source/blender/blenlib/intern/math_vector.c	2011-12-18 07:11:18 UTC (rev 42701)
+++ trunk/blender/source/blender/blenlib/intern/math_vector.c	2011-12-18 07:27:11 UTC (rev 42702)
@@ -416,6 +416,15 @@
 	while(i--) { *(array_pt--) = j--; }
 }
 
+void range_vn_fl(float *array_tar, const int size, const float start, const float step)
+{
+	float *array_pt= array_tar + (size-1);
+	int i= size;
+	while(i--) {
+		*(array_pt--) = start + step * (float)(i);
+	}
+}
+
 void negate_vn(float *array_tar, const int size)
 {
 	float *array_pt= array_tar + (size-1);

Modified: trunk/blender/source/blender/python/mathutils/mathutils.c
===================================================================
--- trunk/blender/source/blender/python/mathutils/mathutils.c	2011-12-18 07:11:18 UTC (rev 42701)
+++ trunk/blender/source/blender/python/mathutils/mathutils.c	2011-12-18 07:27:11 UTC (rev 42702)
@@ -40,37 +40,14 @@
 "This module provides access to matrices, eulers, quaternions and vectors."
 );
 static int mathutils_array_parse_fast(float *array,
-                                      int array_min, int array_max,
-                                      PyObject *value, const char *error_prefix)
+                                      int size,
+                                      PyObject *value_fast,
+									  const char *error_prefix)
 {
-	PyObject *value_fast= NULL;
 	PyObject *item;
 
-	int i, size;
+	int i;
 
-	/* non list/tuple cases */
-	if (!(value_fast=PySequence_Fast(value, error_prefix))) {
-		/* PySequence_Fast sets the error */
-		return -1;
-	}
-
-	size= PySequence_Fast_GET_SIZE(value_fast);
-
-	if (size > array_max || size < array_min) {
-		if (array_max == array_min)	{
-			PyErr_Format(PyExc_ValueError,
-			             "%.200s: sequence size is %d, expected %d",
-			             error_prefix, size, array_max);
-		}
-		else {
-			PyErr_Format(PyExc_ValueError,
-			             "%.200s: sequence size is %d, expected [%d - %d]",
-			             error_prefix, size, array_min, array_max);
-		}
-		Py_DECREF(value_fast);
-		return -1;
-	}
-
 	i= size;
 	do {
 		i--;
@@ -93,9 +70,10 @@
 /* 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)
 {
-#if 1 /* approx 6x speedup for mathutils types */
 	int size;
 
+#if 1 /* approx 6x speedup for mathutils types */
+
 	if (    (size= VectorObject_Check(value)     ? ((VectorObject *)value)->size : 0) ||
 	        (size= EulerObject_Check(value)      ? 3 : 0) ||
 	        (size= QuaternionObject_Check(value) ? 4 : 0) ||
@@ -125,10 +103,88 @@
 	else
 #endif
 	{
-		return mathutils_array_parse_fast(array, array_min, array_max, value, error_prefix);
+		PyObject *value_fast= NULL;
+
+		/* non list/tuple cases */
+		if (!(value_fast=PySequence_Fast(value, error_prefix))) {
+			/* PySequence_Fast sets the error */
+			return -1;
+		}
+
+		size= PySequence_Fast_GET_SIZE(value_fast);
+
+		if (size > array_max || size < array_min) {
+			if (array_max == array_min)	{
+				PyErr_Format(PyExc_ValueError,
+							 "%.200s: sequence size is %d, expected %d",
+							 error_prefix, size, array_max);
+			}
+			else {
+				PyErr_Format(PyExc_ValueError,
+							 "%.200s: sequence size is %d, expected [%d - %d]",
+							 error_prefix, size, array_min, array_max);
+			}
+			Py_DECREF(value_fast);
+			return -1;
+		}
+
+		return mathutils_array_parse_fast(array, size, value_fast, error_prefix);
 	}
 }
 
+int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix)
+{
+	int size;
+
+#if 1 /* approx 6x speedup for mathutils types */
+
+	if (    (size= VectorObject_Check(value)     ? ((VectorObject *)value)->size : 0) ||
+	        (size= EulerObject_Check(value)      ? 3 : 0) ||
+	        (size= QuaternionObject_Check(value) ? 4 : 0) ||
+	        (size= ColorObject_Check(value)      ? 3 : 0))
+	{
+		if (BaseMath_ReadCallback((BaseMathObject *)value) == -1) {
+			return -1;
+		}
+
+		if (size < array_min) {
+			PyErr_Format(PyExc_ValueError,
+			             "%.200s: sequence size is %d, expected > %d",
+			             error_prefix, size, array_min);
+			return -1;
+		}
+		
+		*array= PyMem_Malloc(size * sizeof(float));
+		memcpy(*array, ((BaseMathObject *)value)->data, size * sizeof(float));
+		return size;
+	}
+	else
+#endif
+	{
+		PyObject *value_fast= NULL;
+		//*array= NULL;
+
+		/* non list/tuple cases */
+		if (!(value_fast=PySequence_Fast(value, error_prefix))) {
+			/* PySequence_Fast sets the error */
+			return -1;
+		}
+
+		size= PySequence_Fast_GET_SIZE(value_fast);
+
+		if (size < array_min) {
+			PyErr_Format(PyExc_ValueError,
+			             "%.200s: sequence size is %d, expected > %d",
+			             error_prefix, size, array_min);
+			return -1;
+		}
+
+		*array= PyMem_Malloc(size * sizeof(float));
+
+		return mathutils_array_parse_fast(*array, size, value_fast, error_prefix);
+	}
+}
+
 int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix)
 {
 	if (EulerObject_Check(value)) {

Modified: trunk/blender/source/blender/python/mathutils/mathutils.h
===================================================================
--- trunk/blender/source/blender/python/mathutils/mathutils.h	2011-12-18 07:11:18 UTC (rev 42701)
+++ trunk/blender/source/blender/python/mathutils/mathutils.h	2011-12-18 07:27:11 UTC (rev 42702)
@@ -115,6 +115,7 @@
 
 /* utility func */
 int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix);
+int mathutils_array_parse_alloc(float **array, int array_min, PyObject *value, const char *error_prefix);
 int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix);
 
 int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat);

Modified: trunk/blender/source/blender/python/mathutils/mathutils_Vector.c
===================================================================
--- trunk/blender/source/blender/python/mathutils/mathutils_Vector.c	2011-12-18 07:11:18 UTC (rev 42701)
+++ trunk/blender/source/blender/python/mathutils/mathutils_Vector.c	2011-12-18 07:27:11 UTC (rev 42702)
@@ -54,15 +54,29 @@
  */
 static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *UNUSED(kwds))
 {
-	float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
+	float *vec= NULL;
 	int size= 3; /* default to a 3D vector */
 
 	switch(PyTuple_GET_SIZE(args)) {
 	case 0:
+		vec= PyMem_Malloc(size * sizeof(float));
+
+		if (vec == NULL) {
+			PyErr_SetString(PyExc_MemoryError,
+							"Vector(): "
+							"problem allocating pointer space");
+			return NULL;
+		}
+
+		fill_vn_fl(vec, size, 0.0f);
 		break;
 	case 1:
-		if ((size=mathutils_array_parse(vec, 2, 4, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1)
+		if ((size=mathutils_array_parse_alloc(&vec, 2, PyTuple_GET_ITEM(args, 0), "mathutils.Vector()")) == -1) {
+			if (vec) {
+				PyMem_Free(vec);
+			}
 			return NULL;
+		}
 		break;
 	default:
 		PyErr_SetString(PyExc_TypeError,
@@ -87,6 +101,215 @@
 	}
 }
 
+/*-----------------------CLASS-METHODS----------------------------*/
+PyDoc_STRVAR(C_Vector_Fill_doc,
+".. classmethod:: Fill(size, fill=0.0)\n"
+"\n"
+"   Create a vector of length size with all values set to fill.\n"
+"\n"
+"   :arg size: The length of the vector to be created.\n"
+"   :type size: int\n"
+"   :arg fill: The value used to fill the vector.\n"
+"   :type fill: float\n"
+);
+static PyObject *C_Vector_Fill(PyObject *cls, PyObject *args)
+{
+	float *vec;
+	int size;
+	float fill= 0.0f;
+
+	if (!PyArg_ParseTuple(args, "i|f:Vector.Fill", &size, &fill)) {
+		return NULL;
+	}
+
+	if (size < 2) {
+		PyErr_SetString(PyExc_RuntimeError,
+		                "Vector(): invalid size");
+		return NULL;
+	}
+
+	vec= PyMem_Malloc(size * sizeof(float));
+
+	if (vec == NULL) {
+		PyErr_SetString(PyExc_MemoryError,
+						"Vector.Fill(): "
+		                "problem allocating pointer space");
+		return NULL;
+	}
+
+	fill_vn_fl(vec, size, fill);
+
+	return Vector_CreatePyObject_alloc(vec, size, (PyTypeObject *)cls);
+}
+
+PyDoc_STRVAR(C_Vector_Range_doc,
+".. classmethod:: Range(start=0, stop, step=1)\n"
+"\n"
+"   Create a filled with a range of values.\n"
+"\n"
+"   :arg start: The start of the range used to fill the vector.\n"
+"   :type start: int\n"
+"   :arg stop: The end of the range used to fill the vector.\n"
+"   :type stop: int\n"
+"   :arg step: The step between successive values in the vector.\n"
+"   :type step: int\n"
+);
+static PyObject *C_Vector_Range(PyObject *cls, PyObject *args)
+{
+	float *vec;
+	int stop, size;
+	int start= 0;
+	int step= 1;
+
+	if (!PyArg_ParseTuple(args, "i|ii:Vector.Range", &start, &stop, &step)) {
+		return NULL;
+	}
+
+	switch(PyTuple_GET_SIZE(args)){
+	case 1:
+		size = start;
+		start= 0;
+		break;
+	case 2:
+		if (start >= stop) {
+			PyErr_SetString(PyExc_RuntimeError,
+		                "Start value is larger"
+						"than the stop value");
+			return NULL;
+		}
+
+		size= stop - start;
+		break;
+	default:
+		if (start >= stop) {
+			PyErr_SetString(PyExc_RuntimeError,
+		                "Start value is larger"
+						"than the stop value");
+			return NULL;
+		}
+		size= (stop - start)/step;
+		if (size%step)
+			size++;
+		break;
+	}
+
+	vec= PyMem_Malloc(size * sizeof(float));
+
+	if (vec == NULL) {
+		PyErr_SetString(PyExc_MemoryError,
+						"Vector.Range(): "
+		                "problem allocating pointer space");
+		return NULL;
+	}
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list