Added some equvalency tests for the other math objects

* ==, != are defined for matrix, quat, euler.
This commit is contained in:
Joseph Gilbert 2005-11-22 17:59:49 +00:00
parent 6c619b235c
commit b63e26e109
7 changed files with 319 additions and 54 deletions

@ -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]

@ -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

@ -41,6 +41,36 @@
#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)

@ -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 );

@ -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

@ -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

@ -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){