summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension-python/Makefile.am3
-rw-r--r--libdimension-python/Scene.c74
-rw-r--r--libdimension-python/Vector.c355
-rw-r--r--libdimension-python/dimension.c45
-rw-r--r--libdimension-python/scene.c106
-rw-r--r--libdimension-python/tests/Makefile.am3
-rwxr-xr-xlibdimension-python/tests/geometry.py52
7 files changed, 523 insertions, 115 deletions
diff --git a/libdimension-python/Makefile.am b/libdimension-python/Makefile.am
index adb792b..239f051 100644
--- a/libdimension-python/Makefile.am
+++ b/libdimension-python/Makefile.am
@@ -30,4 +30,5 @@ dimension_la_SOURCES = dimension.c
dimension_la_LDFLAGS = -avoid-version -module
dimension_la_LIBADD = $(top_builddir)/libdimension/libdimension.la
-EXTRA_DIST = scene.c
+EXTRA_DIST = Scene.c \
+ Vector.c
diff --git a/libdimension-python/Scene.c b/libdimension-python/Scene.c
new file mode 100644
index 0000000..48a41cb
--- /dev/null
+++ b/libdimension-python/Scene.c
@@ -0,0 +1,74 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+typedef struct dmnsn_py_Scene {
+ PyObject_HEAD
+ dmnsn_scene *scene;
+} dmnsn_py_Scene;
+
+static PyObject *
+dmnsn_py_Scene_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ dmnsn_py_Scene *self;
+ self = (dmnsn_py_Scene *)type->tp_alloc(type, 0);
+ self->scene = dmnsn_new_scene();
+ return (PyObject *)self;
+}
+
+static int
+dmnsn_py_Scene_init(dmnsn_py_Scene *self, PyObject *args, PyObject *kwds)
+{
+ return 0;
+}
+
+static void
+dmnsn_py_Scene_dealloc(dmnsn_py_Scene *self)
+{
+ dmnsn_delete_scene(self->scene);
+ Py_TYPE(self)->tp_free((PyObject *)self);
+}
+
+static PyMethodDef dmnsn_py_Scene_methods[] = {
+ { NULL }
+};
+
+static PyGetSetDef dmnsn_py_Scene_getsetters[] = {
+ { NULL }
+};
+
+static PyTypeObject dmnsn_py_SceneType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "dimension.Scene",
+ .tp_basicsize = sizeof(dmnsn_py_Scene),
+ .tp_dealloc = (destructor)dmnsn_py_Scene_dealloc,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = "Dimension scene",
+ .tp_methods = dmnsn_py_Scene_methods,
+ .tp_getset = dmnsn_py_Scene_getsetters,
+ .tp_init = (initproc)dmnsn_py_Scene_init,
+ .tp_new = dmnsn_py_Scene_new,
+};
+
+static bool
+dmnsn_py_init_SceneType(void)
+{
+ Py_INCREF(&dmnsn_py_SceneType);
+ return PyType_Ready(&dmnsn_py_SceneType) >= 0;
+}
diff --git a/libdimension-python/Vector.c b/libdimension-python/Vector.c
new file mode 100644
index 0000000..ca7d4e1
--- /dev/null
+++ b/libdimension-python/Vector.c
@@ -0,0 +1,355 @@
+/*************************************************************************
+ * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This file is part of The Dimension Python Module. *
+ * *
+ * The Dimension Python Module is free software; you can redistribute it *
+ * and/ or modify it under the terms of the GNU Lesser General Public *
+ * License as published by the Free Software Foundation; either version *
+ * 3 of the License, or (at your option) any later version. *
+ * *
+ * The Dimension Python Module is distributed in the hope that it will *
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied *
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
+ * the GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program. If not, see *
+ * <http://www.gnu.org/licenses/>. *
+ *************************************************************************/
+
+typedef struct dmnsn_py_Vector {
+ PyObject_HEAD
+ dmnsn_vector v;
+} dmnsn_py_Vector;
+
+static PyTypeObject dmnsn_py_VectorType;
+
+static int
+dmnsn_py_Vector_init(dmnsn_py_Vector *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwlist[] = { "x", "y", "z", NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "ddd", kwlist,
+ &self->v.x, &self->v.y, &self->v.z))
+ return -1;
+
+ return 0;
+}
+
+static PyObject *
+dmnsn_py_Vector_repr(dmnsn_py_Vector *self)
+{
+ PyObject *x = PyFloat_FromDouble(self->v.x);
+ PyObject *y = PyFloat_FromDouble(self->v.y);
+ PyObject *z = PyFloat_FromDouble(self->v.z);
+
+ if (!x || !y || !x) {
+ Py_XDECREF(z);
+ Py_XDECREF(y);
+ Py_XDECREF(x);
+ return NULL;
+ }
+
+ PyObject *repr = PyUnicode_FromFormat("dimension.Vector(%R, %R, %R)",
+ x, y, z);
+ Py_DECREF(z);
+ Py_DECREF(y);
+ Py_DECREF(x);
+ return repr;
+}
+
+static PyObject *
+dmnsn_py_Vector_str(dmnsn_py_Vector *self)
+{
+ PyObject *x = PyFloat_FromDouble(self->v.x);
+ PyObject *y = PyFloat_FromDouble(self->v.y);
+ PyObject *z = PyFloat_FromDouble(self->v.z);
+
+ if (!x || !y || !x) {
+ Py_XDECREF(z);
+ Py_XDECREF(y);
+ Py_XDECREF(x);
+ return NULL;
+ }
+
+ PyObject *repr = PyUnicode_FromFormat("<%S, %S, %S>", x, y, z);
+ Py_DECREF(z);
+ Py_DECREF(y);
+ Py_DECREF(x);
+ return repr;
+}
+
+static PyObject *
+dmnsn_py_Vector_richcompare(PyObject *lhs, PyObject *rhs, int op)
+{
+ if (!PyObject_TypeCheck(lhs, &dmnsn_py_VectorType)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Vectors can only be compared with Vectors");
+ return NULL;
+ }
+ if (!PyObject_TypeCheck(lhs, &dmnsn_py_VectorType)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Vectors can only be compared with Vectors");
+ return NULL;
+ }
+
+ dmnsn_py_Vector *vlhs = (dmnsn_py_Vector *)lhs;
+ dmnsn_py_Vector *vrhs = (dmnsn_py_Vector *)rhs;
+
+ bool equal =
+ dmnsn_vector_norm(dmnsn_vector_sub(vlhs->v, vrhs->v)) < dmnsn_epsilon;
+
+ PyObject *result;
+ switch (op) {
+ case Py_EQ:
+ result = equal ? Py_True : Py_False;
+ break;
+ case Py_NE:
+ result = !equal ? Py_True : Py_False;
+ break;
+ default:
+ result = Py_NotImplemented;
+ break;
+ }
+
+ Py_INCREF(result);
+ return result;
+}
+
+static PyObject *
+dmnsn_py_Vector_add(PyObject *lhs, PyObject *rhs)
+{
+ if (!PyObject_TypeCheck(lhs, &dmnsn_py_VectorType)
+ || !PyObject_TypeCheck(rhs, &dmnsn_py_VectorType))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Vectors can only be added to Vectors");
+ return NULL;
+ }
+
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ dmnsn_py_Vector *vlhs = (dmnsn_py_Vector *)lhs;
+ dmnsn_py_Vector *vrhs = (dmnsn_py_Vector *)rhs;
+ ret->v = dmnsn_vector_add(vlhs->v, vrhs->v);
+ }
+ return (PyObject *)ret;
+}
+
+static PyObject *
+dmnsn_py_Vector_sub(PyObject *lhs, PyObject *rhs)
+{
+ if (!PyObject_TypeCheck(lhs, &dmnsn_py_VectorType)
+ || !PyObject_TypeCheck(rhs, &dmnsn_py_VectorType))
+ {
+ PyErr_SetString(PyExc_TypeError,
+ "Vectors can only be subtracted from Vectors");
+ return NULL;
+ }
+
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ dmnsn_py_Vector *vlhs = (dmnsn_py_Vector *)lhs;
+ dmnsn_py_Vector *vrhs = (dmnsn_py_Vector *)rhs;
+ ret->v = dmnsn_vector_sub(vlhs->v, vrhs->v);
+ }
+ return (PyObject *)ret;
+}
+
+static PyObject *
+dmnsn_py_Vector_mul(PyObject *lhs, PyObject *rhs)
+{
+ dmnsn_py_Vector *vec;
+ double dbl;
+
+ if (PyObject_TypeCheck(lhs, &dmnsn_py_VectorType)) {
+ vec = (dmnsn_py_Vector *)lhs;
+ dbl = PyFloat_AsDouble(rhs);
+ if (PyErr_Occurred())
+ return NULL;
+ } else {
+ vec = (dmnsn_py_Vector *)rhs;
+ dbl = PyFloat_AsDouble(lhs);
+ if (PyErr_Occurred())
+ return NULL;
+ }
+
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ ret->v = dmnsn_vector_mul(dbl, vec->v);
+ }
+ return (PyObject *)ret;
+}
+
+static PyObject *
+dmnsn_py_Vector_div(PyObject *lhs, PyObject *rhs)
+{
+ if (!PyObject_TypeCheck(lhs, &dmnsn_py_VectorType)) {
+ PyErr_SetString(PyExc_TypeError,
+ "Vectors can only be divided by scalars");
+ return NULL;
+ }
+
+ double drhs = PyFloat_AsDouble(rhs);
+ if (PyErr_Occurred())
+ return NULL;
+
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ dmnsn_py_Vector *vlhs = (dmnsn_py_Vector *)lhs;
+ ret->v = dmnsn_vector_div(vlhs->v, drhs);
+ }
+ return (PyObject *)ret;
+}
+
+static int
+dmnsn_py_Vector_bool(PyObject *obj)
+{
+ dmnsn_py_Vector *vec = (dmnsn_py_Vector *)obj;
+ return dmnsn_vector_norm(vec->v) >= dmnsn_epsilon;
+}
+
+static PyObject *
+dmnsn_py_Vector_positive(PyObject *rhs)
+{
+ Py_INCREF(rhs);
+ return rhs;
+}
+
+static PyObject *
+dmnsn_py_Vector_negative(PyObject *rhs)
+{
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ dmnsn_py_Vector *vrhs = (dmnsn_py_Vector *)rhs;
+ ret->v = dmnsn_vector_negate(vrhs->v);
+ }
+ return (PyObject *)ret;
+}
+
+static PyObject *
+dmnsn_py_Vector_cross(PyObject *self, PyObject *args)
+{
+ dmnsn_py_Vector *lhs, *rhs;
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &dmnsn_py_VectorType, &lhs,
+ &dmnsn_py_VectorType, &rhs))
+ return NULL;
+
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ ret->v = dmnsn_vector_cross(lhs->v, rhs->v);
+ }
+ return (PyObject *)ret;
+}
+
+static PyObject *
+dmnsn_py_Vector_dot(PyObject *self, PyObject *args)
+{
+ dmnsn_py_Vector *lhs, *rhs;
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &dmnsn_py_VectorType, &lhs,
+ &dmnsn_py_VectorType, &rhs))
+ return NULL;
+
+ return PyFloat_FromDouble(dmnsn_vector_dot(lhs->v, rhs->v));
+}
+
+static PyObject *
+dmnsn_py_Vector_proj(PyObject *self, PyObject *args)
+{
+ dmnsn_py_Vector *u, *d;
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &dmnsn_py_VectorType, &u,
+ &dmnsn_py_VectorType, &d))
+ return NULL;
+
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ ret->v = dmnsn_vector_proj(u->v, d->v);
+ }
+ return (PyObject *)ret;
+}
+
+static PyNumberMethods dmnsn_py_Vector_as_number = {
+ .nb_add = dmnsn_py_Vector_add,
+ .nb_subtract = dmnsn_py_Vector_sub,
+ .nb_multiply = dmnsn_py_Vector_mul,
+ .nb_true_divide = dmnsn_py_Vector_div,
+ .nb_bool = dmnsn_py_Vector_bool,
+ .nb_positive = dmnsn_py_Vector_positive,
+ .nb_negative = dmnsn_py_Vector_negative,
+};
+
+static PyObject *
+dmnsn_py_Vector_norm(dmnsn_py_Vector *self)
+{
+ return PyFloat_FromDouble(dmnsn_vector_norm(self->v));
+}
+
+static PyObject *
+dmnsn_py_Vector_normalized(dmnsn_py_Vector *self)
+{
+ dmnsn_py_Vector *ret = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (ret) {
+ ret->v = dmnsn_vector_normalized(self->v);
+ }
+ return (PyObject *)ret;
+}
+
+static PyMethodDef dmnsn_py_Vector_methods[] = {
+ { "norm", (PyCFunction)dmnsn_py_Vector_norm, METH_NOARGS,
+ "Return the magnitude of the vector" },
+ { "normalized", (PyCFunction)dmnsn_py_Vector_normalized, METH_NOARGS,
+ "Return the magnitude of the vector" },
+ { NULL }
+};
+
+static PyObject *
+dmnsn_py_Vector_getx(dmnsn_py_Vector *self, void *closure)
+{
+ return PyFloat_FromDouble(self->v.x);
+}
+
+static PyObject *
+dmnsn_py_Vector_gety(dmnsn_py_Vector *self, void *closure)
+{
+ return PyFloat_FromDouble(self->v.y);
+}
+
+static PyObject *
+dmnsn_py_Vector_getz(dmnsn_py_Vector *self, void *closure)
+{
+ return PyFloat_FromDouble(self->v.z);
+}
+
+static PyGetSetDef dmnsn_py_Vector_getsetters[] = {
+ { "x", (getter)dmnsn_py_Vector_getx, NULL, "x coordinate", NULL },
+ { "y", (getter)dmnsn_py_Vector_gety, NULL, "y coordinate", NULL },
+ { "z", (getter)dmnsn_py_Vector_getz, NULL, "z coordinate", NULL },
+ { NULL }
+};
+
+static PyTypeObject dmnsn_py_VectorType = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ .tp_name = "dimension.Vector",
+ .tp_basicsize = sizeof(dmnsn_py_Vector),
+ .tp_repr = (reprfunc)dmnsn_py_Vector_repr,
+ .tp_str = (reprfunc)dmnsn_py_Vector_str,
+ .tp_as_number = &dmnsn_py_Vector_as_number,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = "Dimension vector",
+ .tp_richcompare = dmnsn_py_Vector_richcompare,
+ .tp_methods = dmnsn_py_Vector_methods,
+ .tp_getset = dmnsn_py_Vector_getsetters,
+ .tp_init = (initproc)dmnsn_py_Vector_init,
+};
+
+static bool
+dmnsn_py_init_VectorType(void)
+{
+ dmnsn_py_VectorType.tp_new = PyType_GenericNew;
+ Py_INCREF(&dmnsn_py_VectorType);
+ return PyType_Ready(&dmnsn_py_VectorType) >= 0;
+}
diff --git a/libdimension-python/dimension.c b/libdimension-python/dimension.c
index ca19844..511f197 100644
--- a/libdimension-python/dimension.c
+++ b/libdimension-python/dimension.c
@@ -23,13 +23,13 @@
#include <structmember.h>
#include "dimension.h"
-#include "scene.c"
+#include "Vector.c"
+#include "Scene.c"
static PyObject *
dmnsn_py_dieOnWarnings(PyObject *self, PyObject *args)
{
int die;
-
if (!PyArg_ParseTuple(args, "i", &die))
return NULL;
@@ -42,6 +42,11 @@ dmnsn_py_dieOnWarnings(PyObject *self, PyObject *args)
static PyMethodDef DimensionMethods[] = {
{ "dieOnWarnings", dmnsn_py_dieOnWarnings, METH_VARARGS,
"Turn Dimension warnings into fatal errors." },
+
+ { "cross", dmnsn_py_Vector_cross, METH_VARARGS, "Cross product." },
+ { "dot", dmnsn_py_Vector_dot, METH_VARARGS, "Dot product." },
+ { "proj", dmnsn_py_Vector_proj, METH_VARARGS, "Vector projection." },
+
{ NULL, NULL, 0, NULL }
};
@@ -56,13 +61,39 @@ static struct PyModuleDef dimensionmodule = {
PyMODINIT_FUNC
PyInit_dimension(void)
{
- if (!dmnsn_py_init_SceneType())
+ if (!dmnsn_py_init_VectorType()
+ || !dmnsn_py_init_SceneType())
return NULL;
- PyObject *m = PyModule_Create(&dimensionmodule);
- if (!m)
+ PyObject *module = PyModule_Create(&dimensionmodule);
+ if (!module)
return NULL;
- PyModule_AddObject(m, "Scene", (PyObject *)&dmnsn_py_SceneType);
- return m;
+ PyModule_AddObject(module, "Vector", (PyObject *)&dmnsn_py_VectorType);
+
+ /* Vector constants */
+ dmnsn_py_Vector *zero = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ dmnsn_py_Vector *x = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ dmnsn_py_Vector *y = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ dmnsn_py_Vector *z = PyObject_New(dmnsn_py_Vector, &dmnsn_py_VectorType);
+ if (!zero || !x || !y || !z) {
+ Py_XDECREF(zero);
+ Py_XDECREF(x);
+ Py_XDECREF(y);
+ Py_XDECREF(z);
+ Py_DECREF(module);
+ return NULL;
+ }
+ zero->v = dmnsn_zero;
+ x->v = dmnsn_x;
+ y->v = dmnsn_y;
+ z->v = dmnsn_z;
+ PyModule_AddObject(module, "Zero", (PyObject *)zero);
+ PyModule_AddObject(module, "X", (PyObject *)x);
+ PyModule_AddObject(module, "Y", (PyObject *)y);
+ PyModule_AddObject(module, "Z", (PyObject *)z);
+
+ PyModule_AddObject(module, "Scene", (PyObject *)&dmnsn_py_SceneType);
+
+ return module;
}
diff --git a/libdimension-python/scene.c b/libdimension-python/scene.c
deleted file mode 100644
index 5b6066c..0000000
--- a/libdimension-python/scene.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*************************************************************************
- * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> *
- * *
- * This file is part of The Dimension Python Module. *
- * *
- * The Dimension Python Module is free software; you can redistribute it *
- * and/ or modify it under the terms of the GNU Lesser General Public *
- * License as published by the Free Software Foundation; either version *
- * 3 of the License, or (at your option) any later version. *
- * *
- * The Dimension Python Module is distributed in the hope that it will *
- * be useful, but WITHOUT ANY WARRANTY; without even the implied *
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See *
- * the GNU Lesser General Public License for more details. *
- * *
- * You should have received a copy of the GNU Lesser General Public *
- * License along with this program. If not, see *
- * <http://www.gnu.org/licenses/>. *
- *************************************************************************/
-
-typedef struct {
- PyObject_HEAD
- dmnsn_scene *scene;
-} dmnsn_py_SceneObject;
-
-static PyObject *
-dmnsn_py_SceneNew(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- dmnsn_py_SceneObject *self;
- self = (dmnsn_py_SceneObject *)type->tp_alloc(type, 0);
- self->scene = dmnsn_new_scene();
- return (PyObject *)self;
-}
-
-static int
-dmnsn_py_SceneInit(dmnsn_py_SceneObject *self, PyObject *args, PyObject *kwds)
-{
- return 0;
-}
-
-static void
-dmnsn_py_SceneDealloc(dmnsn_py_SceneObject *self)
-{
- dmnsn_delete_scene(self->scene);
- Py_TYPE(self)->tp_free((PyObject *)self);
-}
-
-static PyMemberDef dmnsn_py_SceneMembers[] = {
- { NULL }
-};
-
-static PyMethodDef dmnsn_py_SceneMethods[] = {
- { NULL }
-};
-
-static PyGetSetDef dmnsn_py_SceneGetSetters[] = {
- { NULL }
-};
-
-static PyTypeObject dmnsn_py_SceneType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "dimension.Scene", /* tp_name */
- sizeof(dmnsn_py_SceneObject), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)dmnsn_py_SceneDealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* 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 */
- "Dimension scene", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- dmnsn_py_SceneMethods, /* tp_methods */
- dmnsn_py_SceneMembers, /* tp_members */
- dmnsn_py_SceneGetSetters, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- (initproc)dmnsn_py_SceneInit, /* tp_init */
- 0, /* tp_alloc */
- dmnsn_py_SceneNew, /* tp_new */
-};
-
-static bool
-dmnsn_py_init_SceneType(void)
-{
- Py_INCREF(&dmnsn_py_SceneType);
- return PyType_Ready(&dmnsn_py_SceneType) >= 0;
-}
diff --git a/libdimension-python/tests/Makefile.am b/libdimension-python/tests/Makefile.am
index 4bebfda..17589ba 100644
--- a/libdimension-python/tests/Makefile.am
+++ b/libdimension-python/tests/Makefile.am
@@ -17,7 +17,8 @@
## along with this program. If not, see <http://www.gnu.org/licenses/>. ##
###########################################################################
-TESTS = demo.py
+TESTS = geometry.py \
+ demo.py
TESTS_ENVIRONMENT = PYTHONPATH=$(top_builddir)/libdimension-python/.libs
.py:
diff --git a/libdimension-python/tests/geometry.py b/libdimension-python/tests/geometry.py
new file mode 100755
index 0000000..b398a1b
--- /dev/null
+++ b/libdimension-python/tests/geometry.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python3
+
+#########################################################################
+# Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> #
+# #
+# This file is part of The Dimension Test Suite. #
+# #
+# The Dimension Test Suite is free software; you can redistribute it #
+# and/or modify it under the terms of the GNU General Public License as #
+# published by the Free Software Foundation; either version 3 of the #
+# License, or (at your option) any later version. #
+# #
+# The Dimension Test Suite is distributed in the hope that it will be #
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty #
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU #
+# General Public License for more details. #
+# #
+# You should have received a copy of the GNU General Public License #
+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
+#########################################################################
+
+from dimension import *
+
+# Treat warnings as errors for tests
+dieOnWarnings(True)
+
+assert Zero == Vector(0, 0, 0), Zero
+assert X == Vector(1, 0, 0), X
+assert Y == Vector(0, 1, 0), Y
+assert Z == Vector(0, 0, 1), Z
+
+v = Vector(1.5, 2.5, 3.5)
+
+assert v.x == 1.5, v.x
+assert v.y == 2.5, v.y
+assert v.z == 3.5, v.z
+assert repr(v) == 'dimension.Vector(1.5, 2.5, 3.5)', repr(v)
+assert str(v) == '<1.5, 2.5, 3.5>', str(v)
+
+v = Vector(x = 2, y = 3, z = 6)
+
+assert v.norm() == 7, v.norm()
+assert v.normalized() == v/7, v.normalized()
+assert v + v == 2*v == v*2 == Vector(4, 6, 12), v + v
+assert v/2 == v - v/2 == Vector(1, 1.5, 3), v/2
+assert +v == v, +v
+assert v + -v == Zero, v + -v
+assert cross(v, v) == Zero, cross(v, v)
+assert dot(v, v) == v.norm()**2, dot(v, v)
+assert v, bool(v)
+assert not Zero, not Zero
+assert proj(v, X) == 2*X, proj(v, X)