@@ -95,6 +95,33 @@ at_least_3_unique_points(npy_intp npoints, const double* x, const double* y)
9595 return false ;
9696}
9797
98+ /* Holds on to info from Qhull so that it can be destructed automatically. */
99+ class QhullInfo {
100+ public:
101+ QhullInfo (FILE *error_file, qhT* qh) {
102+ this ->error_file = error_file;
103+ this ->qh = qh;
104+ }
105+
106+ ~QhullInfo () {
107+ qh_freeqhull (this ->qh , !qh_ALL);
108+ int curlong, totlong; /* Memory remaining. */
109+ qh_memfreeshort (this ->qh , &curlong, &totlong);
110+ if (curlong || totlong) {
111+ PyErr_WarnEx (PyExc_RuntimeWarning,
112+ " Qhull could not free all allocated memory" , 1 );
113+ }
114+
115+ if (this ->error_file != stderr) {
116+ fclose (error_file);
117+ }
118+ }
119+
120+ private:
121+ FILE* error_file;
122+ qhT* qh;
123+ };
124+
98125/* Delaunay implementation method.
99126 * If hide_qhull_errors is true then qhull error messages are discarded;
100127 * if it is false then they are written to stderr. */
@@ -111,7 +138,6 @@ delaunay_impl(npy_intp npoints, const double* x, const double* y,
111138 int exitcode; /* Value returned from qh_new_qhull(). */
112139 std::vector<int > tri_indices; /* Maps qhull facet id to triangle index. */
113140 int indices[3 ];
114- int curlong, totlong; /* Memory remaining after qh_memfreeshort. */
115141 PyObject* tuple; /* Return tuple (triangles, neighbors). */
116142 const int ndim = 2 ;
117143 npy_intp dims[2 ];
@@ -157,6 +183,7 @@ delaunay_impl(npy_intp npoints, const double* x, const double* y,
157183 }
158184
159185 /* Perform Delaunay triangulation. */
186+ QhullInfo info (error_file, qh);
160187 qh_zero (qh, error_file);
161188 exitcode = qh_new_qhull (qh, ndim, (int )npoints, points.data (), False,
162189 (char *)" qhull d Qt Qbb Qc Qz" , NULL , error_file);
@@ -165,7 +192,7 @@ delaunay_impl(npy_intp npoints, const double* x, const double* y,
165192 " Error in qhull Delaunay triangulation calculation: %s (exitcode=%d)%s" ,
166193 qhull_error_msg[exitcode], exitcode,
167194 hide_qhull_errors ? " ; use python verbose option (-v) to see original qhull error." : " " );
168- goto error ;
195+ return NULL ;
169196 }
170197
171198 /* Split facets so that they only have 3 points each. */
@@ -230,17 +257,6 @@ delaunay_impl(npy_intp npoints, const double* x, const double* y,
230257 }
231258 }
232259
233- /* Clean up. */
234- qh_freeqhull (qh, !qh_ALL);
235- qh_memfreeshort (qh, &curlong, &totlong);
236- if (curlong || totlong) {
237- PyErr_WarnEx (PyExc_RuntimeWarning,
238- " Qhull could not free all allocated memory" , 1 );
239- }
240- if (hide_qhull_errors) {
241- fclose (error_file);
242- }
243-
244260 tuple = PyTuple_New (2 );
245261 PyTuple_SetItem (tuple, 0 , (PyObject*)triangles);
246262 PyTuple_SetItem (tuple, 1 , (PyObject*)neighbors);
@@ -250,12 +266,6 @@ delaunay_impl(npy_intp npoints, const double* x, const double* y,
250266 /* Clean up. */
251267 Py_XDECREF (triangles);
252268 Py_XDECREF (neighbors);
253- qh_freeqhull (qh, !qh_ALL);
254- qh_memfreeshort (qh, &curlong, &totlong);
255- /* Don't bother checking curlong and totlong as raising error anyway. */
256- if (hide_qhull_errors) {
257- fclose (error_file);
258- }
259269
260270 return NULL ;
261271}
0 commit comments