+1 on the changes, with some qualifications: -for qualifying in place vs. returning new, whatabout verb/noun instead of present/past tense of verb: matrix.invert() inverts the matrix, returns none matrix.inverse() returns the new inverse matrix.
in the rename methods we go from translation_part() to to_translation() however, (nit picking) the 'to' implies that the matrix is being changed, we are getting into the same region of ambiguity that you were attempting to solve in the earlier example. a suggustion is to use the verb 'derive' as in : matrix.derive_quaternion() matrix.derive_translation() or some other similar verb. cheers Bassam On Thu, 2011-02-03 at 21:54 +0000, Campbell Barton wrote: > On Thu, Feb 3, 2011 at 11:25 AM, Alex Fraser <[email protected]> wrote: > > On Thu, Feb 3, 2011 at 10:08 PM, Campbell Barton <[email protected]> > > wrote: > >> Here are some proposed changes to the mathutils API I'd like to make > > > > As discussed on IRC, these changes look fine to me. One more > > suggestion: can we allow vector components to be specified without the > > use of a tuple, i.e. Vector(x,y,z) instead of Vector((x,y,z))? > > > > Cheers, > > Alex (z0r) > > Short answer is it doesn't make sense for Vectors to have one triple > arg, so - we could. > > Longer answer: > > The reason I made this change is that Quaternions and Eulers have > optional arguments which are more cumbersome to parse in C (see > example below) > > Since if we support both we would want to allow the same for other types: eg. > Quaternion(w, x, y, z) # 2.4x, NOT SUPPORTED IN 2.5x > Quaternion((w, x, y, z)) > Quaternion((x, y, z), angle) > Quaternion(someOtherQuat) > > Euler(x, y, z) # 2.4x, NOT SUPPORTED IN 2.5x > Euler((x, y, z)) > Euler((x, y, z), 'ZXY') > Euler(x, y, z, 'ZXY') # 2.4x didnt have order argument but perhaps > this would be expected to work too? > Euler(someOtherEuler) > > Since quats have axis/angle and eulers have optional order argument > there needs to be checks for argument lengths '0, 1, 2, 4' for quats, > and '0, 1, 2, 3, (possibly) 4' for eulers. > > The likelyhood we add new arguments to , Vector(x,y,z,w) is low so it > could be an exception, but then its confusing as to why Vector(x,y,z) > and Euler(x,y,z) doesn't. > > My preference is to have consistency between types rather then have > Vector() as the exception, even though I can see its a bit annoying. > > To see what I mean about sloppy argument parsing, see comparison of > 2.4x and 2.5x code below - both the same function though 2.5x uses > mathutils_array_parse() utility function. > The 2.4x code even had a memory leak for some time (refcount error). > > # --- 2.5x Code > static PyObject *Quaternion_new(PyTypeObject *type, PyObject *args, > PyObject *kwds) > { > PyObject *seq= NULL; > double angle = 0.0f; > float quat[QUAT_SIZE]= {0.0f, 0.0f, 0.0f, 0.0f}; > > if(kwds && PyDict_Size(kwds)) { > PyErr_SetString(PyExc_TypeError, "mathutils.Quaternion(): takes > no > keyword args"); > return NULL; > } > > if(!PyArg_ParseTuple(args, "|Od:mathutils.Quaternion", &seq, &angle)) > return NULL; > > switch(PyTuple_GET_SIZE(args)) { > case 0: > break; > case 1: > if (mathutils_array_parse(quat, QUAT_SIZE, QUAT_SIZE, seq, > "mathutils.Quaternion()") == -1) > return NULL; > break; > case 2: > if (mathutils_array_parse(quat, 3, 3, seq, > "mathutils.Quaternion()") == -1) > return NULL; > angle= fmod(angle + M_PI*2, M_PI*4) - M_PI*2; /* clamp because > of > precision issues */ > axis_angle_to_quat(quat, quat, angle); > break; > /* PyArg_ParseTuple assures no more then 2 */ > } > return newQuaternionObject(quat, Py_NEW, type); > } > > > > > # --- 2.4x Code: > PyObject *M_Mathutils_Quaternion(PyObject * self, PyObject * args) > { > PyObject *listObject = NULL, *n, *q, *f; > int size, i; > float quat[4]; > double norm = 0.0f, angle = 0.0f; > > size = PySequence_Length(args); > if (size == 1 || size == 2) { //seq? > listObject = PySequence_GetItem(args, 0); > if (PySequence_Check(listObject)) { > size = PySequence_Length(listObject); > if ((size == 4 && PySequence_Length(args) !=1) || > (size == 3 && PySequence_Length(args) !=2) || > (size >4 || size < 3)) { > // invalid args/size > Py_DECREF(listObject); > PyErr_SetString(PyExc_AttributeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > if(size == 3){ //get angle in axis/angle > n = PySequence_GetItem(args, 1); > if(n == NULL) { // parsed item not a number or > getItem fail > Py_DECREF(listObject); > PyErr_SetString(PyExc_TypeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > > angle = PyFloat_AsDouble(n); > Py_DECREF(n); > > if (angle==-1 && PyErr_Occurred()) { > Py_DECREF(listObject); > PyErr_SetString(PyExc_TypeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > } > }else{ > Py_DECREF(listObject); /* assume the list is teh second > arg */ > listObject = PySequence_GetItem(args, 1); > if (size>1 && PySequence_Check(listObject)) { > size = PySequence_Length(listObject); > if (size != 3) { > // invalid args/size > Py_DECREF(listObject); > PyErr_SetString(PyExc_AttributeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > n = PySequence_GetItem(args, 0); > if(n == NULL) { // parsed item not a number or > getItem fail > Py_DECREF(listObject); > PyErr_SetString(PyExc_TypeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > angle = PyFloat_AsDouble(n); > Py_DECREF(n); > > if (angle==-1 && PyErr_Occurred()) { > Py_DECREF(listObject); > PyErr_SetString(PyExc_TypeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > } else { // argument was not a sequence > Py_XDECREF(listObject); > PyErr_SetString(PyExc_TypeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > } > } else if (size == 0) { //returns a new empty quat > return newQuaternionObject(NULL, Py_NEW); > } else { > Py_INCREF(args); > listObject = args; > } > > if (size == 3) { // invalid quat size > if(PySequence_Length(args) != 2){ > Py_DECREF(listObject); > PyErr_SetString(PyExc_AttributeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > }else{ > if(size != 4){ > Py_DECREF(listObject); > PyErr_SetString(PyExc_AttributeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > } > > for (i=0; i<size; i++) { //parse > q = PySequence_GetItem(listObject, i); > if (q == NULL) { // Failed to read sequence > Py_DECREF(listObject); > PyErr_SetString(PyExc_RuntimeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > > f = PyNumber_Float(q); > if(f == NULL) { // parsed item not a number > Py_DECREF(q); > Py_DECREF(listObject); > PyErr_SetString(PyExc_TypeError, > "Mathutils.Quaternion(): 4d > numeric sequence expected or 3d vector and number\n"); > return NULL; > } > > quat[i] = (float)PyFloat_AS_DOUBLE(f); > Py_DECREF(f); > Py_DECREF(q); > } > if(size == 3){ //calculate the quat based on axis/angle > norm = sqrt(quat[0] * quat[0] + quat[1] * quat[1] + quat[2] * > quat[2]); > quat[0] /= (float)norm; > quat[1] /= (float)norm; > quat[2] /= (float)norm; > > angle = angle * (Py_PI / 180); > quat[3] =(float) (sin(angle/ 2.0f)) * quat[2]; > quat[2] =(float) (sin(angle/ 2.0f)) * quat[1]; > quat[1] =(float) (sin(angle/ 2.0f)) * quat[0]; > quat[0] =(float) (cos(angle/ 2.0f)); > } > > Py_DECREF(listObject); > return newQuaternionObject(quat, Py_NEW); > } > _______________________________________________ Bf-committers mailing list [email protected] http://lists.blender.org/mailman/listinfo/bf-committers
