/*------------------------------------------- -errexit- return exitcode to system after an error assumes exitcode non-zero prints useful information see qh_errexit2() in qhull.c for printing 2 facets */ void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) { if (qh ERREXITcalled) { fprintf (qh ferr, "\nqhull error while processing previous error. Exit program\n"); exit(1); } qh ERREXITcalled= True; if (!qh QHULLfinished) qh hulltime= qh_CPUclock - qh hulltime; qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL); fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command); fprintf(qh ferr, "Options selected for %s:\n%s\n", qh_version, qh qhull_options); if (qh furthest_id >= 0) { fprintf(qh ferr, "Last point added to hull was p%d.", qh furthest_id); if (zzval_(Ztotmerge)) fprintf(qh ferr, " Last merge was #%d.", zzval_(Ztotmerge)); if (qh QHULLfinished) fprintf(qh ferr, "\nQhull has finished constructing the hull."); else if (qh POSTmerging) fprintf(qh ferr, "\nQhull has started post-merging."); fprintf (qh ferr, "\n"); } if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge))) qh_produce_output(); else { if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) { fprintf (qh ferr, "\nAt error exit:\n"); qh_printsummary (qh ferr); if (qh PRINTstatistics) { qh_collectstatistics(); qh_printstatistics(qh ferr, "at error exit"); qh_memstatistics (qh ferr); } } if (qh PRINTprecision) qh_printstats (qh ferr, qhstat precision, NULL); } if (!exitcode) exitcode= qh_ERRqhull; else if (exitcode == qh_ERRsingular) qh_printhelp_singular(qh ferr); else if (exitcode == qh_ERRprec && !qh PREmerge) qh_printhelp_degenerate (qh ferr); if (qh NOerrexit) { fprintf (qh ferr, "qhull error while ending program. Exit program\n"); exit(1); } qh NOerrexit= True; longjmp(qh errexit, exitcode); } /* errexit */
int call_qhull (void) { int curlong, totlong, exitcode, numpoints, dim; coordT *points; boolT ismalloc; char *flags; qh_init_A (stdin, stdout, stderr, 0, NULL); exitcode= setjmp (qh errexit); if (!exitcode) { strcat (qh rbox_command, "user"); /* for documentation only */ qh_initflags ("qhull Tc (your flags go here)"); /* 1st word ignored */ /* define the input data */ points= array; /* an array of point coordinates */ ismalloc= False; /* True if qhull should 'free(points)' at end*/ dim= 3; /* dimension of points */ numpoints= 100; /* number of points */; /* For Delaunay triangulation ('d' or 'v'), set "qh PROJECTdelaunay= True" to project points to a paraboloid. You may project the points yourself. For halfspace intersection ('H'), compute the dual point array by "points= qh_sethalfspace_all (dim, numpoints, array, feasible);" */ qh_init_B (points, numpoints, dim, ismalloc); qh_qhull(); /* construct the hull */ /* For Voronoi centers ('v'), call qh_setvoronoi_all() */ qh_check_output(); /* optional */ qh_produce_output(); /* optional */ if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone) qh_check_points(); /* optional */ /* exitcode == 0 */ } qh NOerrexit= True; qh_freeqhull(!qh_ALL); qh_memfreeshort (&curlong, &totlong); if (curlong || totlong) /* optional */ fprintf (stderr, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong); return exitcode; } /* call_qhull */
static PyObject* py_qconvex(PyObject *self, PyObject *args) { const char *arg; const char *data; int curlong, totlong; /* used !qh_NOmem */ int exitcode, numpoints, dim; coordT *points; boolT ismalloc; char* argv[10]; int argc = 1; char *rest; char *token; /* Defensively copy the string first */ char tempstr[30]; char* ptr; char *bp; size_t size; FILE* fin; FILE* fout; if (!PyArg_ParseTuple(args, "ss", &arg, &data)) return NULL; strcpy(tempstr, arg); ptr = tempstr; while(token = strtok_r(ptr, " ", &rest)) { argv[argc] = token; ptr = rest; argc += 1; } argv[0] = "qconvex"; /* Because qhull uses stdin and stdout streams for io, we need to create FILE* stream to simulate these io streams.*/ fin = fmemopen(data, strlen(data), "r"); fout = open_memstream(&bp, &size); if ((fin != NULL) && (fout != NULL)) { /* Now do the usual qhull code (modified from qconvex.c). */ qh_init_A(fin, fout, stderr, argc, argv); exitcode= setjmp(qh errexit); if (!exitcode) { qh_checkflags(qh qhull_command, hidden_options); qh_initflags(qh qhull_command); points= qh_readpoints(&numpoints, &dim, &ismalloc); if (dim >= 5) { qh_option("Qxact_merge", NULL, NULL); qh MERGEexact= True; } qh_init_B(points, numpoints, dim, ismalloc); qh_qhull(); qh_check_output(); qh_produce_output(); if (qh VERIFYoutput && !qh FORCEoutput && !qh STOPpoint && !qh STOPcone) qh_check_points(); exitcode= qh_ERRnone; } qh NOerrexit= True; /* no more setjmp */ #ifdef qh_NOmem qh_freeqhull( True); #else qh_freeqhull( False); qh_memfreeshort(&curlong, &totlong); if (curlong || totlong) fprintf(stderr, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong); #endif fclose(fin); fclose(fout); return Py_BuildValue("s", bp); } else { return NULL; } }