diff options
author | Campbell Barton <ideasman42@gmail.com> | 2010-01-25 12:44:04 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2010-01-25 12:44:04 +0300 |
commit | 0a0f4c9d81cfa2a4b4a9999e1dc976bc417d7d54 (patch) | |
tree | 367f259b695955a514530d125ab495344724eafb /source/blender/python/generic/vector.c | |
parent | eed13d859b67185996569178ede9241a5695f215 (diff) |
Mathutils refactor & include in sphinx generated docs, (TODO, include getset'ers in docs)
- Mathutils.MidpointVecs --> vector.lerp(other, fac)
- Mathutils.AngleBetweenVecs --> vector.angle(other)
- Mathutils.ProjectVecs --> vector.project(other)
- Mathutils.DifferenceQuats --> quat.difference(other)
- Mathutils.Slerp --> quat.slerp(other, fac)
- Mathutils.Rand: removed, use pythons random module
- Mathutils.RotationMatrix(angle, size, axis_flag, axis) --> Mathutils.RotationMatrix(angle, size, axis); merge axis & axis_flag args
- Matrix.scalePart --> Matrix.scale_part
- Matrix.translationPart --> Matrix.translation_part
- Matrix.rotationPart --> Matrix.rotation_part
- toMatrix --> to_matrix
- toEuler --> to_euler
- toQuat --> to_quat
- Vector.toTrackQuat --> Vector.to_track_quat
Diffstat (limited to 'source/blender/python/generic/vector.c')
-rw-r--r-- | source/blender/python/generic/vector.c | 446 |
1 files changed, 332 insertions, 114 deletions
diff --git a/source/blender/python/generic/vector.c b/source/blender/python/generic/vector.c index 862b7338ac0..558e4aac9c9 100644 --- a/source/blender/python/generic/vector.c +++ b/source/blender/python/generic/vector.c @@ -41,37 +41,6 @@ static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat); /* utility func */ -/*-----------------------METHOD DEFINITIONS ----------------------*/ -static PyObject *Vector_Zero( VectorObject * self ); -static PyObject *Vector_Normalize( VectorObject * self ); -static PyObject *Vector_Negate( VectorObject * self ); -static PyObject *Vector_Resize2D( VectorObject * self ); -static PyObject *Vector_Resize3D( VectorObject * self ); -static PyObject *Vector_Resize4D( VectorObject * self ); -static PyObject *Vector_ToTuple( VectorObject * self, PyObject *value ); -static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ); -static PyObject *Vector_Reflect( VectorObject *self, VectorObject *value ); -static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ); -static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ); -static PyObject *Vector_copy( VectorObject * self ); - -static struct PyMethodDef Vector_methods[] = { - {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, NULL}, - {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, NULL}, - {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, NULL}, - {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, NULL}, - {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, NULL}, - {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, NULL}, - {"toTuple", (PyCFunction) Vector_ToTuple, METH_O, NULL}, - {"toTrackQuat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, NULL}, - {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, NULL}, - {"cross", ( PyCFunction ) Vector_Cross, METH_O, NULL}, - {"dot", ( PyCFunction ) Vector_Dot, METH_O, NULL}, - {"copy", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, - {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, - {NULL, NULL, 0, NULL} -}; - //----------------------------------Mathutils.Vector() ------------------ // Supports 2D, 3D, and 4D vector objects both int and float values // accepted. Mixed float and int values accepted. Ints are parsed to float @@ -124,8 +93,13 @@ static PyObject *Vector_new(PyTypeObject *type, PyObject *args, PyObject *kwds) } /*-----------------------------METHODS---------------------------- */ -/*----------------------------Vector.zero() ---------------------- - set the vector data to 0,0,0 */ +static char Vector_Zero_doc[] = +".. method:: zero()\n" +"\n" +" Set all values to zero.\n" +" :return: an instance of itself\n" +" :rtype: vector\n"; + static PyObject *Vector_Zero(VectorObject * self) { int i; @@ -137,8 +111,18 @@ static PyObject *Vector_Zero(VectorObject * self) Py_INCREF(self); return (PyObject*)self; } -/*----------------------------Vector.normalize() ----------------- - normalize the vector data to a unit vector */ +/*----------------------------Vector.normalize() ----------------- */ +static char Vector_Normalize_doc[] = +".. method:: normalize()\n" +"\n" +" Normalize the vector, making the length of the vector always 1.0.\n" +" :return: an instance of itself\n" +" :rtype: vector\n" +"\n" +" .. warning:: Normalizing a vector where all values are zero results in all axis having a nan value (not a number).\n" +"\n" +" .. note:: Normalize works for vectors of all sizes, however 4D Vectors w axis is left untouched.\n"; + static PyObject *Vector_Normalize(VectorObject * self) { int i; @@ -161,8 +145,14 @@ static PyObject *Vector_Normalize(VectorObject * self) } -/*----------------------------Vector.resize2D() ------------------ - resize the vector to x,y */ +/*----------------------------Vector.resize2D() ------------------ */ +static char Vector_Resize2D_doc[] = +".. method:: resize2D()\n" +"\n" +" Resize the vector to 2D (x, y).\n" +" :return: an instance of itself\n" +" :rtype: vector\n"; + static PyObject *Vector_Resize2D(VectorObject * self) { if(self->wrapped==Py_WRAP) { @@ -184,8 +174,14 @@ static PyObject *Vector_Resize2D(VectorObject * self) Py_INCREF(self); return (PyObject*)self; } -/*----------------------------Vector.resize3D() ------------------ - resize the vector to x,y,z */ +/*----------------------------Vector.resize3D() ------------------ */ +static char Vector_Resize3D_doc[] = +".. method:: resize3D()\n" +"\n" +" Resize the vector to 3D (x, y, z).\n" +" :return: an instance of itself\n" +" :rtype: vector\n"; + static PyObject *Vector_Resize3D(VectorObject * self) { if (self->wrapped==Py_WRAP) { @@ -210,8 +206,14 @@ static PyObject *Vector_Resize3D(VectorObject * self) Py_INCREF(self); return (PyObject*)self; } -/*----------------------------Vector.resize4D() ------------------ - resize the vector to x,y,z,w */ +/*----------------------------Vector.resize4D() ------------------ */ +static char Vector_Resize4D_doc[] = +".. method:: resize4D()\n" +"\n" +" Resize the vector to 4D (x, y, z, w).\n" +" :return: an instance of itself\n" +" :rtype: vector\n"; + static PyObject *Vector_Resize4D(VectorObject * self) { if(self->wrapped==Py_WRAP) { @@ -239,8 +241,17 @@ static PyObject *Vector_Resize4D(VectorObject * self) return (PyObject*)self; } -/*----------------------------Vector.resize4D() ------------------ - resize the vector to x,y,z,w */ +/*----------------------------Vector.toTuple() ------------------ */ +static char Vector_ToTuple_doc[] = +".. method:: to_tuple(precision)\n" +"\n" +" Return this vector as a tuple with.\n" +"\n" +" :arg precision: The number to round the value to in [0, 21].\n" +" :type precision: int\n" +" :return: the values of the vector rounded by *precision*\n" +" :rtype: tuple\n"; + static PyObject *Vector_ToTuple(VectorObject * self, PyObject *value) { int ndigits= PyLong_AsSsize_t(value); @@ -265,8 +276,19 @@ static PyObject *Vector_ToTuple(VectorObject * self, PyObject *value) return ret; } -/*----------------------------Vector.toTrackQuat(track, up) ---------------------- - extract a quaternion from the vector and the track and up axis */ +/*----------------------------Vector.toTrackQuat(track, up) ---------------------- */ +static char Vector_ToTrackQuat_doc[] = +".. method:: to_track_quat(track, up)\n" +"\n" +" Return a quaternion rotation from the vector and the track and up axis.\n" +"\n" +" :arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].\n" +" :type track: string\n" +" :arg up: Up axis in ['X', 'Y', 'Z'].\n" +" :type up: string\n" +" :return: rotation from the vector and the track and up axis." +" :rtype: Quaternion\n"; + static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) { float vec[3], quat[4]; @@ -290,14 +312,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) if (strack[0] == '-') { switch(strack[1]) { case 'X': - case 'x': track = 3; break; case 'Y': - case 'y': track = 4; break; - case 'z': case 'Z': track = 5; break; @@ -315,14 +334,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) switch(strack[0]) { case '-': case 'X': - case 'x': track = 0; break; case 'Y': - case 'y': track = 1; break; - case 'z': case 'Z': track = 2; break; @@ -341,14 +357,11 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) if (strlen(sup) == 1) { switch(*sup) { case 'X': - case 'x': up = 0; break; - case 'Y': case 'y': up = 1; break; - case 'z': case 'Z': up = 2; break; @@ -385,6 +398,16 @@ static PyObject *Vector_ToTrackQuat( VectorObject * self, PyObject * args ) return a reflected vector on the mirror normal vec - ((2 * DotVecs(vec, mirror)) * mirror) */ +static char Vector_Reflect_doc[] = +".. method:: reflect(mirror)\n" +"\n" +" Return the reflection vector from the *mirror* argument.\n" +"\n" +" :arg mirror: This vector could be a normal from the reflecting surface.\n" +" :type mirror: vector\n" +" :return: The reflected vector.\n" +" :rtype: Vector object matching the size of this vector.\n"; + static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value ) { float mirror[3], vec[3]; @@ -414,6 +437,18 @@ static PyObject *Vector_Reflect( VectorObject * self, VectorObject * value ) return newVectorObject(reflect, self->size, Py_NEW, NULL); } +static char Vector_Cross_doc[] = +".. method:: cross(other)\n" +"\n" +" Return the cross product of this vector and another.\n" +"\n" +" :arg other: The other vector to perform the cross product with.\n" +" :type other: vector\n" +" :return: The cross product.\n" +" :rtype: Vector\n" +"\n" +" .. note:: both vectors must be 3D\n"; + static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ) { VectorObject *vecCross = NULL; @@ -436,6 +471,16 @@ static PyObject *Vector_Cross( VectorObject * self, VectorObject * value ) return (PyObject *)vecCross; } +static char Vector_Dot_doc[] = +".. method:: dot(other)\n" +"\n" +" Return the dot product of this vector and another.\n" +"\n" +" :arg other: The other vector to perform the dot product with.\n" +" :type other: vector\n" +" :return: The dot product.\n" +" :rtype: Vector\n"; + static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ) { double dot = 0.0; @@ -460,8 +505,156 @@ static PyObject *Vector_Dot( VectorObject * self, VectorObject * value ) return PyFloat_FromDouble(dot); } -/*----------------------------Vector.copy() -------------------------------------- - return a copy of the vector */ +static char Vector_Angle_doc[] = +".. function:: angle(other)\n" +"\n" +" Return the angle between two vectors.\n" +"\n" +" :type other: vector\n" +" :return angle: angle in radians\n" +" :rtype: float\n" +"\n" +" .. note:: Zero length vectors raise an :exc:`AttributeError`.\n"; +static PyObject *Vector_Angle(VectorObject * self, VectorObject * value) +{ + double dot = 0.0f, angleRads, test_v1 = 0.0f, test_v2 = 0.0f; + int x, size; + + if (!VectorObject_Check(value)) { + PyErr_SetString( PyExc_TypeError, "vec.angle(value): expected a vector argument" ); + return NULL; + } + + if(self->size != value->size) { + PyErr_SetString(PyExc_AttributeError, "vec.angle(value): expects both vectors to have the same size\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + + //since size is the same.... + size = self->size; + + for(x = 0; x < size; x++) { + test_v1 += self->vec[x] * self->vec[x]; + test_v2 += value->vec[x] * value->vec[x]; + } + if (!test_v1 || !test_v2){ + PyErr_SetString(PyExc_AttributeError, "vector.angle(other): zero length vectors are not acceptable arguments\n"); + return NULL; + } + + //dot product + for(x = 0; x < size; x++) { + dot += self->vec[x] * value->vec[x]; + } + dot /= (sqrt(test_v1) * sqrt(test_v2)); + + angleRads = (double)saacos(dot); + +#ifdef USE_MATHUTILS_DEG + return PyFloat_FromDouble(angleRads * (180/ Py_PI)); +#else + return PyFloat_FromDouble(angleRads); +#endif +} + +static char Vector_Project_doc[] = +".. function:: project(other)\n" +"\n" +" Return the projection of this vector onto the *other*.\n" +"\n" +" :type other: vector\n" +" :return projection: the parallel projection vector\n" +" :rtype: vector\n"; + +static PyObject *Vector_Project(VectorObject * self, VectorObject * value) +{ + float vec[4]; + double dot = 0.0f, dot2 = 0.0f; + int x, size; + + if (!VectorObject_Check(value)) { + PyErr_SetString( PyExc_TypeError, "vec.project(value): expected a vector argument" ); + return NULL; + } + + if(self->size != value->size) { + PyErr_SetString(PyExc_AttributeError, "vec.project(value): expects both vectors to have the same size\n"); + return NULL; + } + + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(value)) + return NULL; + + + //since they are the same size... + size = self->size; + + //get dot products + for(x = 0; x < size; x++) { + dot += self->vec[x] * value->vec[x]; + dot2 += value->vec[x] * value->vec[x]; + } + //projection + dot /= dot2; + for(x = 0; x < size; x++) { + vec[x] = (float)(dot * value->vec[x]); + } + return newVectorObject(vec, size, Py_NEW, NULL); +} + +//----------------------------------Mathutils.MidpointVecs() ------------- +static char Vector_Lerp_doc[] = +".. function:: lerp(other, factor)\n" +"\n" +" Returns the interpolation of two vectors.\n" +"\n" +" :arg other: value to interpolate with.\n" +" :type other: Vector\n" +" :arg factor: The interpolation value in [0.0, 1.0].\n" +" :type factor: float\n" +" :return: The interpolated rotation.\n" +" :rtype: Vector\n"; + +static PyObject *Vector_Lerp(VectorObject * self, PyObject * args) +{ + VectorObject *vec2 = NULL; + float fac, ifac, vec[4]; + int x; + + if(!PyArg_ParseTuple(args, "O!f", &vector_Type, &vec2, &fac)) { + PyErr_SetString(PyExc_TypeError, "vector.lerp(): expects a vector of the same size and float"); + return NULL; + } + if(self->size != vec2->size) { + PyErr_SetString(PyExc_AttributeError, "Mathutils.MidpointVecs(): expects (2) vector objects of the same size"); + return NULL; + } + + if(!BaseMath_ReadCallback(self) || !BaseMath_ReadCallback(vec2)) + return NULL; + + ifac= 1.0 - fac; + + for(x = 0; x < self->size; x++) { + vec[x] = (ifac * self->vec[x]) + (fac * vec2->vec[x]); + } + return newVectorObject(vec, self->size, Py_NEW, NULL); +} + +/*----------------------------Vector.copy() -------------------------------------- */ +static char Vector_copy_doc[] = +".. function:: copy()\n" +"\n" +" Returns a copy of this vector.\n" +"\n" +" :return: A copy of the vector.\n" +" :rtype: Vector\n" +"\n" +" .. note:: use this to get a copy of a wrapped vector with no reference to the original data.\n"; + static PyObject *Vector_copy(VectorObject * self) { if(!BaseMath_ReadCallback(self)) @@ -1808,7 +2001,87 @@ if len(unique) != len(items): */ +//-----------------row_vector_multiplication (internal)----------- +//ROW VECTOR Multiplication - Vector X Matrix +//[x][y][z] * [1][4][7] +// [2][5][8] +// [3][6][9] +//vector/matrix multiplication IS NOT COMMUTATIVE!!!! +static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) +{ + float vecNew[4], vecCopy[4]; + double dot = 0.0f; + int x, y, z = 0, vec_size = vec->size; + + if(mat->colSize != vec_size){ + if(mat->colSize == 4 && vec_size != 3){ + PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); + return NULL; + }else{ + vecCopy[3] = 1.0f; + } + } + + if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat)) + return NULL; + + for(x = 0; x < vec_size; x++){ + vecCopy[x] = vec->vec[x]; + } + vecNew[3] = 1.0f; + //muliplication + for(x = 0; x < mat->rowSize; x++) { + for(y = 0; y < mat->colSize; y++) { + dot += mat->matrix[x][y] * vecCopy[y]; + } + vecNew[z++] = (float)dot; + dot = 0.0f; + } + return newVectorObject(vecNew, vec_size, Py_NEW, NULL); +} + +/*----------------------------Vector.negate() -------------------- */ +static char Vector_Negate_doc[] = +".. method:: negate()\n" +"\n" +" Set all values to their negative.\n" +" :return: an instance of itself\n" +" :rtype: vector\n"; +static PyObject *Vector_Negate(VectorObject * self) +{ + int i; + if(!BaseMath_ReadCallback(self)) + return NULL; + + for(i = 0; i < self->size; i++) + self->vec[i] = -(self->vec[i]); + + BaseMath_WriteCallback(self); // alredy checked for error + + Py_INCREF(self); + return (PyObject*)self; +} + +static struct PyMethodDef Vector_methods[] = { + {"zero", (PyCFunction) Vector_Zero, METH_NOARGS, Vector_Zero_doc}, + {"normalize", (PyCFunction) Vector_Normalize, METH_NOARGS, Vector_Normalize_doc}, + {"negate", (PyCFunction) Vector_Negate, METH_NOARGS, Vector_Negate_doc}, + {"resize2D", (PyCFunction) Vector_Resize2D, METH_NOARGS, Vector_Resize2D_doc}, + {"resize3D", (PyCFunction) Vector_Resize3D, METH_NOARGS, Vector_Resize3D_doc}, + {"resize4D", (PyCFunction) Vector_Resize4D, METH_NOARGS, Vector_Resize4D_doc}, + {"to_tuple", (PyCFunction) Vector_ToTuple, METH_O, Vector_ToTuple_doc}, + {"to_track_quat", ( PyCFunction ) Vector_ToTrackQuat, METH_VARARGS, Vector_ToTrackQuat_doc}, + {"reflect", ( PyCFunction ) Vector_Reflect, METH_O, Vector_Reflect_doc}, + {"cross", ( PyCFunction ) Vector_Cross, METH_O, Vector_Cross_doc}, + {"dot", ( PyCFunction ) Vector_Dot, METH_O, Vector_Dot_doc}, + {"angle", ( PyCFunction ) Vector_Angle, METH_O, Vector_Angle_doc}, + {"project", ( PyCFunction ) Vector_Project, METH_O, Vector_Project_doc}, + {"lerp", ( PyCFunction ) Vector_Lerp, METH_VARARGS, Vector_Lerp_doc}, + {"copy", (PyCFunction) Vector_copy, METH_NOARGS, Vector_copy_doc}, + {"__copy__", (PyCFunction) Vector_copy, METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL} +}; /* Note @@ -1817,6 +2090,8 @@ if len(unique) != len(items): vec*mat and mat*vec both get sent to Vector_mul and it neesd to sort out the order */ +static char vector_doc[] = "This object gives access to Vectors in Blender."; + PyTypeObject vector_Type = { PyVarObject_HEAD_INIT(NULL, 0) /* For printing, in format "<module>.<name>" */ @@ -1852,7 +2127,7 @@ PyTypeObject vector_Type = { /*** Flags to define presence of optional/expanded features ***/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, - NULL, /* char *tp_doc; Documentation string */ + vector_doc, /* char *tp_doc; Documentation string */ /*** Assigned meaning in release 2.0 ***/ /* call function for all accessible objects */ NULL, /* traverseproc tp_traverse; */ @@ -1897,7 +2172,6 @@ PyTypeObject vector_Type = { NULL }; - /*------------------------newVectorObject (internal)------------- creates a new vector object pass Py_WRAP - if vector is a WRAPPER for data allocated by BLENDER @@ -1956,59 +2230,3 @@ PyObject *newVectorObject_cb(PyObject *cb_user, int size, int cb_type, int cb_su return (PyObject *)self; } - -//-----------------row_vector_multiplication (internal)----------- -//ROW VECTOR Multiplication - Vector X Matrix -//[x][y][z] * [1][4][7] -// [2][5][8] -// [3][6][9] -//vector/matrix multiplication IS NOT COMMUTATIVE!!!! -static PyObject *row_vector_multiplication(VectorObject* vec, MatrixObject * mat) -{ - float vecNew[4], vecCopy[4]; - double dot = 0.0f; - int x, y, z = 0, vec_size = vec->size; - - if(mat->colSize != vec_size){ - if(mat->colSize == 4 && vec_size != 3){ - PyErr_SetString(PyExc_AttributeError, "vector * matrix: matrix column size and the vector size must be the same"); - return NULL; - }else{ - vecCopy[3] = 1.0f; - } - } - - if(!BaseMath_ReadCallback(vec) || !BaseMath_ReadCallback(mat)) - return NULL; - - for(x = 0; x < vec_size; x++){ - vecCopy[x] = vec->vec[x]; - } - vecNew[3] = 1.0f; - //muliplication - for(x = 0; x < mat->rowSize; x++) { - for(y = 0; y < mat->colSize; y++) { - dot += mat->matrix[x][y] * vecCopy[y]; - } - vecNew[z++] = (float)dot; - dot = 0.0f; - } - return newVectorObject(vecNew, vec_size, Py_NEW, NULL); -} - -/*----------------------------Vector.negate() -------------------- - set the vector to it's negative -x, -y, -z */ -static PyObject *Vector_Negate(VectorObject * self) -{ - int i; - if(!BaseMath_ReadCallback(self)) - return NULL; - - for(i = 0; i < self->size; i++) - self->vec[i] = -(self->vec[i]); - - BaseMath_WriteCallback(self); // alredy checked for error - - Py_INCREF(self); - return (PyObject*)self; -} |