+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

Reply via email to