Added some equvalency tests for the other math objects
authorJoseph Gilbert <ascotan@gmail.com>
Tue, 22 Nov 2005 17:59:49 +0000 (17:59 +0000)
committerJoseph Gilbert <ascotan@gmail.com>
Tue, 22 Nov 2005 17:59:49 +0000 (17:59 +0000)
* ==, != are defined for matrix, quat, euler.

source/blender/python/api2_2x/doc/Mathutils.py
source/blender/python/api2_2x/euler.c
source/blender/python/api2_2x/gen_utils.c
source/blender/python/api2_2x/gen_utils.h
source/blender/python/api2_2x/matrix.c
source/blender/python/api2_2x/quat.c
source/blender/python/api2_2x/vector.c

index e2440aa9020bc1ef3eae44d465f4c4e76541351c..4b00d0458250d6261d2b4c4b46ba484575805233 100644 (file)
@@ -522,6 +522,8 @@ class Euler:
   @ivar wrapped: Whether or not this object is wrapping data directly
   @note: You can access a euler object like a sequence
       - x = euler[0]
+  @note: Comparison operators can be done:
+      - ==, != test numeric values within epsilon
   @attention: Euler data can be wrapped or non-wrapped. When a object is wrapped it
   means that the object will give you direct access to the data inside of blender. Modification
   of this object will directly change the data inside of blender. To copy a wrapped object
@@ -594,6 +596,8 @@ class Quaternion:
   @ivar axis: Vector representing the axis of rotation.
   @ivar angle: A scalar representing the amount of rotation
   in degrees.
+  @note: Comparison operators can be done:
+      - ==, != test numeric values within epsilon
   @note: Math can be performed on Quaternion classes
       - quat + quat
       - quat - quat 
@@ -699,6 +703,8 @@ class Matrix:
       - mat * float/int
       - mat * vec
       - mat * mat 
+  @note: Comparison operators can be done:
+      - ==, != test numeric values within epsilon
   @note: You can access a quaternion object like a 2d sequence
       - x = matrix[0][1]
       - vector = matrix[2]
index 3ea0e30d56c73d82b9e46601cc1d64770830a2ca..99855f93b0dcc5bd1c68cd7d7f15fe597ab23658 100644 (file)
@@ -248,6 +248,47 @@ static PyObject *Euler_repr(EulerObject * self)
 
        return PyString_FromString(str);
 }
+//------------------------tp_richcmpr
+//returns -1 execption, 0 false, 1 true
+static PyObject* Euler_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+       EulerObject *eulA = NULL, *eulB = NULL;
+       int result = 0;
+
+       if (!EulerObject_Check(objectA) || !EulerObject_Check(objectB)){
+               if (comparison_type == Py_NE){
+                       return EXPP_incr_ret(Py_True); 
+               }else{
+                       return EXPP_incr_ret(Py_False);
+               }
+       }
+       eulA = (EulerObject*)objectA;
+       eulB = (EulerObject*)objectB;
+
+       switch (comparison_type){
+               case Py_EQ:
+                       result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
+                       break;
+               case Py_NE:
+                       result = EXPP_VectorsAreEqual(eulA->eul, eulB->eul, 3, 1);
+                       if (result == 0){
+                               result = 1;
+                       }else{
+                               result = 0;
+                       }
+                       break;
+               default:
+                       printf("The result of the comparison could not be evaluated");
+                       break;
+       }
+       if (result == 1){
+               return EXPP_incr_ret(Py_True);
+       }else{
+               return EXPP_incr_ret(Py_False);
+       }
+}
+//------------------------tp_doc
+static char EulerObject_doc[] = "This is a wrapper for euler objects.";
 //---------------------SEQUENCE PROTOCOLS------------------------
 //----------------------------len(object)------------------------
 //sequence length
