| 8 | |
| 9 | |
| 10 | PyObject* marching_cubes_func(PyObject* lower, PyObject* upper, |
| 11 | int numx, int numy, int numz, PyObject* pyfunc, double isovalue) |
| 12 | { |
| 13 | std::vector<double> vertices; |
| 14 | std::vector<size_t> polygons; |
| 15 | |
| 16 | // Copy the lower and upper coordinates to a C array. |
| 17 | std::array<double,3> lower_; |
| 18 | std::array<double,3> upper_; |
| 19 | for(int i=0; i<3; ++i) |
| 20 | { |
| 21 | PyObject* l = PySequence_GetItem(lower, i); |
| 22 | if(l == NULL) |
| 23 | throw std::runtime_error("len(lower) < 3"); |
| 24 | PyObject* u = PySequence_GetItem(upper, i); |
| 25 | if(u == NULL) |
| 26 | { |
| 27 | Py_DECREF(l); |
| 28 | throw std::runtime_error("len(upper) < 3"); |
| 29 | } |
| 30 | |
| 31 | lower_[i] = PyFloat_AsDouble(l); |
| 32 | upper_[i] = PyFloat_AsDouble(u); |
| 33 | |
| 34 | Py_DECREF(l); |
| 35 | Py_DECREF(u); |
| 36 | if(lower_[i]==-1.0 || upper_[i]==-1.0) |
| 37 | { |
| 38 | if(PyErr_Occurred()) |
| 39 | throw std::runtime_error("unknown error"); |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | auto pyfunc_to_cfunc = [&](double x, double y, double z) -> double { |
| 44 | PyObject* res = PyObject_CallFunction(pyfunc, "(d,d,d)", x, y, z); |
| 45 | if(res == NULL) |
| 46 | return 0.0; |
| 47 | |
| 48 | double result = PyFloat_AsDouble(res); |
| 49 | Py_DECREF(res); |
| 50 | return result; |
| 51 | }; |
| 52 | |
| 53 | // Marching cubes. |
| 54 | mc::marching_cubes(lower_, upper_, numx, numy, numz, pyfunc_to_cfunc, isovalue, vertices, polygons); |
| 55 | |
| 56 | // Copy the result to two Python ndarrays. |
| 57 | npy_intp size_vertices = vertices.size(); |
| 58 | npy_intp size_polygons = polygons.size(); |
| 59 | PyArrayObject* verticesarr = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNew(1, &size_vertices, NPY_DOUBLE)); |
| 60 | PyArrayObject* polygonsarr = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNew(1, &size_polygons, NPY_ULONG)); |
| 61 | |
| 62 | std::vector<double>::const_iterator it = vertices.begin(); |
| 63 | for(int i=0; it!=vertices.end(); ++i, ++it) |
| 64 | *reinterpret_cast<double*>(PyArray_GETPTR1(verticesarr, i)) = *it; |
| 65 | std::vector<size_t>::const_iterator it2 = polygons.begin(); |
| 66 | for(int i=0; it2!=polygons.end(); ++i, ++it2) |
| 67 | *reinterpret_cast<unsigned long*>(PyArray_GETPTR1(polygonsarr, i)) = *it2; |
nothing calls this directly
no test coverage detected