1
/*<html><pre> -<a href="qh-user.htm"
2
>-------------------------------</a><a name="TOP">-</a>
5
user redefinable functions
7
see README.txt see COPYING.txt for copyright information.
9
see qhull.h for data structures, macros, and user-callable functions.
11
see user_eg.c, unix.c, and qhull_interface.cpp for examples.
13
see user.h for user-definable constants
15
use qh_NOmem in mem.h to turn off memory management
16
use qh_NOmerge in user.h to turn off facet merging
17
set qh_KEEPstatistics in user.h to 0 to turn off statistics
19
This is unsupported software. You're welcome to make changes,
20
but you're on your own if something goes wrong. Use 'Tc' to
21
check frequently. Usually qhull will report an error if
22
a data structure becomes inconsistent. If so, it also reports
23
the last point added to the hull, e.g., 102. You can then trace
24
the execution of qhull with "T4P102".
26
Please report any errors that you fix to qhull@qhull.org
28
call_qhull is a template for calling qhull from within your application
30
if you recompile and load this module, then user.o will not be loaded
33
you can add additional quick allocation sizes in qh_user_memsizes
35
if the other functions here are redefined to not use qh_print...,
36
then io.o will not be loaded from qhull.a. See user_eg.c for an
37
example. We recommend keeping io.o for the extra debugging
38
information it supplies.
43
/*-<a href="qh-user.htm#TOC"
44
>-------------------------------</a><a name="call_qhull">-</a>
47
template for calling qhull from inside your program
48
remove #if 0, #endif to compile
51
exit code (see qh_ERR... in qhull.h)
55
This can be called any number of times.
63
int dim; /* dimension of points */
64
int numpoints; /* number of points */
65
coordT *points; /* array of coordinates for each point */
66
boolT ismalloc; /* True if qhull should free points in qh_freeqhull() or reallocation */
67
char flags[]= "qhull Tv"; /* option flags for qhull, see qh_opt.htm */
68
FILE *outfile= stdout; /* output from qh_produce_output()
69
use NULL to skip qh_produce_output() */
70
FILE *errfile= stderr; /* error messages from qhull code */
71
int exitcode; /* 0 if no error from qhull */
72
facetT *facet; /* set by FORALLfacets */
73
int curlong, totlong; /* memory remaining after qh_memfreeshort */
75
/* initialize dim, numpoints, points[], ismalloc here */
76
exitcode= qh_new_qhull (dim, numpoints, points, ismalloc,
77
flags, outfile, errfile);
78
if (!exitcode) { /* if no error */
79
/* 'qh facet_list' contains the convex hull */
81
/* ... your code ... */
84
qh_freeqhull(!qh_ALL);
85
qh_memfreeshort (&curlong, &totlong);
86
if (curlong || totlong)
87
fprintf (errfile, "qhull internal warning (main): did not free %d bytes of long memory (%d pieces)\n", totlong, curlong);
91
/*-<a href="qh-user.htm#TOC"
92
>-------------------------------</a><a name="new_qhull">-</a>
94
qh_new_qhull( dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
95
build new qhull data structure and return exitcode (0 if no errors)
98
do not modify points until finished with results.
99
The qhull data structure contains pointers into the points array.
100
do not call qhull functions before qh_new_qhull().
101
The qhull data structure is not initialized until qh_new_qhull().
104
qhull_cmd must start with "qhull "
105
projects points to a new point array for Delaunay triangulations ('d' and 'v')
106
transforms points into a new point array for halfspace intersection ('H')
109
To allow multiple, concurrent calls to qhull()
110
- set qh_QHpointer in user.h
111
- use qh_save_qhull and qh_restore_qhull to swap the global data structure between calls.
112
- use qh_freeqhull(qh_ALL) to free intermediate convex hulls
115
user_eg.c for an example
117
int qh_new_qhull (int dim, int numpoints, coordT *points, boolT ismalloc,
118
char *qhull_cmd, FILE *outfile, FILE *errfile) {
119
int exitcode, hulldim;
121
static boolT firstcall = True;
125
qh_meminit (errfile);
128
if (strncmp (qhull_cmd,"qhull ", 6)) {
129
fprintf (errfile, "qh_new_qhull: start qhull_cmd argument with \"qhull \"\n");
132
qh_initqhull_start (NULL, outfile, errfile);
133
trace1(( qh ferr, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
134
exitcode = setjmp (qh errexit);
137
qh NOerrexit = False;
138
qh_initflags (qhull_cmd);
140
qh PROJECTdelaunay= True;
142
/* points is an array of halfspaces,
143
the last coordinate of each halfspace is its offset */
145
qh_setfeasible (hulldim);
146
new_points= qh_sethalfspace_all (dim, numpoints, points, qh feasible_point);
153
new_ismalloc= ismalloc;
155
qh_init_B (new_points, numpoints, hulldim, new_ismalloc);
160
if (qh VERIFYoutput && !qh STOPpoint && !qh STOPcone)
167
/*-<a href="qh-user.htm#TOC"
168
>-------------------------------</a><a name="errexit">-</a>
170
qh_errexit( exitcode, facet, ridge )
171
report and exit from an error
172
report facet and ridge if non-NULL
173
reports useful information such as last point processed
174
set qh.FORCEoutput to print neighborhood of facet
177
qh_errexit2() in qhull.c for printing 2 facets
180
check for error within error processing
182
print facet and ridge (if any)
183
report commandString, options, qh.furthest_id
184
print summary and statistics (including precision statistics)
186
print help text for singular data set
187
exit program via long jump (if defined) or exit()
189
void qh_errexit(int exitcode, facetT *facet, ridgeT *ridge) {
191
if (qh ERREXITcalled) {
192
fprintf (qh ferr, "\nqhull error while processing previous error. Exit program\n");
195
qh ERREXITcalled= True;
196
if (!qh QHULLfinished)
197
qh hulltime= qh_CPUclock - qh hulltime;
198
qh_errprint("ERRONEOUS", facet, NULL, ridge, NULL);
199
fprintf (qh ferr, "\nWhile executing: %s | %s\n", qh rbox_command, qh qhull_command);
200
fprintf(qh ferr, "Options selected for Qhull %s:\n%s\n", qh_version, qh qhull_options);
201
if (qh furthest_id >= 0) {
202
fprintf(qh ferr, "Last point added to hull was p%d.", qh furthest_id);
203
if (zzval_(Ztotmerge))
204
fprintf(qh ferr, " Last merge was #%d.", zzval_(Ztotmerge));
205
if (qh QHULLfinished)
206
fprintf(qh ferr, "\nQhull has finished constructing the hull.");
207
else if (qh POSTmerging)
208
fprintf(qh ferr, "\nQhull has started post-merging.");
209
fprintf (qh ferr, "\n");
211
if (qh FORCEoutput && (qh QHULLfinished || (!facet && !ridge)))
214
if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh hull_dim+1) {
215
fprintf (qh ferr, "\nAt error exit:\n");
216
qh_printsummary (qh ferr);
217
if (qh PRINTstatistics) {
218
qh_collectstatistics();
219
qh_printstatistics(qh ferr, "at error exit");
220
qh_memstatistics (qh ferr);
223
if (qh PRINTprecision)
224
qh_printstats (qh ferr, qhstat precision, NULL);
227
exitcode= qh_ERRqhull;
228
else if (exitcode == qh_ERRsingular)
229
qh_printhelp_singular(qh ferr);
230
else if (exitcode == qh_ERRprec && !qh PREmerge)
231
qh_printhelp_degenerate (qh ferr);
233
fprintf (qh ferr, "qhull error while ending program. Exit program\n");
237
longjmp(qh errexit, exitcode);
241
/*-<a href="qh-user.htm#TOC"
242
>-------------------------------</a><a name="errprint">-</a>
244
qh_errprint( fp, string, atfacet, otherfacet, atridge, atvertex )
245
prints out the information of facets and ridges to fp
246
also prints neighbors and geomview output
249
except for string, any parameter may be NULL
251
void qh_errprint(char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
255
fprintf(qh ferr, "%s FACET:\n", string);
256
qh_printfacet(qh ferr, atfacet);
259
fprintf(qh ferr, "%s OTHER FACET:\n", string);
260
qh_printfacet(qh ferr, otherfacet);
263
fprintf(qh ferr, "%s RIDGE:\n", string);
264
qh_printridge(qh ferr, atridge);
265
if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
266
qh_printfacet(qh ferr, atridge->top);
268
&& atridge->bottom != atfacet && atridge->bottom != otherfacet)
269
qh_printfacet(qh ferr, atridge->bottom);
271
atfacet= atridge->top;
273
otherfacet= otherfacet_(atridge, atfacet);
276
fprintf(qh ferr, "%s VERTEX:\n", string);
277
qh_printvertex (qh ferr, atvertex);
279
if (qh fout && qh FORCEoutput && atfacet && !qh QHULLfinished && !qh IStracing) {
280
fprintf(qh ferr, "ERRONEOUS and NEIGHBORING FACETS to output\n");
281
for (i= 0; i < qh_PRINTEND; i++) /* use fout for geomview output */
282
qh_printneighborhood (qh fout, qh PRINTout[i], atfacet, otherfacet,
288
/*-<a href="qh-user.htm#TOC"
289
>-------------------------------</a><a name="printfacetlist">-</a>
291
qh_printfacetlist( fp, facetlist, facets, printall )
292
print all fields for a facet list and/or set of facets to fp
294
only prints good facets
297
also prints all vertices
299
void qh_printfacetlist(facetT *facetlist, setT *facets, boolT printall) {
300
facetT *facet, **facetp;
302
qh_printbegin (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
303
FORALLfacet_(facetlist)
304
qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
305
FOREACHfacet_(facets)
306
qh_printafacet(qh ferr, qh_PRINTfacets, facet, printall);
307
qh_printend (qh ferr, qh_PRINTfacets, facetlist, facets, printall);
308
} /* printfacetlist */
311
/*-<a href="qh-globa.htm#TOC"
312
>-------------------------------</a><a name="user_memsizes">-</a>
315
allocate up to 10 additional, quick allocation sizes
318
increase maximum number of allocations in qh_initqhull_mem()
320
void qh_user_memsizes (void) {
322
/* qh_memsize (size); */
323
} /* user_memsizes */