forked from bartvdbraak/blender
Added some equvalency tests for the other math objects
* ==, != are defined for matrix, quat, euler.
This commit is contained in:
parent
6c619b235c
commit
b63e26e109
@ -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){
|
||||
|
Loading…
Reference in New Issue
Block a user