#include "_tri.h" #include "src/mplutils.h" #include "src/py_exceptions.h" /* Triangulation */ typedef struct { PyObject_HEAD; Triangulation* ptr; } PyTriangulation; static PyTypeObject PyTriangulationType; static PyObject* PyTriangulation_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { PyTriangulation* self; self = (PyTriangulation*)type->tp_alloc(type, 0); self->ptr = NULL; return (PyObject*)self; } const char* PyTriangulation_init__doc__ = "Triangulation(x, y, triangles, mask, edges, neighbors)\n" "\n" "Create a new C++ Triangulation object\n" "This should not be called directly, instead use the python class\n" "matplotlib.tri.Triangulation instead.\n"; static int PyTriangulation_init(PyTriangulation* self, PyObject* args, PyObject* kwds) { Triangulation::CoordinateArray x, y; Triangulation::TriangleArray triangles; Triangulation::MaskArray mask; Triangulation::EdgeArray edges; Triangulation::NeighborArray neighbors; if (!PyArg_ParseTuple(args, "O&O&O&O&O&O&", &x.converter, &x, &y.converter, &y, &triangles.converter, &triangles, &mask.converter, &mask, &edges.converter, &edges, &neighbors.converter, &neighbors)) { return -1; } // x and y. if (x.empty() || y.empty() || x.dim(0) != y.dim(0)) { PyErr_SetString(PyExc_ValueError, "x and y must be 1D arrays of the same length"); } // triangles. if (triangles.empty() || triangles.dim(1) != 3) { PyErr_SetString(PyExc_ValueError, "triangles must be a 2D array of shape (?,3)"); } // Optional mask. if (!mask.empty() && mask.dim(0) != triangles.dim(0)) { PyErr_SetString(PyExc_ValueError, "mask must be a 1D array with the same length as the triangles array"); } // Optional edges. if (!edges.empty() && edges.dim(1) != 2) { PyErr_SetString(PyExc_ValueError, "edges must be a 2D array with shape (?,2)"); } // Optional neighbors. if (!neighbors.empty() && (neighbors.dim(0) != triangles.dim(0) || neighbors.dim(1) != triangles.dim(1))) { PyErr_SetString(PyExc_ValueError, "neighbors must be a 2D array with the same shape as the triangles array"); } CALL_CPP_INIT("Triangulation", (self->ptr = new Triangulation(x, y, triangles, mask, edges, neighbors))); return 0; } static void PyTriangulation_dealloc(PyTriangulation* self) { delete self->ptr; Py_TYPE(self)->tp_free((PyObject*)self); } const char* PyTriangulation_calculate_plane_coefficients__doc__ = "calculate_plane_coefficients(z, plane_coefficients)\n" "\n" "Calculate plane equation coefficients for all unmasked triangles"; static PyObject* PyTriangulation_calculate_plane_coefficients(PyTriangulation* self, PyObject* args, PyObject* kwds) { Triangulation::CoordinateArray z; if (!PyArg_ParseTuple(args, "O&:calculate_plane_coefficients", &z.converter, &z)) { return NULL; } if (z.empty() || z.dim(0) != self->ptr->get_npoints()) { PyErr_SetString(PyExc_ValueError, "z array must have same length as triangulation x and y arrays"); } Triangulation::TwoCoordinateArray result; CALL_CPP("calculate_plane_coefficients", (result = self->ptr->calculate_plane_coefficients(z))); return result.pyobj(); } const char* PyTriangulation_get_edges__doc__ = "get_edges()\n" "\n" "Return edges array"; static PyObject* PyTriangulation_get_edges(PyTriangulation* self, PyObject* args, PyObject* kwds) { Triangulation::EdgeArray* result; CALL_CPP("get_edges", (result = &self->ptr->get_edges())); if (result->empty()) { Py_RETURN_NONE; } else return result->pyobj(); } const char* PyTriangulation_get_neighbors__doc__ = "get_neighbors()\n" "\n" "Return neighbors array"; static PyObject* PyTriangulation_get_neighbors(PyTriangulation* self, PyObject* args, PyObject* kwds) { Triangulation::NeighborArray* result; CALL_CPP("get_neighbors", (result = &self->ptr->get_neighbors())); if (result->empty()) { Py_RETURN_NONE; } else return result->pyobj(); } const char* PyTriangulation_set_mask__doc__ = "set_mask(mask)\n" "\n" "Set or clear the mask array."; static PyObject* PyTriangulation_set_mask(PyTriangulation* self, PyObject* args, PyObject* kwds) { Triangulation::MaskArray mask; if (!PyArg_ParseTuple(args, "O&:set_mask", &mask.converter, &mask)) { return NULL; } if (!mask.empty() && mask.dim(0) != self->ptr->get_ntri()) { PyErr_SetString(PyExc_ValueError, "mask must be a 1D array with the same length as the triangles array"); } CALL_CPP("set_mask", (self->ptr->set_mask(mask))); Py_RETURN_NONE; } static PyTypeObject* PyTriangulation_init_type(PyObject* m, PyTypeObject* type) { static PyMethodDef methods[] = { {"calculate_plane_coefficients", (PyCFunction)PyTriangulation_calculate_plane_coefficients, METH_VARARGS, PyTriangulation_calculate_plane_coefficients__doc__}, {"get_edges", (PyCFunction)PyTriangulation_get_edges, METH_NOARGS, PyTriangulation_get_edges__doc__}, {"get_neighbors", (PyCFunction)PyTriangulation_get_neighbors, METH_NOARGS, PyTriangulation_get_neighbors__doc__}, {"set_mask", (PyCFunction)PyTriangulation_set_mask, METH_VARARGS, PyTriangulation_set_mask__doc__}, {NULL} }; memset(type, 0, sizeof(PyTypeObject)); type->tp_name = "matplotlib._tri.Triangulation"; type->tp_doc = PyTriangulation_init__doc__; type->tp_basicsize = sizeof(PyTriangulation); type->tp_dealloc = (destructor)PyTriangulation_dealloc; type->tp_flags = Py_TPFLAGS_DEFAULT; type->tp_methods = methods; type->tp_new = PyTriangulation_new; type->tp_init = (initproc)PyTriangulation_init; if (PyType_Ready(type) < 0) { return NULL; } if (PyModule_AddObject(m, "Triangulation", (PyObject*)type)) { return NULL; } return type; } /* TriContourGenerator */ typedef struct { PyObject_HEAD; TriContourGenerator* ptr; PyTriangulation* py_triangulation; } PyTriContourGenerator; static PyTypeObject PyTriContourGeneratorType; static PyObject* PyTriContourGenerator_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { PyTriContourGenerator* self; self = (PyTriContourGenerator*)type->tp_alloc(type, 0); self->ptr = NULL; self->py_triangulation = NULL; return (PyObject*)self; } const char* PyTriContourGenerator_init__doc__ = "TriContourGenerator(triangulation, z)\n" "\n" "Create a new C++ TriContourGenerator object\n" "This should not be called directly, instead use the functions\n" "matplotlib.axes.tricontour and tricontourf instead.\n"; static int PyTriContourGenerator_init(PyTriContourGenerator* self, PyObject* args, PyObject* kwds) { PyObject* triangulation_arg; TriContourGenerator::CoordinateArray z; if (!PyArg_ParseTuple(args, "O!O&", &PyTriangulationType, &triangulation_arg, &z.converter, &z)) { return -1; } PyTriangulation* py_triangulation = (PyTriangulation*)triangulation_arg; Py_INCREF(py_triangulation); self->py_triangulation = py_triangulation; Triangulation& triangulation = *(py_triangulation->ptr); if (z.empty() || z.dim(0) != triangulation.get_npoints()) { PyErr_SetString(PyExc_ValueError, "z must be a 1D array with the same length as the x and y arrays"); } CALL_CPP_INIT("TriContourGenerator", (self->ptr = new TriContourGenerator(triangulation, z))); return 0; } static void PyTriContourGenerator_dealloc(PyTriContourGenerator* self) { delete self->ptr; Py_XDECREF(self->py_triangulation); Py_TYPE(self)->tp_free((PyObject *)self); } const char* PyTriContourGenerator_create_contour__doc__ = "create_contour(level)\n" "\n" "Create and return a non-filled contour."; static PyObject* PyTriContourGenerator_create_contour(PyTriContourGenerator* self, PyObject* args, PyObject* kwds) { double level; if (!PyArg_ParseTuple(args, "d:create_contour", &level)) { return NULL; } PyObject* result; CALL_CPP("create_contour", (result = self->ptr->create_contour(level))); return result; } const char* PyTriContourGenerator_create_filled_contour__doc__ = "create_filled_contour(lower_level, upper_level)\n" "\n" "Create and return a filled contour"; static PyObject* PyTriContourGenerator_create_filled_contour(PyTriContourGenerator* self, PyObject* args, PyObject* kwds) { double lower_level, upper_level; if (!PyArg_ParseTuple(args, "dd:create_filled_contour", &lower_level, &upper_level)) { return NULL; } PyObject* result; CALL_CPP("create_filled_contour", (result = self->ptr->create_filled_contour(lower_level, upper_level))); return result; } static PyTypeObject* PyTriContourGenerator_init_type(PyObject* m, PyTypeObject* type) { static PyMethodDef methods[] = { {"create_contour", (PyCFunction)PyTriContourGenerator_create_contour, METH_VARARGS, PyTriContourGenerator_create_contour__doc__}, {"create_filled_contour", (PyCFunction)PyTriContourGenerator_create_filled_contour, METH_VARARGS, PyTriContourGenerator_create_filled_contour__doc__}, {NULL} }; memset(type, 0, sizeof(PyTypeObject)); type->tp_name = "matplotlib._tri.TriContourGenerator"; type->tp_doc = PyTriContourGenerator_init__doc__; type->tp_basicsize = sizeof(PyTriContourGenerator); type->tp_dealloc = (destructor)PyTriContourGenerator_dealloc; type->tp_flags = Py_TPFLAGS_DEFAULT; type->tp_methods = methods; type->tp_new = PyTriContourGenerator_new; type->tp_init = (initproc)PyTriContourGenerator_init; if (PyType_Ready(type) < 0) { return NULL; } if (PyModule_AddObject(m, "TriContourGenerator", (PyObject*)type)) { return NULL; } return type; } /* TrapezoidMapTriFinder */ typedef struct { PyObject_HEAD; TrapezoidMapTriFinder* ptr; PyTriangulation* py_triangulation; } PyTrapezoidMapTriFinder; static PyTypeObject PyTrapezoidMapTriFinderType; static PyObject* PyTrapezoidMapTriFinder_new(PyTypeObject* type, PyObject* args, PyObject* kwds) { PyTrapezoidMapTriFinder* self; self = (PyTrapezoidMapTriFinder*)type->tp_alloc(type, 0); self->ptr = NULL; self->py_triangulation = NULL; return (PyObject*)self; } const char* PyTrapezoidMapTriFinder_init__doc__ = "TrapezoidMapTriFinder(triangulation)\n" "\n" "Create a new C++ TrapezoidMapTriFinder object\n" "This should not be called directly, instead use the python class\n" "matplotlib.tri.TrapezoidMapTriFinder instead.\n"; static int PyTrapezoidMapTriFinder_init(PyTrapezoidMapTriFinder* self, PyObject* args, PyObject* kwds) { PyObject* triangulation_arg; if (!PyArg_ParseTuple(args, "O!", &PyTriangulationType, &triangulation_arg)) { return -1; } PyTriangulation* py_triangulation = (PyTriangulation*)triangulation_arg; Py_INCREF(py_triangulation); self->py_triangulation = py_triangulation; Triangulation& triangulation = *(py_triangulation->ptr); CALL_CPP_INIT("TrapezoidMapTriFinder", (self->ptr = new TrapezoidMapTriFinder(triangulation))); return 0; } static void PyTrapezoidMapTriFinder_dealloc(PyTrapezoidMapTriFinder* self) { delete self->ptr; Py_XDECREF(self->py_triangulation); Py_TYPE(self)->tp_free((PyObject *)self); } const char* PyTrapezoidMapTriFinder_find_many__doc__ = "find_many(x, y)\n" "\n" "Find indices of triangles containing the point coordinates (x, y)"; static PyObject* PyTrapezoidMapTriFinder_find_many(PyTrapezoidMapTriFinder* self, PyObject* args, PyObject* kwds) { TrapezoidMapTriFinder::CoordinateArray x, y; if (!PyArg_ParseTuple(args, "O&O&:find_many", &x.converter, &x, &y.converter, &y)) { return NULL; } if (x.empty() || y.empty() || x.dim(0) != y.dim(0)) { PyErr_SetString(PyExc_ValueError, "x and y must be array_like with same shape"); } TrapezoidMapTriFinder::TriIndexArray result; CALL_CPP("find_many", (result = self->ptr->find_many(x, y))); return result.pyobj(); } const char* PyTrapezoidMapTriFinder_get_tree_stats__doc__ = "get_tree_stats()\n" "\n" "Return statistics about the tree used by the trapezoid map"; static PyObject* PyTrapezoidMapTriFinder_get_tree_stats(PyTrapezoidMapTriFinder* self, PyObject* args, PyObject* kwds) { PyObject* result; CALL_CPP("get_tree_stats", (result = self->ptr->get_tree_stats())); return result; } const char* PyTrapezoidMapTriFinder_initialize__doc__ = "initialize()\n" "\n" "Initialize this object, creating the trapezoid map from the triangulation"; static PyObject* PyTrapezoidMapTriFinder_initialize(PyTrapezoidMapTriFinder* self, PyObject* args, PyObject* kwds) { CALL_CPP("initialize", (self->ptr->initialize())); Py_RETURN_NONE; } const char* PyTrapezoidMapTriFinder_print_tree__doc__ = "print_tree()\n" "\n" "Print the search tree as text to stdout; useful for debug purposes"; static PyObject* PyTrapezoidMapTriFinder_print_tree(PyTrapezoidMapTriFinder* self, PyObject* args, PyObject* kwds) { CALL_CPP("print_tree", (self->ptr->print_tree())); Py_RETURN_NONE; } static PyTypeObject* PyTrapezoidMapTriFinder_init_type(PyObject* m, PyTypeObject* type) { static PyMethodDef methods[] = { {"find_many", (PyCFunction)PyTrapezoidMapTriFinder_find_many, METH_VARARGS, PyTrapezoidMapTriFinder_find_many__doc__}, {"get_tree_stats", (PyCFunction)PyTrapezoidMapTriFinder_get_tree_stats, METH_NOARGS, PyTrapezoidMapTriFinder_get_tree_stats__doc__}, {"initialize", (PyCFunction)PyTrapezoidMapTriFinder_initialize, METH_NOARGS, PyTrapezoidMapTriFinder_initialize__doc__}, {"print_tree", (PyCFunction)PyTrapezoidMapTriFinder_print_tree, METH_NOARGS, PyTrapezoidMapTriFinder_print_tree__doc__}, {NULL} }; memset(type, 0, sizeof(PyTypeObject)); type->tp_name = "matplotlib._tri.TrapezoidMapTriFinder"; type->tp_doc = PyTrapezoidMapTriFinder_init__doc__; type->tp_basicsize = sizeof(PyTrapezoidMapTriFinder); type->tp_dealloc = (destructor)PyTrapezoidMapTriFinder_dealloc; type->tp_flags = Py_TPFLAGS_DEFAULT; type->tp_methods = methods; type->tp_new = PyTrapezoidMapTriFinder_new; type->tp_init = (initproc)PyTrapezoidMapTriFinder_init; if (PyType_Ready(type) < 0) { return NULL; } if (PyModule_AddObject(m, "TrapezoidMapTriFinder", (PyObject*)type)) { return NULL; } return type; } /* Module */ extern "C" { struct module_state { /* The Sun compiler can't handle empty structs */ #if defined(__SUNPRO_C) || defined(_MSC_VER) int _dummy; #endif }; #if PY3K static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_tri", NULL, sizeof(struct module_state), NULL, NULL, NULL, NULL, NULL }; #define INITERROR return NULL PyMODINIT_FUNC PyInit__tri(void) #else #define INITERROR return PyMODINIT_FUNC init_tri(void) #endif { PyObject *m; #if PY3K m = PyModule_Create(&moduledef); #else m = Py_InitModule3("_tri", NULL, NULL); #endif if (m == NULL) { INITERROR; } if (!PyTriangulation_init_type(m, &PyTriangulationType)) { INITERROR; } if (!PyTriContourGenerator_init_type(m, &PyTriContourGeneratorType)) { INITERROR; } if (!PyTrapezoidMapTriFinder_init_type(m, &PyTrapezoidMapTriFinderType)) { INITERROR; } import_array(); #if PY3K return m; #endif } } // extern "C"