@@ -360,19 +401,53 @@ static PySequenceMethods Euler_SeqMethods = {
 };
 //------------------PY_OBECT DEFINITION--------------------------
 PyTypeObject euler_Type = {
-       PyObject_HEAD_INIT(NULL) 
-       0,                                                                                      /*ob_size */
-       "euler",                                                                        /*tp_name */
-       sizeof(EulerObject),                                            /*tp_basicsize */
-       0,                                                                                      /*tp_itemsize */
-       (destructor) Euler_dealloc,                                     /*tp_dealloc */
-       (printfunc) 0,                                                          /*tp_print */
-       (getattrfunc) Euler_getattr,                            /*tp_getattr */
-       (setattrfunc) Euler_setattr,                            /*tp_setattr */
-       0,                                                                                      /*tp_compare */
-       (reprfunc) Euler_repr,                                          /*tp_repr */
-       0,                                                                                      /*tp_as_number */
-       &Euler_SeqMethods,                                                      /*tp_as_sequence */
+       PyObject_HEAD_INIT(NULL)                //tp_head
+       0,                                                              //tp_internal
+       "euler",                                                //tp_name
+       sizeof(EulerObject),                    //tp_basicsize
+       0,                                                              //tp_itemsize
+       (destructor)Euler_dealloc,              //tp_dealloc
+       0,                                                              //tp_print
+       (getattrfunc)Euler_getattr,     //tp_getattr
+       (setattrfunc) Euler_setattr,    //tp_setattr
+       0,                                                              //tp_compare
+       (reprfunc) Euler_repr,                  //tp_repr
+       0,                              //tp_as_number
+       &Euler_SeqMethods,                              //tp_as_sequence
+       0,                                                              //tp_as_mapping
+       0,                                                              //tp_hash
+       0,                                                              //tp_call
+       0,                                                              //tp_str
+       0,                                                              //tp_getattro
+       0,                                                              //tp_setattro
+       0,                                                              //tp_as_buffer
+       Py_TPFLAGS_DEFAULT,                             //tp_flags
+       EulerObject_doc,                                //tp_doc
+       0,                                                              //tp_traverse
+       0,                                                              //tp_clear
+       (richcmpfunc)Euler_richcmpr,    //tp_richcompare
+       0,                                                              //tp_weaklistoffset
+       0,                                                              //tp_iter
+       0,                                                              //tp_iternext
+       0,                                                              //tp_methods
+       0,                                                              //tp_members
+       0,                                                              //tp_getset
+       0,                                                              //tp_base
+       0,                                                              //tp_dict
+       0,                                                              //tp_descr_get
+       0,                                                              //tp_descr_set
+       0,                                                              //tp_dictoffset
+       0,                                                              //tp_init
+       0,                                                              //tp_alloc
+       0,                                                              //tp_new
+       0,                                                              //tp_free
+       0,                                                              //tp_is_gc
+       0,                                                              //tp_bases
+       0,                                                              //tp_mro
+       0,                                                              //tp_cache
+       0,                                                              //tp_subclasses
+       0,                                                              //tp_weaklist
+       0                                                               //tp_del
 };
 //------------------------newEulerObject (internal)-------------
 //creates a new euler object
index b88d8e2201004dab58ac6c300c573dba7768fd0d..de29e4ba001a738f6461b434f16d608a5f293c61 100644 (file)
 
 #include "constant.h"
 
+//---------------------- EXPP_FloatsAreEqual -------------------------
+//Floating point comparisons 
+//floatStep = number of representable floats allowable in between
+// float A and float B to be considered equal.
+int EXPP_FloatsAreEqual(float A, float B, int floatSteps)
+{
+       int a, b, delta;
+    assert(floatSteps > 0 && floatSteps < (4 * 1024 * 1024));
+    a = *(int*)&A;
+    if (a < 0) 
+               a = 0x80000000 - a;
+    b = *(int*)&B;
+    if (b < 0) 
+               b = 0x80000000 - b;
+    delta = abs(a - b);
+    if (delta <= floatSteps)   
+               return 1;
+    return 0;
+}
+//---------------------- EXPP_VectorsAreEqual -------------------------
+//Builds on EXPP_FloatsAreEqual to test vectors
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps){
+
+       int x;
+       for (x=0; x< size; x++){
+               if (EXPP_FloatsAreEqual(vecA[x], vecB[x], floatSteps) == 0)
+                       return 0;
+       }
+       return 1;
+}
 //---------------------- EXPP_GetModuleConstant -------------------------
 //Helper function for returning a module constant
 PyObject *EXPP_GetModuleConstant(char *module, char *constant)
index bf68d1a3c9bdf5efd231e6dd91541c7a4e347f42..5aa2cf5a8783bc0d74d4362f7ef6eefc2b80814b 100644 (file)
@@ -62,6 +62,9 @@
 #define Py_RETURN_FALSE return Py_INCREF(Py_False), Py_False
 #endif
 
