diff --git a/lib/matplotlib/tests/test_triangulation.py b/lib/matplotlib/tests/test_triangulation.py index 74c79f33e22e..751b8c63cbae 100644 --- a/lib/matplotlib/tests/test_triangulation.py +++ b/lib/matplotlib/tests/test_triangulation.py @@ -985,6 +985,29 @@ def test_trirefiner_fortran_contiguous_triangles(): assert_array_equal(fine_triang1.triangles, fine_triang2.triangles) +def test_qhull_triangle_orientation(): + # github issue 4437. + xi = np.linspace(-2, 2, 100) + x, y = map(np.ravel, np.meshgrid(xi, xi)) + w = np.logical_and(x > y - 1, np.logical_and(x < -1.95, y > -1.2)) + x, y = x[w], y[w] + theta = np.radians(25) + x1 = x*np.cos(theta) - y*np.sin(theta) + y1 = x*np.sin(theta) + y*np.cos(theta) + + # Calculate Delaunay triangulation using Qhull. + triang = mtri.Triangulation(x1, y1) + + # Neighbors returned by Qhull. + qhull_neighbors = triang.neighbors + + # Obtain neighbors using own C++ calculation. + triang._neighbors = None + own_neighbors = triang.neighbors + + assert_array_equal(qhull_neighbors, own_neighbors) + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s', '--with-doctest'], exit=False) diff --git a/lib/matplotlib/tri/_tri.cpp b/lib/matplotlib/tri/_tri.cpp index d7d676032912..c51c1c1ced87 100644 --- a/lib/matplotlib/tri/_tri.cpp +++ b/lib/matplotlib/tri/_tri.cpp @@ -224,7 +224,8 @@ Triangulation::Triangulation(PyArrayObject* x, PyArrayObject* triangles, PyArrayObject* mask, PyArrayObject* edges, - PyArrayObject* neighbors) + PyArrayObject* neighbors, + int correct_triangle_orientations) : _npoints(PyArray_DIM(x,0)), _ntri(PyArray_DIM(triangles,0)), _x(x), @@ -235,7 +236,8 @@ Triangulation::Triangulation(PyArrayObject* x, _neighbors(neighbors) { _VERBOSE("Triangulation::Triangulation"); - correct_triangles(); + if (correct_triangle_orientations) + correct_triangles(); } Triangulation::~Triangulation() @@ -2230,7 +2232,7 @@ TriModule::TriModule() Py::Object TriModule::new_triangulation(const Py::Tuple &args) { _VERBOSE("TriModule::new_triangulation"); - args.verify_length(6); + args.verify_length(7); // x and y. PyArrayObject* x = (PyArrayObject*)PyArray_ContiguousFromObject( @@ -2305,7 +2307,10 @@ Py::Object TriModule::new_triangulation(const Py::Tuple &args) } } - return Py::asObject(new Triangulation(x, y, triangles, mask, edges, neighbors)); + int correct_triangle_orientations = Py::Int(args[6]); + + return Py::asObject(new Triangulation(x, y, triangles, mask, edges, neighbors, + correct_triangle_orientations)); } Py::Object TriModule::new_tricontourgenerator(const Py::Tuple &args) diff --git a/lib/matplotlib/tri/_tri.h b/lib/matplotlib/tri/_tri.h index c923411d9900..db75452c9881 100644 --- a/lib/matplotlib/tri/_tri.h +++ b/lib/matplotlib/tri/_tri.h @@ -180,13 +180,17 @@ class Triangulation : public Py::PythonExtension * once. * neighbors: Optional int array of shape (ntri,3) indicating which * triangles are the neighbors of which TriEdges, or -1 if - * there is no such neighbor. */ + * there is no such neighbor. + * correct_triangle_orientations: Whether or not should correct triangle + * orientations so that vertices are + * ordered anticlockwise. */ Triangulation(PyArrayObject* x, PyArrayObject* y, PyArrayObject* triangles, PyArrayObject* mask, PyArrayObject* edges, - PyArrayObject* neighbors); + PyArrayObject* neighbors, + int correct_triangle_orientations); virtual ~Triangulation(); diff --git a/lib/matplotlib/tri/triangulation.py b/lib/matplotlib/tri/triangulation.py index 3309823e136a..69c4c153e715 100644 --- a/lib/matplotlib/tri/triangulation.py +++ b/lib/matplotlib/tri/triangulation.py @@ -107,7 +107,7 @@ def get_cpp_triangulation(self): if self._cpp_triangulation is None: self._cpp_triangulation = _tri.Triangulation( self.x, self.y, self.triangles, self.mask, self._edges, - self._neighbors) + self._neighbors, not self.is_delaunay) return self._cpp_triangulation def get_masked_triangles(self):