Line data Source code
1 : /*<html><pre> -<a href="qh-user_r.htm"
2 : >-------------------------------</a><a name="TOP">-</a>
3 :
4 : user_r.c
5 : user redefinable functions
6 :
7 : see user2_r.c for qh_fprintf, qh_malloc, qh_free
8 :
9 : see README.txt see COPYING.txt for copyright information.
10 :
11 : see libqhull_r.h for data structures, macros, and user-callable functions.
12 :
13 : see user_eg_r.c, user_eg2_r.c, and unix_r.c for examples.
14 :
15 : see user_r.h for user-definable constants
16 :
17 : use qh_NOmem in mem_r.h to turn off memory management
18 : use qh_NOmerge in user_r.h to turn off facet merging
19 : set qh_KEEPstatistics in user_r.h to 0 to turn off statistics
20 :
21 : This is unsupported software. You're welcome to make changes,
22 : but you're on your own if something goes wrong. Use 'Tc' to
23 : check frequently. Usually qhull will report an error if
24 : a data structure becomes inconsistent. If so, it also reports
25 : the last point added to the hull, e.g., 102. You can then trace
26 : the execution of qhull with "T4P102".
27 :
28 : Please report any errors that you fix to qhull@qhull.org
29 :
30 : Qhull-template is a template for calling qhull from within your application
31 :
32 : if you recompile and load this module, then user.o will not be loaded
33 : from qhull.a
34 :
35 : you can add additional quick allocation sizes in qh_user_memsizes
36 :
37 : if the other functions here are redefined to not use qh_print...,
38 : then io.o will not be loaded from qhull.a. See user_eg_r.c for an
39 : example. We recommend keeping io.o for the extra debugging
40 : information it supplies.
41 : */
42 :
43 : #include "qhull_ra.h"
44 :
45 : #include <stdarg.h>
46 :
47 : /*-<a href="qh-user_r.htm#TOC"
48 : >-------------------------------</a><a name="qhull_template">-</a>
49 :
50 : Qhull-template
51 : Template for calling qhull from inside your program
52 :
53 : returns:
54 : exit code(see qh_ERR... in libqhull_r.h)
55 : all memory freed
56 :
57 : notes:
58 : This can be called any number of times.
59 : */
60 : #if 0
61 : {
62 : int dim; /* dimension of points */
63 : int numpoints; /* number of points */
64 : coordT *points; /* array of coordinates for each point */
65 : boolT ismalloc; /* True if qhull should free points in qh_freeqhull() or reallocation */
66 : char flags[]= "qhull Tv"; /* option flags for qhull, see html/qh-quick.htm */
67 : FILE *outfile= stdout; /* output from qh_produce_output
68 : use NULL to skip qh_produce_output */
69 : FILE *errfile= stderr; /* error messages from qhull code */
70 : int exitcode; /* 0 if no error from qhull */
71 : facetT *facet; /* set by FORALLfacets */
72 : int curlong, totlong; /* memory remaining after qh_memfreeshort */
73 :
74 : qhT qh_qh; /* Qhull's data structure. First argument of most calls */
75 : qhT *qh= &qh_qh; /* Alternatively -- qhT *qh= (qhT *)malloc(sizeof(qhT)) */
76 :
77 : QHULL_LIB_CHECK /* Check for compatible library */
78 :
79 : qh_zero(qh, errfile);
80 :
81 : /* initialize dim, numpoints, points[], ismalloc here */
82 : exitcode= qh_new_qhull(qh, dim, numpoints, points, ismalloc,
83 : flags, outfile, errfile);
84 : if (!exitcode) { /* if no error */
85 : /* 'qh->facet_list' contains the convex hull */
86 : FORALLfacets {
87 : /* ... your code ... */
88 : }
89 : }
90 : qh_freeqhull(qh, !qh_ALL);
91 : qh_memfreeshort(qh, &curlong, &totlong);
92 : if (curlong || totlong)
93 : qh_fprintf(qh, errfile, 7079, "qhull internal warning (main): did not free %d bytes of long memory(%d pieces)\n", totlong, curlong);
94 : }
95 : #endif
96 :
97 : /*-<a href="qh-user_r.htm#TOC"
98 : >-------------------------------</a><a name="new_qhull">-</a>
99 :
100 : qh_new_qhull(qh, dim, numpoints, points, ismalloc, qhull_cmd, outfile, errfile )
101 : Run qhull
102 : Before first call, either call qh_zero(qh, errfile), or set qh to all zero.
103 :
104 : returns:
105 : results in qh
106 : exitcode (0 if no errors).
107 :
108 : notes:
109 : do not modify points until finished with results.
110 : The qhull data structure contains pointers into the points array.
111 : do not call qhull functions before qh_new_qhull().
112 : The qhull data structure is not initialized until qh_new_qhull().
113 : do not call qh_init_A (global_r.c)
114 :
115 : Default errfile is stderr, outfile may be null
116 : qhull_cmd must start with "qhull "
117 : projects points to a new point array for Delaunay triangulations ('d' and 'v')
118 : transforms points into a new point array for halfspace intersection ('H')
119 :
120 : see:
121 : Qhull-template at the beginning of this file.
122 : An example of using qh_new_qhull is user_eg_r.c
123 : */
124 5 : int qh_new_qhull(qhT *qh, int dim, int numpoints, coordT *points, boolT ismalloc,
125 : char *qhull_cmd, FILE *outfile, FILE *errfile) {
126 : /* gcc may issue a "might be clobbered" warning for dim, points, and ismalloc [-Wclobbered].
127 : These parameters are not referenced after a longjmp() and hence not clobbered.
128 : See http://stackoverflow.com/questions/7721854/what-sense-do-these-clobbered-variable-warnings-make */
129 : int exitcode, hulldim;
130 : boolT new_ismalloc;
131 : coordT *new_points;
132 :
133 5 : if(!errfile){
134 0 : errfile= stderr;
135 : }
136 5 : if (!qh->qhmem.ferr) {
137 0 : qh_meminit(qh, errfile);
138 : } else {
139 5 : qh_memcheck(qh);
140 : }
141 5 : if (strncmp(qhull_cmd, "qhull ", (size_t)6) && strcmp(qhull_cmd, "qhull") != 0) {
142 0 : qh_fprintf(qh, errfile, 6186, "qhull error (qh_new_qhull): start qhull_cmd argument with \"qhull \" or set to \"qhull\"\n");
143 0 : return qh_ERRinput;
144 : }
145 5 : qh_initqhull_start(qh, NULL, outfile, errfile);
146 5 : if(numpoints==0 && points==NULL){
147 0 : trace1((qh, qh->ferr, 1047, "qh_new_qhull: initialize Qhull\n"));
148 0 : return 0;
149 : }
150 5 : trace1((qh, qh->ferr, 1044, "qh_new_qhull: build new Qhull for %d %d-d points with %s\n", numpoints, dim, qhull_cmd));
151 5 : exitcode= setjmp(qh->errexit);
152 7 : if (!exitcode) {
153 5 : qh->NOerrexit= False;
154 5 : qh_initflags(qh, qhull_cmd);
155 5 : if (qh->DELAUNAY)
156 5 : qh->PROJECTdelaunay= True;
157 5 : if (qh->HALFspace) {
158 : /* points is an array of halfspaces,
159 : the last coordinate of each halfspace is its offset */
160 0 : hulldim= dim-1;
161 0 : qh_setfeasible(qh, hulldim);
162 0 : new_points= qh_sethalfspace_all(qh, dim, numpoints, points, qh->feasible_point);
163 0 : new_ismalloc= True;
164 0 : if (ismalloc)
165 0 : qh_free(points);
166 : }else {
167 5 : hulldim= dim;
168 5 : new_points= points;
169 5 : new_ismalloc= ismalloc;
170 : }
171 5 : qh_init_B(qh, new_points, numpoints, hulldim, new_ismalloc);
172 4 : qh_qhull(qh);
173 3 : qh_check_output(qh);
174 3 : if (outfile) {
175 0 : qh_produce_output(qh);
176 : }else {
177 3 : qh_prepare_output(qh);
178 : }
179 3 : if (qh->VERIFYoutput && !qh->FORCEoutput && !qh->STOPadd && !qh->STOPcone && !qh->STOPpoint)
180 0 : qh_check_points(qh);
181 : }
182 5 : qh->NOerrexit= True;
183 5 : return exitcode;
184 : } /* new_qhull */
185 :
186 : /*-<a href="qh-user_r.htm#TOC"
187 : >-------------------------------</a><a name="errexit">-</a>
188 :
189 : qh_errexit(qh, exitcode, facet, ridge )
190 : report and exit from an error
191 : report facet and ridge if non-NULL
192 : reports useful information such as last point processed
193 : set qh.FORCEoutput to print neighborhood of facet
194 :
195 : see:
196 : qh_errexit2() in libqhull_r.c for printing 2 facets
197 :
198 : design:
199 : check for error within error processing
200 : compute qh.hulltime
201 : print facet and ridge (if any)
202 : report commandString, options, qh.furthest_id
203 : print summary and statistics (including precision statistics)
204 : if qh_ERRsingular
205 : print help text for singular data set
206 : exit program via long jump (if defined) or exit()
207 : */
208 2 : void qh_errexit(qhT *qh, int exitcode, facetT *facet, ridgeT *ridge) {
209 :
210 2 : qh->tracefacet= NULL; /* avoid infinite recursion through qh_fprintf */
211 2 : qh->traceridge= NULL;
212 2 : qh->tracevertex= NULL;
213 2 : if (qh->ERREXITcalled) {
214 0 : qh_fprintf(qh, qh->ferr, 8126, "\nqhull error while handling previous error in qh_errexit. Exit program\n");
215 0 : qh_exit(qh_ERRother);
216 : }
217 2 : qh->ERREXITcalled= True;
218 2 : if (!qh->QHULLfinished)
219 2 : qh->hulltime= qh_CPUclock - qh->hulltime;
220 2 : qh_errprint(qh, "ERRONEOUS", facet, NULL, ridge, NULL);
221 2 : qh_option(qh, "_maxoutside", NULL, &qh->MAXoutside);
222 2 : qh_fprintf(qh, qh->ferr, 8127, "\nWhile executing: %s | %s\n", qh->rbox_command, qh->qhull_command);
223 2 : qh_fprintf(qh, qh->ferr, 8128, "Options selected for Qhull %s:\n%s\n", qh_version, qh->qhull_options);
224 2 : if (qh->furthest_id >= 0) {
225 0 : qh_fprintf(qh, qh->ferr, 8129, "Last point added to hull was p%d.", qh->furthest_id);
226 0 : if (zzval_(Ztotmerge))
227 0 : qh_fprintf(qh, qh->ferr, 8130, " Last merge was #%d.", zzval_(Ztotmerge));
228 0 : if (qh->QHULLfinished)
229 0 : qh_fprintf(qh, qh->ferr, 8131, "\nQhull has finished constructing the hull.");
230 0 : else if (qh->POSTmerging)
231 0 : qh_fprintf(qh, qh->ferr, 8132, "\nQhull has started post-merging.");
232 0 : qh_fprintf(qh, qh->ferr, 8133, "\n");
233 : }
234 2 : if (qh->FORCEoutput && (qh->QHULLfinished || (!facet && !ridge)))
235 0 : qh_produce_output(qh);
236 2 : else if (exitcode != qh_ERRinput) {
237 1 : if (exitcode != qh_ERRsingular && zzval_(Zsetplane) > qh->hull_dim+1) {
238 0 : qh_fprintf(qh, qh->ferr, 8134, "\nAt error exit:\n");
239 0 : qh_printsummary(qh, qh->ferr);
240 0 : if (qh->PRINTstatistics) {
241 0 : qh_collectstatistics(qh);
242 0 : qh_allstatistics(qh);
243 0 : qh_printstatistics(qh, qh->ferr, "at error exit");
244 0 : qh_memstatistics(qh, qh->ferr);
245 : }
246 : }
247 1 : if (qh->PRINTprecision)
248 1 : qh_printstats(qh, qh->ferr, qh->qhstat.precision, NULL);
249 : }
250 2 : if (!exitcode)
251 0 : exitcode= qh_ERRother;
252 2 : else if (exitcode == qh_ERRprec && !qh->PREmerge)
253 0 : qh_printhelp_degenerate(qh, qh->ferr);
254 2 : else if (exitcode == qh_ERRqhull)
255 0 : qh_printhelp_internal(qh, qh->ferr);
256 2 : else if (exitcode == qh_ERRsingular)
257 1 : qh_printhelp_singular(qh, qh->ferr);
258 1 : else if (exitcode == qh_ERRdebug)
259 0 : qh_fprintf(qh, qh->ferr, 8016, "qhull exit due to qh_ERRdebug\n");
260 1 : else if (exitcode == qh_ERRtopology || exitcode == qh_ERRwide || exitcode == qh_ERRprec) {
261 0 : if (qh->NOpremerge && !qh->MERGING)
262 0 : qh_printhelp_degenerate(qh, qh->ferr);
263 0 : else if (exitcode == qh_ERRtopology)
264 0 : qh_printhelp_topology(qh, qh->ferr);
265 0 : else if (exitcode == qh_ERRwide)
266 0 : qh_printhelp_wide(qh, qh->ferr);
267 1 : }else if (exitcode > 255) {
268 0 : qh_fprintf(qh, qh->ferr, 6426, "qhull internal error (qh_errexit): exit code %d is greater than 255. Invalid argument for exit(). Replaced with 255\n", exitcode);
269 0 : exitcode= 255;
270 : }
271 2 : if (qh->NOerrexit) {
272 0 : qh_fprintf(qh, qh->ferr, 6187, "qhull internal error (qh_errexit): either error while reporting error QH%d, or qh.NOerrexit not cleared after setjmp(). Exit program with error status %d\n",
273 : qh->last_errcode, exitcode);
274 0 : qh_exit(exitcode);
275 : }
276 2 : qh->ERREXITcalled= False;
277 2 : qh->NOerrexit= True;
278 2 : qh->ALLOWrestart= False; /* longjmp will undo qh_build_withrestart */
279 2 : longjmp(qh->errexit, exitcode);
280 : } /* errexit */
281 :
282 : /*-<a href="qh-user_r.htm#TOC"
283 : >-------------------------------</a><a name="errprint">-</a>
284 :
285 : qh_errprint(qh, fp, string, atfacet, otherfacet, atridge, atvertex )
286 : prints out the information of facets and ridges to fp
287 : also prints neighbors and geomview output
288 :
289 : notes:
290 : except for string, any parameter may be NULL
291 : */
292 2 : void qh_errprint(qhT *qh, const char *string, facetT *atfacet, facetT *otherfacet, ridgeT *atridge, vertexT *atvertex) {
293 : int i;
294 :
295 2 : if (atvertex) {
296 0 : qh_fprintf(qh, qh->ferr, 8138, "%s VERTEX:\n", string);
297 0 : qh_printvertex(qh, qh->ferr, atvertex);
298 : }
299 2 : if (atridge) {
300 0 : qh_fprintf(qh, qh->ferr, 8137, "%s RIDGE:\n", string);
301 0 : qh_printridge(qh, qh->ferr, atridge);
302 0 : if (!atfacet)
303 0 : atfacet= atridge->top;
304 0 : if (!otherfacet)
305 0 : otherfacet= otherfacet_(atridge, atfacet);
306 0 : if (atridge->top && atridge->top != atfacet && atridge->top != otherfacet)
307 0 : qh_printfacet(qh, qh->ferr, atridge->top);
308 0 : if (atridge->bottom && atridge->bottom != atfacet && atridge->bottom != otherfacet)
309 0 : qh_printfacet(qh, qh->ferr, atridge->bottom);
310 : }
311 2 : if (atfacet) {
312 0 : qh_fprintf(qh, qh->ferr, 8135, "%s FACET:\n", string);
313 0 : qh_printfacet(qh, qh->ferr, atfacet);
314 : }
315 2 : if (otherfacet) {
316 0 : qh_fprintf(qh, qh->ferr, 8136, "%s OTHER FACET:\n", string);
317 0 : qh_printfacet(qh, qh->ferr, otherfacet);
318 : }
319 2 : if (qh->fout && qh->FORCEoutput && atfacet && !qh->QHULLfinished && !qh->IStracing) {
320 0 : qh_fprintf(qh, qh->ferr, 8139, "ERRONEOUS and NEIGHBORING FACETS to output\n");
321 0 : for (i=0; i < qh_PRINTEND; i++) /* use fout for geomview output */
322 0 : qh_printneighborhood(qh, qh->fout, qh->PRINTout[i], atfacet, otherfacet,
323 : !qh_ALL);
324 : }
325 2 : } /* errprint */
326 :
327 :
328 : /*-<a href="qh-user_r.htm#TOC"
329 : >-------------------------------</a><a name="printfacetlist">-</a>
330 :
331 : qh_printfacetlist(qh, fp, facetlist, facets, printall )
332 : print all fields for a facet list and/or set of facets to fp
333 : if !printall,
334 : only prints good facets
335 :
336 : notes:
337 : also prints all vertices
338 : */
339 0 : void qh_printfacetlist(qhT *qh, facetT *facetlist, setT *facets, boolT printall) {
340 : facetT *facet, **facetp;
341 :
342 0 : if (facetlist)
343 : /* coverity[check_return] */
344 0 : qh_checklists(qh, facetlist);
345 0 : qh_fprintf(qh, qh->ferr, 9424, "printfacetlist: vertices\n");
346 0 : qh_printbegin(qh, qh->ferr, qh_PRINTfacets, facetlist, facets, printall);
347 0 : if (facetlist) {
348 0 : qh_fprintf(qh, qh->ferr, 9413, "printfacetlist: facetlist\n");
349 0 : FORALLfacet_(facetlist)
350 0 : qh_printafacet(qh, qh->ferr, qh_PRINTfacets, facet, printall);
351 : }
352 0 : if (facets) {
353 0 : qh_fprintf(qh, qh->ferr, 9414, "printfacetlist: %d facets\n", qh_setsize(qh, facets));
354 0 : FOREACHfacet_(facets)
355 0 : qh_printafacet(qh, qh->ferr, qh_PRINTfacets, facet, printall);
356 : }
357 0 : qh_fprintf(qh, qh->ferr, 9412, "printfacetlist: end\n");
358 0 : qh_printend(qh, qh->ferr, qh_PRINTfacets, facetlist, facets, printall);
359 0 : } /* printfacetlist */
360 :
361 :
362 : /*-<a href="qh-user_r.htm#TOC"
363 : >-------------------------------</a><a name="printhelp_degenerate">-</a>
364 :
365 : qh_printhelp_degenerate(qh, fp )
366 : prints descriptive message for precision error with qh_ERRprec
367 :
368 : notes:
369 : no message if qh_QUICKhelp
370 : */
371 0 : void qh_printhelp_degenerate(qhT *qh, FILE *fp) {
372 :
373 0 : if (qh->MERGEexact || qh->PREmerge || qh->JOGGLEmax < REALmax/2)
374 0 : qh_fprintf(qh, fp, 9368, "\n\
375 : A Qhull error has occurred. Qhull should have corrected the above\n\
376 : precision error. Please send the input and all of the output to\n\
377 : qhull_bug@qhull.org\n");
378 : else if (!qh_QUICKhelp) {
379 0 : qh_fprintf(qh, fp, 9369, "\n\
380 : Precision problems were detected during construction of the convex hull.\n\
381 : This occurs because convex hull algorithms assume that calculations are\n\
382 : exact, but floating-point arithmetic has roundoff errors.\n\
383 : \n\
384 : To correct for precision problems, do not use 'Q0'. By default, Qhull\n\
385 : selects 'C-0' or 'Qx' and merges non-convex facets. With option 'QJ',\n\
386 : Qhull joggles the input to prevent precision problems. See \"Imprecision\n\
387 : in Qhull\" (qh-impre.htm).\n\
388 : \n\
389 : If you use 'Q0', the output may include\n\
390 : coplanar ridges, concave ridges, and flipped facets. In 4-d and higher,\n\
391 : Qhull may produce a ridge with four neighbors or two facets with the same \n\
392 : vertices. Qhull reports these events when they occur. It stops when a\n\
393 : concave ridge, flipped facet, or duplicate facet occurs.\n");
394 : #if REALfloat
395 : qh_fprintf(qh, fp, 9370, "\
396 : \n\
397 : Qhull is currently using single precision arithmetic. The following\n\
398 : will probably remove the precision problems:\n\
399 : - recompile qhull for realT precision(#define REALfloat 0 in user_r.h).\n");
400 : #endif
401 0 : if (qh->DELAUNAY && !qh->SCALElast && qh->MAXabs_coord > 1e4)
402 0 : qh_fprintf(qh, fp, 9371, "\
403 : \n\
404 : When computing the Delaunay triangulation of coordinates > 1.0,\n\
405 : - use 'Qbb' to scale the last coordinate to [0,m] (max previous coordinate)\n");
406 0 : if (qh->DELAUNAY && !qh->ATinfinity)
407 0 : qh_fprintf(qh, fp, 9372, "\
408 : When computing the Delaunay triangulation:\n\
409 : - use 'Qz' to add a point at-infinity. This reduces precision problems.\n");
410 :
411 0 : qh_fprintf(qh, fp, 9373, "\
412 : \n\
413 : If you need triangular output:\n\
414 : - use option 'Qt' to triangulate the output\n\
415 : - use option 'QJ' to joggle the input points and remove precision errors\n\
416 : - use option 'Ft'. It triangulates non-simplicial facets with added points.\n\
417 : \n\
418 : If you must use 'Q0',\n\
419 : try one or more of the following options. They can not guarantee an output.\n\
420 : - use 'QbB' to scale the input to a cube.\n\
421 : - use 'Po' to produce output and prevent partitioning for flipped facets\n\
422 : - use 'V0' to set min. distance to visible facet as 0 instead of roundoff\n\
423 : - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
424 : - options 'Qf', 'Qbb', and 'QR0' may also help\n",
425 : qh->DISTround);
426 0 : qh_fprintf(qh, fp, 9374, "\
427 : \n\
428 : To guarantee simplicial output:\n\
429 : - use option 'Qt' to triangulate the output\n\
430 : - use option 'QJ' to joggle the input points and remove precision errors\n\
431 : - use option 'Ft' to triangulate the output by adding points\n\
432 : - use exact arithmetic (see \"Imprecision in Qhull\", qh-impre.htm)\n\
433 : ");
434 : }
435 0 : } /* printhelp_degenerate */
436 :
437 : /*-<a href="qh-user_r.htm#TOC"
438 : >-------------------------------</a><a name="printhelp_internal">-</a>
439 :
440 : qh_printhelp_internal(qh, fp )
441 : prints descriptive message for qhull internal error with qh_ERRqhull
442 :
443 : notes:
444 : no message if qh_QUICKhelp
445 : */
446 0 : void qh_printhelp_internal(qhT *qh, FILE *fp) {
447 :
448 : if (!qh_QUICKhelp) {
449 0 : qh_fprintf(qh, fp, 9426, "\n\
450 : A Qhull internal error has occurred. Please send the input and output to\n\
451 : qhull_bug@qhull.org. If you can duplicate the error with logging ('T4z'), please\n\
452 : include the log file.\n");
453 : }
454 0 : } /* printhelp_internal */
455 :
456 : /*-<a href="qh-user_r.htm#TOC"
457 : >-------------------------------</a><a name="printhelp_narrowhull">-</a>
458 :
459 : qh_printhelp_narrowhull(qh, minangle )
460 : Warn about a narrow hull
461 :
462 : notes:
463 : Alternatively, reduce qh_WARNnarrow in user_r.h
464 :
465 : */
466 0 : void qh_printhelp_narrowhull(qhT *qh, FILE *fp, realT minangle) {
467 :
468 0 : qh_fprintf(qh, fp, 7089, "qhull precision warning: The initial hull is narrow. Is the input lower\n\
469 : dimensional (e.g., a square in 3-d instead of a cube)? Cosine of the minimum\n\
470 : angle is %.16f. If so, Qhull may produce a wide facet.\n\
471 : Options 'Qs' (search all points), 'Qbb' (scale last coordinate), or\n\
472 : 'QbB' (scale to unit box) may remove this warning.\n\
473 : See 'Limitations' in qh-impre.htm. Use 'Pp' to skip this warning.\n",
474 : -minangle); /* convert from angle between normals to angle between facets */
475 0 : } /* printhelp_narrowhull */
476 :
477 : /*-<a href="qh-user_r.htm#TOC"
478 : >-------------------------------</a><a name="printhelp_singular">-</a>
479 :
480 : qh_printhelp_singular(qh, fp )
481 : prints descriptive message for singular input
482 : */
483 1 : void qh_printhelp_singular(qhT *qh, FILE *fp) {
484 : facetT *facet;
485 : vertexT *vertex, **vertexp;
486 : realT min, max, *coord, dist;
487 : int i,k;
488 :
489 1 : qh_fprintf(qh, fp, 9376, "\n\
490 : The input to qhull appears to be less than %d dimensional, or a\n\
491 : computation has overflowed.\n\n\
492 : Qhull could not construct a clearly convex simplex from points:\n",
493 : qh->hull_dim);
494 1 : qh_printvertexlist(qh, fp, "", qh->facet_list, NULL, qh_ALL);
495 : if (!qh_QUICKhelp)
496 1 : qh_fprintf(qh, fp, 9377, "\n\
497 : The center point is coplanar with a facet, or a vertex is coplanar\n\
498 : with a neighboring facet. The maximum round off error for\n\
499 : computing distances is %2.2g. The center point, facets and distances\n\
500 : to the center point are as follows:\n\n", qh->DISTround);
501 1 : qh_printpointid(qh, fp, "center point", qh->hull_dim, qh->interior_point, qh_IDunknown);
502 1 : qh_fprintf(qh, fp, 9378, "\n");
503 5 : FORALLfacets {
504 4 : qh_fprintf(qh, fp, 9379, "facet");
505 16 : FOREACHvertex_(facet->vertices)
506 12 : qh_fprintf(qh, fp, 9380, " p%d", qh_pointid(qh, vertex->point));
507 4 : zinc_(Zdistio);
508 4 : qh_distplane(qh, qh->interior_point, facet, &dist);
509 4 : qh_fprintf(qh, fp, 9381, " distance= %4.2g\n", dist);
510 : }
511 : if (!qh_QUICKhelp) {
512 1 : if (qh->HALFspace)
513 0 : qh_fprintf(qh, fp, 9382, "\n\
514 : These points are the dual of the given halfspaces. They indicate that\n\
515 : the intersection is degenerate.\n");
516 1 : qh_fprintf(qh, fp, 9383,"\n\
517 : These points either have a maximum or minimum x-coordinate, or\n\
518 : they maximize the determinant for k coordinates. Trial points\n\
519 : are first selected from points that maximize a coordinate.\n");
520 1 : if (qh->hull_dim >= qh_INITIALmax)
521 0 : qh_fprintf(qh, fp, 9384, "\n\
522 : Because of the high dimension, the min x-coordinate and max-coordinate\n\
523 : points are used if the determinant is non-zero. Option 'Qs' will\n\
524 : do a better, though much slower, job. Instead of 'Qs', you can change\n\
525 : the points by randomly rotating the input with 'QR0'.\n");
526 : }
527 1 : qh_fprintf(qh, fp, 9385, "\nThe min and max coordinates for each dimension are:\n");
528 4 : for (k=0; k < qh->hull_dim; k++) {
529 3 : min= REALmax;
530 3 : max= -REALmin;
531 18 : for (i=qh->num_points, coord= qh->first_point+k; i--; coord += qh->hull_dim) {
532 15 : maximize_(max, *coord);
533 15 : minimize_(min, *coord);
534 : }
535 3 : qh_fprintf(qh, fp, 9386, " %d: %8.4g %8.4g difference= %4.4g\n", k, min, max, max-min);
536 : }
537 : if (!qh_QUICKhelp) {
538 1 : qh_fprintf(qh, fp, 9387, "\n\
539 : If the input should be full dimensional, you have several options that\n\
540 : may determine an initial simplex:\n\
541 : - use 'QJ' to joggle the input and make it full dimensional\n\
542 : - use 'QbB' to scale the points to the unit cube\n\
543 : - use 'QR0' to randomly rotate the input for different maximum points\n\
544 : - use 'Qs' to search all points for the initial simplex\n\
545 : - use 'En' to specify a maximum roundoff error less than %2.2g.\n\
546 : - trace execution with 'T3' to see the determinant for each point.\n",
547 : qh->DISTround);
548 : #if REALfloat
549 : qh_fprintf(qh, fp, 9388, "\
550 : - recompile qhull for realT precision(#define REALfloat 0 in libqhull_r.h).\n");
551 : #endif
552 1 : qh_fprintf(qh, fp, 9389, "\n\
553 : If the input is lower dimensional:\n\
554 : - use 'QJ' to joggle the input and make it full dimensional\n\
555 : - use 'Qbk:0Bk:0' to delete coordinate k from the input. You should\n\
556 : pick the coordinate with the least range. The hull will have the\n\
557 : correct topology.\n\
558 : - determine the flat containing the points, rotate the points\n\
559 : into a coordinate plane, and delete the other coordinates.\n\
560 : - add one or more points to make the input full dimensional.\n\
561 : ");
562 : }
563 1 : } /* printhelp_singular */
564 :
565 : /*-<a href="qh-user_r.htm#TOC"
566 : >-------------------------------</a><a name="printhelp_topology">-</a>
567 :
568 : qh_printhelp_topology(qh, fp )
569 : prints descriptive message for qhull topology error with qh_ERRtopology
570 :
571 : notes:
572 : no message if qh_QUICKhelp
573 : */
574 0 : void qh_printhelp_topology(qhT *qh, FILE *fp) {
575 :
576 : if (!qh_QUICKhelp) {
577 0 : qh_fprintf(qh, fp, 9427, "\n\
578 : A Qhull topology error has occurred. Qhull did not recover from facet merges and vertex merges.\n\
579 : This usually occurs when the input is nearly degenerate and substantial merging has occurred.\n\
580 : See http://www.qhull.org/html/qh-impre.htm#limit\n");
581 : }
582 0 : } /* printhelp_topology */
583 :
584 : /*-<a href="qh-user_r.htm#TOC"
585 : >-------------------------------</a><a name="printhelp_wide">-</a>
586 :
587 : qh_printhelp_wide(qh, fp )
588 : prints descriptive message for qhull wide facet with qh_ERRwide
589 :
590 : notes:
591 : no message if qh_QUICKhelp
592 : */
593 0 : void qh_printhelp_wide(qhT *qh, FILE *fp) {
594 :
595 : if (!qh_QUICKhelp) {
596 0 : qh_fprintf(qh, fp, 9428, "\n\
597 : A wide merge error has occurred. Qhull has produced a wide facet due to facet merges and vertex merges.\n\
598 : This usually occurs when the input is nearly degenerate and substantial merging has occurred.\n\
599 : See http://www.qhull.org/html/qh-impre.htm#limit\n");
600 : }
601 0 : } /* printhelp_wide */
602 :
603 : /*-<a href="qh-user_r.htm#TOC"
604 : >-------------------------------</a><a name="user_memsizes">-</a>
605 :
606 : qh_user_memsizes(qh)
607 : allocate up to 10 additional, quick allocation sizes
608 :
609 : notes:
610 : increase maximum number of allocations in qh_initqhull_mem()
611 : */
612 4 : void qh_user_memsizes(qhT *qh) {
613 :
614 : QHULL_UNUSED(qh)
615 : /* qh_memsize(qh, size); */
616 4 : } /* user_memsizes */
617 :
618 :
|