+int EXPP_FloatsAreEqual(float A, float B, int floatSteps);
+int EXPP_VectorsAreEqual(float *vecA, float *vecB, int size, int floatSteps);
+
 PyObject *EXPP_GetModuleConstant(char *module, char *constant);
 
 int StringEqual( const char *string1, const char *string2 );
index a0a02a98575063e4b769622e0f6ae51a0ecb86d6..6b90a3a6494ac524eee61db5af3e0c70ecd0ab77 100644 (file)
@@ -374,7 +374,58 @@ static PyObject *Matrix_repr(MatrixObject * self)
 
        return PyString_FromString(str);
 }
+//------------------------tp_richcmpr
+//returns -1 execption, 0 false, 1 true
+static PyObject* Matrix_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+       MatrixObject *matA = NULL, *matB = NULL;
+       int result = 0;
+
+       if (!MatrixObject_Check(objectA) || !MatrixObject_Check(objectB)){
+               if (comparison_type == Py_NE){
+                       return EXPP_incr_ret(Py_True); 
+               }else{
+                       return EXPP_incr_ret(Py_False);
+               }
+       }
+       matA = (MatrixObject*)objectA;
+       matB = (MatrixObject*)objectB;
 
+       if (matA->colSize != matB->colSize && matA->rowSize != matB->rowSize){
+               if (comparison_type == Py_NE){
+                       return EXPP_incr_ret(Py_True); 
+               }else{
+                       return EXPP_incr_ret(Py_False);
+               }
+       }
+
+       switch (comparison_type){
+               case Py_EQ:
+                       //contigPtr is basically a really long vector
+                       result = EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr,
+                               (matA->rowSize * matA->colSize), 1);
+                       break;
+               case Py_NE:
+                       result = EXPP_VectorsAreEqual(matA->contigPtr, matB->contigPtr,
+                               (matA->rowSize * matA->colSize), 1);
+                       if (result == 0){
+                               result = 1;
+                       }else{
+                               result = 0;
+                       }
+                       break;
+               default:
+                       printf("The result of the comparison could not be evaluated");
+                       break;
+       }
+       if (result == 1){
+               return EXPP_incr_ret(Py_True);
+       }else{
+               return EXPP_incr_ret(Py_False);
+       }
+}
+//------------------------tp_doc
+static char MatrixObject_doc[] = "This is a wrapper for matrix objects.";
 //---------------------SEQUENCE PROTOCOLS------------------------
 //----------------------------len(object)------------------------
 //sequence length
@@ -734,19 +785,53 @@ static PyNumberMethods Matrix_NumMethods = {
 };
 //------------------PY_OBECT DEFINITION--------------------------
 PyTypeObject matrix_Type = {
-       PyObject_HEAD_INIT(NULL)                                /* required python macro */
-       0,                                                                              /*ob_size */
-       "Matrix",                                                               /*tp_name */
-       sizeof(MatrixObject),                                   /*tp_basicsize */
-       0,                                                                              /*tp_itemsize */
-       (destructor) Matrix_dealloc,                    /*tp_dealloc */
-       (printfunc) 0,                                                  /*tp_print */
-       (getattrfunc) Matrix_getattr,                   /*tp_getattr */
-       (setattrfunc) Matrix_setattr,                   /*tp_setattr */
-       0,                                                                              /*tp_compare */
-       (reprfunc) Matrix_repr,                                 /*tp_repr */
-       &Matrix_NumMethods,                                             /*tp_as_number */
-       &Matrix_SeqMethods,                                             /*tp_as_sequence */
+       PyObject_HEAD_INIT(NULL)                //tp_head
+       0,                                                              //tp_internal
+       "matrix",                                               //tp_name
+       sizeof(MatrixObject),                   //tp_basicsize
+       0,                                                              //tp_itemsize
+       (destructor)Matrix_dealloc,             //tp_dealloc
+       0,                                                              //tp_print
+       (getattrfunc)Matrix_getattr,    //tp_getattr
+       (setattrfunc) Matrix_setattr,   //tp_setattr
+       0,                                                              //tp_compare
+       (reprfunc) Matrix_repr,                 //tp_repr
+       &Matrix_NumMethods,                             //tp_as_number
+       &Matrix_SeqMethods,                             //tp_as_sequence
+       0,                                                              //tp_as_mapping
+       0,                                                              //tp_hash
+       0,                                                              //tp_call
+       0,                                                              //tp_str
+       0,                                                              //tp_getattro
+       0,                                                              //tp_setattro
+       0,                                                              //tp_as_buffer
+       Py_TPFLAGS_DEFAULT,                             //tp_flags
+       MatrixObject_doc,                               //tp_doc
+       0,                                                              //tp_traverse
+       0,                                                              //tp_clear
+       (richcmpfunc)Matrix_richcmpr,   //tp_richcompare
+       0,                                                              //tp_weaklistoffset
+       0,                                                              //tp_iter
+       0,                                                              //tp_iternext
+       0,                                                              //tp_methods
+       0,                                                              //tp_members
+       0,                                                              //tp_getset
+       0,                                                              //tp_base
+       0,                                                              //tp_dict
+       0,                                                              //tp_descr_get
+       0,                                                              //tp_descr_set
+       0,                                                              //tp_dictoffset
+       0,                                                              //tp_init
+       0,                                                              //tp_alloc
+       0,                                                              //tp_new
+       0,                                                              //tp_free
+       0,                                                              //tp_is_gc
+       0,                                                              //tp_bases
+       0,                                                              //tp_mro
+       0,                                                              //tp_cache
+       0,                                                              //tp_subclasses
+       0,                                                              //tp_weaklist
+       0                                                               //tp_del
 };
 //------------------------newMatrixObject (internal)-------------
 //creates a new matrix object
