Python API: add Vector.orthogonal() method
This commit is contained in:
@@ -800,6 +800,36 @@ static PyObject *Vector_to_track_quat(VectorObject *self, PyObject *args)
|
|||||||
return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
|
return Quaternion_CreatePyObject(quat, Py_NEW, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(Vector_orthogonal_doc,
|
||||||
|
".. method:: orthogonal()\n"
|
||||||
|
"\n"
|
||||||
|
" Return a perpendicular vector.\n"
|
||||||
|
"\n"
|
||||||
|
" :return: a new vector 90 degrees from this vector.\n"
|
||||||
|
" :rtype: :class:`Vector`\n"
|
||||||
|
"\n"
|
||||||
|
" .. note:: the axis is undefined, only use when any orthogonal vector is acceptable.\n"
|
||||||
|
);
|
||||||
|
static PyObject *Vector_orthogonal(VectorObject *self)
|
||||||
|
{
|
||||||
|
float vec[3];
|
||||||
|
|
||||||
|
if (self->size != 3) {
|
||||||
|
PyErr_SetString(PyExc_TypeError,
|
||||||
|
"Vector.orthogonal(): "
|
||||||
|
"Vector must be 3D");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BaseMath_ReadCallback(self) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ortho_v3_v3(vec, self->vec);
|
||||||
|
|
||||||
|
return Vector_CreatePyObject(vec, self->size, Py_NEW, Py_TYPE(self));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Vector.reflect(mirror): return a reflected vector on the mirror normal
|
* Vector.reflect(mirror): return a reflected vector on the mirror normal
|
||||||
* vec - ((2 * DotVecs(vec, mirror)) * mirror)
|
* vec - ((2 * DotVecs(vec, mirror)) * mirror)
|
||||||
@@ -2768,6 +2798,7 @@ static struct PyMethodDef Vector_methods[] = {
|
|||||||
{"resize_4d", (PyCFunction) Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc},
|
{"resize_4d", (PyCFunction) Vector_resize_4d, METH_NOARGS, Vector_resize_4d_doc},
|
||||||
{"to_tuple", (PyCFunction) Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc},
|
{"to_tuple", (PyCFunction) Vector_to_tuple, METH_VARARGS, Vector_to_tuple_doc},
|
||||||
{"to_track_quat", (PyCFunction) Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc},
|
{"to_track_quat", (PyCFunction) Vector_to_track_quat, METH_VARARGS, Vector_to_track_quat_doc},
|
||||||
|
{"orthogonal", (PyCFunction) Vector_orthogonal, METH_NOARGS, Vector_orthogonal_doc},
|
||||||
|
|
||||||
/* operation between 2 or more types */
|
/* operation between 2 or more types */
|
||||||
{"reflect", (PyCFunction) Vector_reflect, METH_O, Vector_reflect_doc},
|
{"reflect", (PyCFunction) Vector_reflect, METH_O, Vector_reflect_doc},
|
||||||
|
|||||||
@@ -3,6 +3,32 @@ import unittest
|
|||||||
from test import support
|
from test import support
|
||||||
from mathutils import Matrix, Vector
|
from mathutils import Matrix, Vector
|
||||||
from mathutils import kdtree
|
from mathutils import kdtree
|
||||||
|
import math
|
||||||
|
|
||||||
|
# keep globals immutable
|
||||||
|
vector_data = (
|
||||||
|
(1.0, 0.0, 0.0),
|
||||||
|
(0.0, 1.0, 0.0),
|
||||||
|
(0.0, 0.0, 1.0),
|
||||||
|
|
||||||
|
(1.0, 1.0, 1.0),
|
||||||
|
|
||||||
|
(0.33783, 0.715698, -0.611206),
|
||||||
|
(-0.944031, -0.326599, -0.045624),
|
||||||
|
(-0.101074, -0.416443, -0.903503),
|
||||||
|
(0.799286, 0.49411, -0.341949),
|
||||||
|
(-0.854645, 0.518036, 0.033936),
|
||||||
|
(0.42514, -0.437866, -0.792114),
|
||||||
|
(-0.358948, 0.597046, 0.717377),
|
||||||
|
(-0.985413,0.144714, 0.089294),
|
||||||
|
)
|
||||||
|
|
||||||
|
# get data at different scales
|
||||||
|
vector_data = sum(
|
||||||
|
(tuple(tuple(a * scale for a in v) for v in vector_data)
|
||||||
|
for scale in (s * sign for s in (0.0001, 0.1, -1.0, 10.0, 1000.0, 100000.0)
|
||||||
|
for sign in (1.0, -1.0))), ()) + ((0.0, 0.0, 0.0),)
|
||||||
|
|
||||||
|
|
||||||
class MatrixTesting(unittest.TestCase):
|
class MatrixTesting(unittest.TestCase):
|
||||||
def test_matrix_column_access(self):
|
def test_matrix_column_access(self):
|
||||||
@@ -149,6 +175,17 @@ class MatrixTesting(unittest.TestCase):
|
|||||||
self.assertEqual(mat * mat, prod_mat)
|
self.assertEqual(mat * mat, prod_mat)
|
||||||
|
|
||||||
|
|
||||||
|
class VectorTesting(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_orthogonal(self):
|
||||||
|
|
||||||
|
angle_90d = math.pi / 2.0
|
||||||
|
for v in vector_data:
|
||||||
|
v = Vector(v)
|
||||||
|
if v.length_squared != 0.0:
|
||||||
|
self.assertAlmostEqual(v.angle(v.orthogonal()), angle_90d)
|
||||||
|
|
||||||
|
|
||||||
class KDTreeTesting(unittest.TestCase):
|
class KDTreeTesting(unittest.TestCase):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -256,6 +293,7 @@ class KDTreeTesting(unittest.TestCase):
|
|||||||
def test_main():
|
def test_main():
|
||||||
try:
|
try:
|
||||||
support.run_unittest(MatrixTesting)
|
support.run_unittest(MatrixTesting)
|
||||||
|
support.run_unittest(VectorTesting)
|
||||||
support.run_unittest(KDTreeTesting)
|
support.run_unittest(KDTreeTesting)
|
||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
|
|||||||
Reference in New Issue
Block a user