index 2b5fcc5966c6f08fee11134af5a69d55aea44d95..3c7cb4b839a0eba60d21d04311df51e40a269f63 100644 (file)
@@ -187,7 +187,9 @@ static PyObject *Quaternion_getattr(QuaternionObject * self, char *name)
                }
                Normalise(vec);
                //If the axis of rotation is 0,0,0 set it to 1,0,0 - for zero-degree rotations
-               if (vec[0] < 1e-44 && vec[1] < 1e-44 && vec[2] < 1e-44){
+               if( EXPP_FloatsAreEqual(vec[0], 0.0f, 10) &&
+                       EXPP_FloatsAreEqual(vec[1], 0.0f, 10) &&
+                       EXPP_FloatsAreEqual(vec[2], 0.0f, 10) ){
                        vec[0] = 1.0f;
                }
                return (PyObject *) newVectorObject(vec, 3, Py_NEW);
@@ -251,6 +253,47 @@ static PyObject *Quaternion_repr(QuaternionObject * self)
 
        return PyString_FromString(str);
 }
+//------------------------tp_richcmpr
+//returns -1 execption, 0 false, 1 true
+static PyObject* Quaternion_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
+{
+       QuaternionObject *quatA = NULL, *quatB = NULL;
+       int result = 0;
+
+       if (!QuaternionObject_Check(objectA) || !QuaternionObject_Check(objectB)){
+               if (comparison_type == Py_NE){
+                       return EXPP_incr_ret(Py_True); 
+               }else{
+                       return EXPP_incr_ret(Py_False);
+               }
+       }
+       quatA = (QuaternionObject*)objectA;
+       quatB = (QuaternionObject*)objectB;
+
+       switch (comparison_type){
+               case Py_EQ:
+                       result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
+                       break;
+               case Py_NE:
+                       result = EXPP_VectorsAreEqual(quatA->quat, quatB->quat, 4, 1);
+                       if (result == 0){
+                               result = 1;
+                       }else{
+                               result = 0;
+                       }
+                       break;
+               default:
+                       printf("The result of the comparison could not be evaluated");
+                       break;
+       }
+       if (result == 1){
+               return EXPP_incr_ret(Py_True);
+       }else{
+               return EXPP_incr_ret(Py_False);
+       }
+}
+//------------------------tp_doc
+static char QuaternionObject_doc[] = "This is a wrapper for quaternion objects.";
 //---------------------SEQUENCE PROTOCOLS------------------------
 //----------------------------len(object)------------------------
 //sequence length
@@ -529,19 +572,53 @@ static PyNumberMethods Quaternion_NumMethods = {
 };
 //------------------PY_OBECT DEFINITION--------------------------
 PyTypeObject quaternion_Type = {
-       PyObject_HEAD_INIT(NULL) 
-       0,                                                                                      /*ob_size */
-       "quaternion",                                                           /*tp_name */
-       sizeof(QuaternionObject),                                       /*tp_basicsize */
-       0,                                                                                      /*tp_itemsize */
-       (destructor) Quaternion_dealloc,                        /*tp_dealloc */
-       (printfunc) 0,                                                          /*tp_print */
-       (getattrfunc) Quaternion_getattr,                       /*tp_getattr */
-       (setattrfunc) Quaternion_setattr,                       /*tp_setattr */
-       0,                                                                                      /*tp_compare */
-       (reprfunc) Quaternion_repr,                                     /*tp_repr */
-       &Quaternion_NumMethods,                                         /*tp_as_number */
-       &Quaternion_SeqMethods,                                         /*tp_as_sequence */
+PyObject_HEAD_INIT(NULL)               //tp_head
+       0,                                                              //tp_internal
+       "quaternion",                                           //tp_name
+       sizeof(QuaternionObject),                       //tp_basicsize
+       0,                                                              //tp_itemsize
+       (destructor)Quaternion_dealloc,         //tp_dealloc
+       0,                                                              //tp_print
+       (getattrfunc)Quaternion_getattr,        //tp_getattr
+       (setattrfunc) Quaternion_setattr,       //tp_setattr
+       0,                                                              //tp_compare
+       (reprfunc) Quaternion_repr,                     //tp_repr
+       &Quaternion_NumMethods,                         //tp_as_number
+       &Quaternion_SeqMethods,                         //tp_as_sequence
+       0,                                                              //tp_as_mapping
+       0,                                                              //tp_hash
+       0,                                                              //tp_call
+       0,                                                              //tp_str
+       0,                                                              //tp_getattro
+       0,                                                              //tp_setattro
+       0,                                                              //tp_as_buffer
+       Py_TPFLAGS_DEFAULT,                             //tp_flags
+       QuaternionObject_doc,                           //tp_doc
+       0,                                                              //tp_traverse
+       0,                                                              //tp_clear
+       (richcmpfunc)Quaternion_richcmpr,       //tp_richcompare
+       0,                                                              //tp_weaklistoffset
+       0,                                                              //tp_iter
+       0,                                                              //tp_iternext
+       0,                                                              //tp_methods
+       0,                                                              //tp_members
+       0,                                                              //tp_getset
+       0,                                                              //tp_base
+       0,                                                              //tp_dict
+       0,                                                              //tp_descr_get
+       0,                                                              //tp_descr_set
+       0,                                                              //tp_dictoffset
+       0,                                                              //tp_init
+       0,                                                              //tp_alloc
+       0,                                                              //tp_new
+       0,                                                              //tp_free
+       0,                                                              //tp_is_gc
+       0,                                                              //tp_bases
+       0,                                                              //tp_mro
+       0,                                                              //tp_cache
+       0,                                                              //tp_subclasses
+       0,                                                              //tp_weaklist
+       0                                                               //tp_del
 };
 //------------------------newQuaternionObject (internal)-------------
 //creates a new quaternion object
index af151d87d4e0d34007d4674657047eb94eb7daac..a0afaf60c1e7ce74c210783056fa07608bae04c3 100644 (file)
@@ -687,18 +687,6 @@ static double vec_magnitude(float *data, int size)
        }
        return (double)sqrt(dot);
 }
-//------------------------vec_equality(internal)
-static int vec_equality(float *dataA, float *dataB, int size, double epsilon)
-{
-       int i;
-
-       for(i=0; i<size; i++){
-               if(!(((dataA[i] + epsilon) > dataB[i]) && ((dataA[i] - epsilon) < dataB[i]))){
-                       return 0;
-               }
-       }
-       return 1;
-}
 //------------------------tp_richcmpr
 //returns -1 execption, 0 false, 1 true
 PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_type)
@@ -744,10 +732,10 @@ PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_t
                        }
                        break;
                case Py_EQ:
-                       result = vec_equality(vecA->vec, vecB->vec, vecA->size, epsilon);
+                       result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
                        break;
                case Py_NE:
-                       result = vec_equality(vecA->vec, vecB->vec, vecA->size, epsilon);
+                       result = EXPP_VectorsAreEqual(vecA->vec, vecB->vec, vecA->size, 1);
                        if (result == 0){
                                result = 1;
                        }else{
@@ -771,6 +759,7 @@ PyObject* Vector_richcmpr(PyObject *objectA, PyObject *objectB, int comparison_t
                        }
                        break;
                default:
+                       printf("The result of the comparison could not be evaluated");
                        break;
        }
        if (result == 1){