Line data Source code
1 :
2 : /*<html><pre> -<a href="qh-globa_r.htm"
3 : >-------------------------------</a><a name="TOP">-</a>
4 :
5 : global_r.c
6 : initializes all the globals of the qhull application
7 :
8 : see README
9 :
10 : see libqhull_r.h for qh.globals and function prototypes
11 :
12 : see qhull_ra.h for internal functions
13 :
14 : Copyright (c) 1993-2020 The Geometry Center.
15 : $Id: //main/2019/qhull/src/libqhull_r/global_r.c#19 $$Change: 3037 $
16 : $DateTime: 2020/09/03 17:28:32 $$Author: bbarber $
17 : */
18 :
19 : #include "qhull_ra.h"
20 :
21 : /*========= qh->definition -- globals defined in libqhull_r.h =======================*/
22 :
23 : /*-<a href ="qh-globa_r.htm#TOC"
24 : >--------------------------------</a><a name="version">-</a>
25 :
26 : qh_version
27 : version string by year and date
28 : qh_version2 for Unix users and -V
29 :
30 : the revision increases on code changes only
31 :
32 : notes:
33 : change date: Changes.txt, Announce.txt, index.htm, README.txt,
34 : qhull-news.html, Eudora signatures, CMakeLists.txt
35 : change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt, CMakeLists.txt
36 : check that CMakeLists.txt @version is the same as qh_version2
37 : change year: Copying.txt
38 : check download size
39 : recompile user_eg_r.c, rbox_r.c, libqhull_r.c, qconvex_r.c, qdelaun_r.c qvoronoi_r.c, qhalf_r.c, testqset_r.c
40 : */
41 :
42 : const char qh_version[]= "2020.2.r 2020/08/31";
43 : const char qh_version2[]= "qhull_r 8.0.2 (2020.2.r 2020/08/31)";
44 :
45 : /*-<a href="qh-globa_r.htm#TOC"
46 : >-------------------------------</a><a name="appendprint">-</a>
47 :
48 : qh_appendprint(qh, printFormat )
49 : append printFormat to qh.PRINTout unless already defined
50 : */
51 0 : void qh_appendprint(qhT *qh, qh_PRINT format) {
52 : int i;
53 :
54 0 : for (i=0; i < qh_PRINTEND; i++) {
55 0 : if (qh->PRINTout[i] == format && format != qh_PRINTqhull)
56 0 : break;
57 0 : if (!qh->PRINTout[i]) {
58 0 : qh->PRINTout[i]= format;
59 0 : break;
60 : }
61 : }
62 0 : } /* appendprint */
63 :
64 : /*-<a href="qh-globa_r.htm#TOC"
65 : >-------------------------------</a><a name="checkflags">-</a>
66 :
67 : qh_checkflags(qh, commandStr, hiddenFlags )
68 : errors if commandStr contains hiddenFlags
69 : hiddenFlags starts and ends with a space and is space delimited (checked)
70 :
71 : notes:
72 : ignores first word (e.g., "qconvex i")
73 : use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
74 :
75 : see:
76 : qh_initflags() initializes Qhull according to commandStr
77 : */
78 0 : void qh_checkflags(qhT *qh, char *command, char *hiddenflags) {
79 0 : char *s= command, *t, *chkerr; /* qh_skipfilename is non-const */
80 : char key, opt, prevopt;
81 0 : char chkkey[]= " "; /* check one character options ('s') */
82 0 : char chkopt[]= " "; /* check two character options ('Ta') */
83 0 : char chkopt2[]= " "; /* check three character options ('Q12') */
84 0 : boolT waserr= False;
85 :
86 0 : if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
87 0 : qh_fprintf(qh, qh->ferr, 6026, "qhull internal error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"\n", hiddenflags);
88 0 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
89 : }
90 0 : if (strpbrk(hiddenflags, ",\n\r\t")) {
91 0 : qh_fprintf(qh, qh->ferr, 6027, "qhull internal error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"\n", hiddenflags);
92 0 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
93 : }
94 0 : while (*s && !isspace(*s)) /* skip program name */
95 0 : s++;
96 0 : while (*s) {
97 0 : while (*s && isspace(*s))
98 0 : s++;
99 0 : if (*s == '-')
100 0 : s++;
101 0 : if (!*s)
102 0 : break;
103 0 : key= *s++;
104 0 : chkerr= NULL;
105 0 : if (key == 'T' && (*s == 'I' || *s == 'O')) { /* TI or TO 'file name' */
106 0 : s= qh_skipfilename(qh, ++s);
107 0 : continue;
108 : }
109 0 : chkkey[1]= key;
110 0 : if (strstr(hiddenflags, chkkey)) {
111 0 : chkerr= chkkey;
112 0 : }else if (isupper(key)) {
113 0 : opt= ' ';
114 0 : prevopt= ' ';
115 0 : chkopt[1]= key;
116 0 : chkopt2[1]= key;
117 0 : while (!chkerr && *s && !isspace(*s)) {
118 0 : opt= *s++;
119 0 : if (isalpha(opt)) {
120 0 : chkopt[2]= opt;
121 0 : if (strstr(hiddenflags, chkopt))
122 0 : chkerr= chkopt;
123 0 : if (prevopt != ' ') {
124 0 : chkopt2[2]= prevopt;
125 0 : chkopt2[3]= opt;
126 0 : if (strstr(hiddenflags, chkopt2))
127 0 : chkerr= chkopt2;
128 : }
129 0 : }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
130 0 : && (prevopt == ' ' || islower(prevopt))) {
131 0 : if (isdigit(*s)) { /* Q12 */
132 0 : chkopt2[2]= opt;
133 0 : chkopt2[3]= *s++;
134 0 : if (strstr(hiddenflags, chkopt2))
135 0 : chkerr= chkopt2;
136 : }else {
137 0 : chkopt[2]= opt;
138 0 : if (strstr(hiddenflags, chkopt))
139 0 : chkerr= chkopt;
140 : }
141 : }else {
142 0 : qh_strtod(s-1, &t);
143 0 : if (s < t)
144 0 : s= t;
145 : }
146 0 : prevopt= opt;
147 : }
148 : }
149 0 : if (chkerr) {
150 0 : *chkerr= '\'';
151 0 : chkerr[strlen(chkerr)-1]= '\'';
152 0 : qh_fprintf(qh, qh->ferr, 6029, "qhull option error: option %s is not used with this program.\n It may be used with qhull.\n", chkerr);
153 0 : waserr= True;
154 : }
155 : }
156 0 : if (waserr)
157 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
158 0 : } /* checkflags */
159 :
160 : /*-<a href="qh-globa_r.htm#TOC"
161 : >-------------------------------</a><a name="clear_outputflags">-</a>
162 :
163 : qh_clear_outputflags(qh)
164 : Clear output flags for QhullPoints
165 : */
166 0 : void qh_clear_outputflags(qhT *qh) {
167 : int i,k;
168 :
169 0 : qh->ANNOTATEoutput= False;
170 0 : qh->DOintersections= False;
171 0 : qh->DROPdim= -1;
172 0 : qh->FORCEoutput= False;
173 0 : qh->GETarea= False;
174 0 : qh->GOODpoint= 0;
175 0 : qh->GOODpointp= NULL;
176 0 : qh->GOODthreshold= False;
177 0 : qh->GOODvertex= 0;
178 0 : qh->GOODvertexp= NULL;
179 0 : qh->IStracing= 0;
180 0 : qh->KEEParea= False;
181 0 : qh->KEEPmerge= False;
182 0 : qh->KEEPminArea= REALmax;
183 0 : qh->PRINTcentrums= False;
184 0 : qh->PRINTcoplanar= False;
185 0 : qh->PRINTdots= False;
186 0 : qh->PRINTgood= False;
187 0 : qh->PRINTinner= False;
188 0 : qh->PRINTneighbors= False;
189 0 : qh->PRINTnoplanes= False;
190 0 : qh->PRINToptions1st= False;
191 0 : qh->PRINTouter= False;
192 0 : qh->PRINTprecision= True;
193 0 : qh->PRINTridges= False;
194 0 : qh->PRINTspheres= False;
195 0 : qh->PRINTstatistics= False;
196 0 : qh->PRINTsummary= False;
197 0 : qh->PRINTtransparent= False;
198 0 : qh->SPLITthresholds= False;
199 0 : qh->TRACElevel= 0;
200 0 : qh->TRInormals= False;
201 0 : qh->USEstdout= False;
202 0 : qh->VERIFYoutput= False;
203 0 : for (k=qh->input_dim+1; k--; ) { /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
204 0 : qh->lower_threshold[k]= -REALmax;
205 0 : qh->upper_threshold[k]= REALmax;
206 0 : qh->lower_bound[k]= -REALmax;
207 0 : qh->upper_bound[k]= REALmax;
208 : }
209 :
210 0 : for (i=0; i < qh_PRINTEND; i++) {
211 0 : qh->PRINTout[i]= qh_PRINTnone;
212 : }
213 :
214 0 : if (!qh->qhull_commandsiz2)
215 0 : qh->qhull_commandsiz2= (int)strlen(qh->qhull_command); /* WARN64 */
216 : else {
217 0 : qh->qhull_command[qh->qhull_commandsiz2]= '\0';
218 : }
219 0 : if (!qh->qhull_optionsiz2)
220 0 : qh->qhull_optionsiz2= (int)strlen(qh->qhull_options); /* WARN64 */
221 : else {
222 0 : qh->qhull_options[qh->qhull_optionsiz2]= '\0';
223 0 : qh->qhull_optionlen= qh_OPTIONline; /* start a new line */
224 : }
225 0 : } /* clear_outputflags */
226 :
227 : /*-<a href="qh-globa_r.htm#TOC"
228 : >-------------------------------</a><a name="clock">-</a>
229 :
230 : qh_clock()
231 : return user CPU time in 100ths (qh_SECtick)
232 : only defined for qh_CLOCKtype == 2
233 :
234 : notes:
235 : use first value to determine time 0
236 : from Stevens '92 8.15
237 : */
238 0 : unsigned long qh_clock(qhT *qh) {
239 :
240 : #if (qh_CLOCKtype == 2)
241 : struct tms time;
242 : static long clktck; /* initialized first call and never updated */
243 : double ratio, cpu;
244 : unsigned long ticks;
245 :
246 : if (!clktck) {
247 : if ((clktck= sysconf(_SC_CLK_TCK)) < 0) {
248 : qh_fprintf(qh, qh->ferr, 6030, "qhull internal error (qh_clock): sysconf() failed. Use qh_CLOCKtype 1 in user_r.h\n");
249 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
250 : }
251 : }
252 : if (times(&time) == -1) {
253 : qh_fprintf(qh, qh->ferr, 6031, "qhull internal error (qh_clock): times() failed. Use qh_CLOCKtype 1 in user_r.h\n");
254 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
255 : }
256 : ratio= qh_SECticks / (double)clktck;
257 : ticks= time.tms_utime * ratio;
258 : return ticks;
259 : #else
260 0 : qh_fprintf(qh, qh->ferr, 6032, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user_r.h\n");
261 0 : qh_errexit(qh, qh_ERRqhull, NULL, NULL); /* never returns */
262 0 : return 0;
263 : #endif
264 : } /* clock */
265 :
266 : /*-<a href="qh-globa_r.htm#TOC"
267 : >-------------------------------</a><a name="freebuffers">-</a>
268 :
269 : qh_freebuffers()
270 : free up global memory buffers
271 :
272 : notes:
273 : must match qh_initbuffers()
274 : */
275 5 : void qh_freebuffers(qhT *qh) {
276 :
277 5 : trace5((qh, qh->ferr, 5001, "qh_freebuffers: freeing up global memory buffers\n"));
278 : /* allocated by qh_initqhull_buffers */
279 5 : qh_setfree(qh, &qh->other_points);
280 5 : qh_setfree(qh, &qh->del_vertices);
281 5 : qh_setfree(qh, &qh->coplanarfacetset);
282 5 : qh_memfree(qh, qh->NEARzero, qh->hull_dim * (int)sizeof(realT));
283 5 : qh_memfree(qh, qh->lower_threshold, (qh->input_dim+1) * (int)sizeof(realT));
284 5 : qh_memfree(qh, qh->upper_threshold, (qh->input_dim+1) * (int)sizeof(realT));
285 5 : qh_memfree(qh, qh->lower_bound, (qh->input_dim+1) * (int)sizeof(realT));
286 5 : qh_memfree(qh, qh->upper_bound, (qh->input_dim+1) * (int)sizeof(realT));
287 5 : qh_memfree(qh, qh->gm_matrix, (qh->hull_dim+1) * qh->hull_dim * (int)sizeof(coordT));
288 5 : qh_memfree(qh, qh->gm_row, (qh->hull_dim+1) * (int)sizeof(coordT *));
289 5 : qh->NEARzero= qh->lower_threshold= qh->upper_threshold= NULL;
290 5 : qh->lower_bound= qh->upper_bound= NULL;
291 5 : qh->gm_matrix= NULL;
292 5 : qh->gm_row= NULL;
293 :
294 5 : if (qh->line) /* allocated by qh_readinput, freed if no error */
295 0 : qh_free(qh->line);
296 5 : if (qh->half_space)
297 0 : qh_free(qh->half_space);
298 5 : if (qh->temp_malloc)
299 0 : qh_free(qh->temp_malloc);
300 5 : if (qh->feasible_point) /* allocated by qh_readfeasible */
301 0 : qh_free(qh->feasible_point);
302 5 : if (qh->feasible_string) /* allocated by qh_initflags */
303 0 : qh_free(qh->feasible_string);
304 5 : qh->line= qh->feasible_string= NULL;
305 5 : qh->half_space= qh->feasible_point= qh->temp_malloc= NULL;
306 : /* usually allocated by qh_readinput */
307 5 : if (qh->first_point && qh->POINTSmalloc) {
308 4 : qh_free(qh->first_point);
309 4 : qh->first_point= NULL;
310 : }
311 5 : if (qh->input_points && qh->input_malloc) { /* set by qh_joggleinput */
312 0 : qh_free(qh->input_points);
313 0 : qh->input_points= NULL;
314 : }
315 5 : trace5((qh, qh->ferr, 5002, "qh_freebuffers: finished\n"));
316 5 : } /* freebuffers */
317 :
318 :
319 : /*-<a href="qh-globa_r.htm#TOC"
320 : >-------------------------------</a><a name="freebuild">-</a>
321 :
322 : qh_freebuild(qh, allmem )
323 : free global memory used by qh_initbuild and qh_buildhull
324 : if !allmem,
325 : does not free short memory (e.g., facetT, freed by qh_memfreeshort)
326 :
327 : design:
328 : free centrums
329 : free each vertex
330 : for each facet
331 : free ridges
332 : free outside set, coplanar set, neighbor set, ridge set, vertex set
333 : free facet
334 : free hash table
335 : free interior point
336 : free merge sets
337 : free temporary sets
338 : */
339 5 : void qh_freebuild(qhT *qh, boolT allmem) {
340 : facetT *facet /*, *previousfacet= NULL*/;
341 : vertexT *vertex /*, *previousvertex= NULL*/;
342 : ridgeT *ridge, **ridgep /*, *previousridge= NULL */;
343 : mergeT *merge, **mergep;
344 : int newsize;
345 : boolT freeall;
346 :
347 : /* free qhT global sets first, includes references from qh_buildhull */
348 5 : trace5((qh, qh->ferr, 5004, "qh_freebuild: free global sets\n"));
349 5 : FOREACHmerge_(qh->facet_mergeset) /* usually empty */
350 0 : qh_memfree(qh, merge, (int)sizeof(mergeT));
351 5 : FOREACHmerge_(qh->degen_mergeset) /* usually empty */
352 0 : qh_memfree(qh, merge, (int)sizeof(mergeT));
353 5 : FOREACHmerge_(qh->vertex_mergeset) /* usually empty */
354 0 : qh_memfree(qh, merge, (int)sizeof(mergeT));
355 5 : qh->facet_mergeset= NULL; /* temp set freed by qh_settempfree_all */
356 5 : qh->degen_mergeset= NULL; /* temp set freed by qh_settempfree_all */
357 5 : qh->vertex_mergeset= NULL; /* temp set freed by qh_settempfree_all */
358 5 : qh_setfree(qh, &(qh->hash_table));
359 5 : trace5((qh, qh->ferr, 5003, "qh_freebuild: free temporary sets (qh_settempfree_all)\n"));
360 5 : qh_settempfree_all(qh);
361 5 : trace1((qh, qh->ferr, 1005, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
362 5 : if (qh->del_vertices)
363 4 : qh_settruncate(qh, qh->del_vertices, 0);
364 5 : if (allmem) {
365 0 : while ((vertex= qh->vertex_list)) {
366 0 : if (vertex->next)
367 0 : qh_delvertex(qh, vertex);
368 : else {
369 0 : qh_memfree(qh, vertex, (int)sizeof(vertexT)); /* sentinel */
370 0 : qh->newvertex_list= qh->vertex_list= NULL;
371 0 : break;
372 : }
373 : /* previousvertex= vertex; */ /* in case of memory fault */
374 : /* QHULL_UNUSED(previousvertex) */
375 : }
376 5 : }else if (qh->VERTEXneighbors) {
377 14675 : FORALLvertices
378 14672 : qh_setfreelong(qh, &(vertex->neighbors));
379 : }
380 5 : qh->VERTEXneighbors= False;
381 5 : qh->GOODclosest= NULL;
382 5 : if (allmem) {
383 0 : FORALLfacets {
384 0 : FOREACHridge_(facet->ridges)
385 0 : ridge->seen= False;
386 : }
387 0 : while ((facet= qh->facet_list)) {
388 0 : if (!facet->newfacet || !qh->NEWtentative || qh_setsize(qh, facet->ridges) > 1) { /* skip tentative horizon ridges */
389 0 : trace4((qh, qh->ferr, 4095, "qh_freebuild: delete the previously-seen ridges of f%d\n", facet->id));
390 0 : FOREACHridge_(facet->ridges) {
391 0 : if (ridge->seen)
392 0 : qh_delridge(qh, ridge);
393 : else
394 0 : ridge->seen= True;
395 : /* previousridge= ridge; */ /* in case of memory fault */
396 : /* QHULL_UNUSED(previousridge) */
397 : }
398 : }
399 0 : qh_setfree(qh, &(facet->outsideset));
400 0 : qh_setfree(qh, &(facet->coplanarset));
401 0 : qh_setfree(qh, &(facet->neighbors));
402 0 : qh_setfree(qh, &(facet->ridges));
403 0 : qh_setfree(qh, &(facet->vertices));
404 0 : if (facet->next)
405 0 : qh_delfacet(qh, facet);
406 : else {
407 0 : qh_memfree(qh, facet, (int)sizeof(facetT));
408 0 : qh->visible_list= qh->newfacet_list= qh->facet_list= NULL;
409 : }
410 : /* previousfacet= facet; */ /* in case of memory fault */
411 : /* QHULL_UNUSED(previousfacet) */
412 : }
413 : }else {
414 5 : freeall= True;
415 5 : if (qh_setlarger_quick(qh, qh->hull_dim + 1, &newsize))
416 4 : freeall= False;
417 29341 : FORALLfacets {
418 29336 : qh_setfreelong(qh, &(facet->outsideset));
419 29336 : qh_setfreelong(qh, &(facet->coplanarset));
420 29336 : if (!facet->simplicial || freeall) {
421 0 : qh_setfreelong(qh, &(facet->neighbors));
422 0 : qh_setfreelong(qh, &(facet->ridges));
423 0 : qh_setfreelong(qh, &(facet->vertices));
424 : }
425 : }
426 : }
427 : /* qh internal constants */
428 5 : qh_memfree(qh, qh->interior_point, qh->normal_size);
429 5 : qh->interior_point= NULL;
430 5 : } /* freebuild */
431 :
432 : /*-<a href="qh-globa_r.htm#TOC"
433 : >-------------------------------</a><a name="freeqhull">-</a>
434 :
435 : qh_freeqhull(qh, allmem )
436 :
437 : free global memory and set qhT to 0
438 : if !allmem,
439 : does not free short memory (freed by qh_memfreeshort unless qh_NOmem)
440 :
441 : notes:
442 : sets qh.NOerrexit in case caller forgets to
443 : Does not throw errors
444 :
445 : see:
446 : see qh_initqhull_start2()
447 : For libqhull_r, qhstatT is part of qhT
448 :
449 : design:
450 : free global and temporary memory from qh_initbuild and qh_buildhull
451 : free buffers
452 : */
453 5 : void qh_freeqhull(qhT *qh, boolT allmem) {
454 :
455 5 : qh->NOerrexit= True; /* no more setjmp since called at exit and ~QhullQh */
456 5 : trace1((qh, qh->ferr, 1006, "qh_freeqhull: free global memory\n"));
457 5 : qh_freebuild(qh, allmem);
458 5 : qh_freebuffers(qh);
459 5 : trace1((qh, qh->ferr, 1061, "qh_freeqhull: clear qhT except for qh.qhmem and qh.qhstat\n"));
460 : /* memset is the same in qh_freeqhull() and qh_initqhull_start2() */
461 5 : memset((char *)qh, 0, sizeof(qhT)-sizeof(qhmemT)-sizeof(qhstatT));
462 5 : qh->NOerrexit= True;
463 5 : } /* freeqhull */
464 :
465 : /*-<a href="qh-globa_r.htm#TOC"
466 : >-------------------------------</a><a name="init_A">-</a>
467 :
468 : qh_init_A(qh, infile, outfile, errfile, argc, argv )
469 : initialize memory and stdio files
470 : convert input options to option string (qh.qhull_command)
471 :
472 : notes:
473 : infile may be NULL if qh_readpoints() is not called
474 :
475 : errfile should always be defined. It is used for reporting
476 : errors. outfile is used for output and format options.
477 :
478 : argc/argv may be 0/NULL
479 :
480 : called before error handling initialized
481 : qh_errexit() may not be used
482 : */
483 0 : void qh_init_A(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
484 0 : qh_meminit(qh, errfile);
485 0 : qh_initqhull_start(qh, infile, outfile, errfile);
486 0 : qh_init_qhull_command(qh, argc, argv);
487 0 : } /* init_A */
488 :
489 : /*-<a href="qh-globa_r.htm#TOC"
490 : >-------------------------------</a><a name="init_B">-</a>
491 :
492 : qh_init_B(qh, points, numpoints, dim, ismalloc )
493 : initialize globals for points array
494 :
495 : points has numpoints dim-dimensional points
496 : points[0] is the first coordinate of the first point
497 : points[1] is the second coordinate of the first point
498 : points[dim] is the first coordinate of the second point
499 :
500 : ismalloc=True
501 : Qhull will call qh_free(points) on exit or input transformation
502 : ismalloc=False
503 : Qhull will allocate a new point array if needed for input transformation
504 :
505 : qh.qhull_command
506 : is the option string.
507 : It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
508 :
509 : returns:
510 : if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
511 : projects the input to a new point array
512 :
513 : if qh.DELAUNAY,
514 : qh.hull_dim is increased by one
515 : if qh.ATinfinity,
516 : qh_projectinput adds point-at-infinity for Delaunay tri.
517 :
518 : if qh.SCALEinput
519 : changes the upper and lower bounds of the input, see qh_scaleinput
520 :
521 : if qh.ROTATEinput
522 : rotates the input by a random rotation, see qh_rotateinput
523 : if qh.DELAUNAY
524 : rotates about the last coordinate
525 :
526 : notes:
527 : called after points are defined
528 : qh_errexit() may be used
529 : */
530 5 : void qh_init_B(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc) {
531 5 : qh_initqhull_globals(qh, points, numpoints, dim, ismalloc);
532 4 : if (qh->qhmem.LASTsize == 0)
533 4 : qh_initqhull_mem(qh);
534 : /* mem_r.c and qset_r.c are initialized */
535 4 : qh_initqhull_buffers(qh);
536 4 : qh_initthresholds(qh, qh->qhull_command);
537 4 : if (qh->PROJECTinput || (qh->DELAUNAY && qh->PROJECTdelaunay))
538 4 : qh_projectinput(qh);
539 4 : if (qh->SCALEinput)
540 0 : qh_scaleinput(qh);
541 4 : if (qh->ROTATErandom >= 0) {
542 0 : qh_randommatrix(qh, qh->gm_matrix, qh->hull_dim, qh->gm_row);
543 0 : if (qh->DELAUNAY) {
544 0 : int k, lastk= qh->hull_dim-1;
545 0 : for (k=0; k < lastk; k++) {
546 0 : qh->gm_row[k][lastk]= 0.0;
547 0 : qh->gm_row[lastk][k]= 0.0;
548 : }
549 0 : qh->gm_row[lastk][lastk]= 1.0;
550 : }
551 0 : qh_gram_schmidt(qh, qh->hull_dim, qh->gm_row);
552 0 : qh_rotateinput(qh, qh->gm_row);
553 : }
554 4 : } /* init_B */
555 :
556 : /*-<a href="qh-globa_r.htm#TOC"
557 : >-------------------------------</a><a name="init_qhull_command">-</a>
558 :
559 : qh_init_qhull_command(qh, argc, argv )
560 : build qh.qhull_command from argc/argv
561 : Calls qh_exit if qhull_command is too short
562 :
563 : returns:
564 : a space-delimited string of options (just as typed)
565 :
566 : notes:
567 : makes option string easy to input and output
568 :
569 : argc/argv may be 0/NULL
570 : */
571 0 : void qh_init_qhull_command(qhT *qh, int argc, char *argv[]) {
572 :
573 0 : if (!qh_argv_to_command(argc, argv, qh->qhull_command, (int)sizeof(qh->qhull_command))){
574 : /* Assumes qh.ferr is defined. */
575 0 : qh_fprintf(qh, qh->ferr, 6033, "qhull input error: more than %d characters in command line.\n",
576 : (int)sizeof(qh->qhull_command));
577 0 : qh_exit(qh_ERRinput); /* error reported, can not use qh_errexit */
578 : }
579 0 : } /* init_qhull_command */
580 :
581 : /*-<a href="qh-globa_r.htm#TOC"
582 : >-------------------------------</a><a name="initflags">-</a>
583 :
584 : qh_initflags(qh, commandStr )
585 : set flags and initialized constants from commandStr
586 : calls qh_exit() if qh.NOerrexit
587 :
588 : returns:
589 : sets qh.qhull_command to command if needed
590 :
591 : notes:
592 : ignores first word (e.g., 'qhull' in "qhull d")
593 : use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
594 :
595 : see:
596 : qh_initthresholds() continues processing of 'Pdn' and 'PDn'
597 : 'prompt' in unix_r.c for documentation
598 :
599 : design:
600 : for each space-delimited option group
601 : if top-level option
602 : check syntax
603 : append appropriate option to option string
604 : set appropriate global variable or append printFormat to print options
605 : else
606 : for each sub-option
607 : check syntax
608 : append appropriate option to option string
609 : set appropriate global variable or append printFormat to print options
610 : */
611 5 : void qh_initflags(qhT *qh, char *command) {
612 : int k, i, lastproject;
613 5 : char *s= command, *t = NULL, *prev_s, *start, key, *lastwarning= NULL;
614 5 : boolT isgeom= False, wasproject;
615 : realT r;
616 :
617 5 : if(qh->NOerrexit){
618 0 : qh_fprintf(qh, qh->ferr, 6245, "qhull internal error (qh_initflags): qh.NOerrexit was not cleared before calling qh_initflags(). It should be cleared after setjmp(). Exit qhull.\n");
619 0 : qh_exit(qh_ERRqhull);
620 : }
621 : #ifdef qh_RANDOMdist
622 : qh->RANDOMfactor= qh_RANDOMdist;
623 : qh_option(qh, "Random-qh_RANDOMdist", NULL, &qh->RANDOMfactor);
624 : qh->RANDOMdist= True;
625 : #endif
626 5 : if (command <= &qh->qhull_command[0] || command > &qh->qhull_command[0] + sizeof(qh->qhull_command)) {
627 5 : if (command != &qh->qhull_command[0]) {
628 5 : *qh->qhull_command= '\0';
629 5 : strncat(qh->qhull_command, command, sizeof(qh->qhull_command)-strlen(qh->qhull_command)-1);
630 : }
631 30 : while (*s && !isspace(*s)) /* skip program name */
632 25 : s++;
633 : }
634 30 : while (*s) {
635 50 : while (*s && isspace(*s))
636 25 : s++;
637 25 : if (*s == '-')
638 0 : s++;
639 25 : if (!*s)
640 0 : break;
641 25 : prev_s= s;
642 25 : switch (*s++) {
643 5 : case 'd':
644 5 : qh_option(qh, "delaunay", NULL, NULL);
645 5 : qh->DELAUNAY= True;
646 5 : break;
647 0 : case 'f':
648 0 : qh_option(qh, "facets", NULL, NULL);
649 0 : qh_appendprint(qh, qh_PRINTfacets);
650 0 : break;
651 0 : case 'i':
652 0 : qh_option(qh, "incidence", NULL, NULL);
653 0 : qh_appendprint(qh, qh_PRINTincidences);
654 0 : break;
655 0 : case 'm':
656 0 : qh_option(qh, "mathematica", NULL, NULL);
657 0 : qh_appendprint(qh, qh_PRINTmathematica);
658 0 : break;
659 0 : case 'n':
660 0 : qh_option(qh, "normals", NULL, NULL);
661 0 : qh_appendprint(qh, qh_PRINTnormals);
662 0 : break;
663 0 : case 'o':
664 0 : qh_option(qh, "offFile", NULL, NULL);
665 0 : qh_appendprint(qh, qh_PRINToff);
666 0 : break;
667 0 : case 'p':
668 0 : qh_option(qh, "points", NULL, NULL);
669 0 : qh_appendprint(qh, qh_PRINTpoints);
670 0 : break;
671 0 : case 's':
672 0 : qh_option(qh, "summary", NULL, NULL);
673 0 : qh->PRINTsummary= True;
674 0 : break;
675 0 : case 'v':
676 0 : qh_option(qh, "voronoi", NULL, NULL);
677 0 : qh->VORONOI= True;
678 0 : qh->DELAUNAY= True;
679 0 : break;
680 0 : case 'A':
681 0 : if (!isdigit(*s) && *s != '.' && *s != '-') {
682 0 : qh_fprintf(qh, qh->ferr, 7002, "qhull input warning: no maximum cosine angle given for option 'An'. A1.0 is coplanar\n");
683 0 : lastwarning= s-1;
684 : }else {
685 0 : if (*s == '-') {
686 0 : qh->premerge_cos= -qh_strtod(s, &s);
687 0 : qh_option(qh, "Angle-premerge-", NULL, &qh->premerge_cos);
688 0 : qh->PREmerge= True;
689 : }else {
690 0 : qh->postmerge_cos= qh_strtod(s, &s);
691 0 : qh_option(qh, "Angle-postmerge", NULL, &qh->postmerge_cos);
692 0 : qh->POSTmerge= True;
693 : }
694 0 : qh->MERGING= True;
695 : }
696 0 : break;
697 0 : case 'C':
698 0 : if (!isdigit(*s) && *s != '.' && *s != '-') {
699 0 : qh_fprintf(qh, qh->ferr, 7003, "qhull input warning: no centrum radius given for option 'Cn'\n");
700 0 : lastwarning= s-1;
701 : }else {
702 0 : if (*s == '-') {
703 0 : qh->premerge_centrum= -qh_strtod(s, &s);
704 0 : qh_option(qh, "Centrum-premerge-", NULL, &qh->premerge_centrum);
705 0 : qh->PREmerge= True;
706 : }else {
707 0 : qh->postmerge_centrum= qh_strtod(s, &s);
708 0 : qh_option(qh, "Centrum-postmerge", NULL, &qh->postmerge_centrum);
709 0 : qh->POSTmerge= True;
710 : }
711 0 : qh->MERGING= True;
712 : }
713 0 : break;
714 0 : case 'E':
715 0 : if (*s == '-') {
716 0 : qh_fprintf(qh, qh->ferr, 6363, "qhull option error: expecting a positive number for maximum roundoff 'En'. Got '%s'\n", s-1);
717 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
718 0 : }else if (!isdigit(*s)) {
719 0 : qh_fprintf(qh, qh->ferr, 7005, "qhull option warning: no maximum roundoff given for option 'En'\n");
720 0 : lastwarning= s-1;
721 : }else {
722 0 : qh->DISTround= qh_strtod(s, &s);
723 0 : qh_option(qh, "Distance-roundoff", NULL, &qh->DISTround);
724 0 : qh->SETroundoff= True;
725 : }
726 0 : break;
727 0 : case 'H':
728 0 : start= s;
729 0 : qh->HALFspace= True;
730 0 : qh_strtod(s, &t);
731 0 : while (t > s) {
732 0 : if (*t && !isspace(*t)) {
733 0 : if (*t == ',')
734 0 : t++;
735 : else {
736 0 : qh_fprintf(qh, qh->ferr, 6364, "qhull option error: expecting 'Hn,n,n,...' for feasible point of halfspace intersection. Got '%s'\n", start-1);
737 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
738 : }
739 : }
740 0 : s= t;
741 0 : qh_strtod(s, &t);
742 : }
743 0 : if (start < t) {
744 0 : if (!(qh->feasible_string= (char *)calloc((size_t)(t-start+1), (size_t)1))) {
745 0 : qh_fprintf(qh, qh->ferr, 6034, "qhull error: insufficient memory for 'Hn,n,n'\n");
746 0 : qh_errexit(qh, qh_ERRmem, NULL, NULL);
747 : }
748 0 : strncpy(qh->feasible_string, start, (size_t)(t-start));
749 0 : qh_option(qh, "Halfspace-about", NULL, NULL);
750 0 : qh_option(qh, qh->feasible_string, NULL, NULL);
751 : }else
752 0 : qh_option(qh, "Halfspace", NULL, NULL);
753 0 : break;
754 0 : case 'R':
755 0 : if (!isdigit(*s)) {
756 0 : qh_fprintf(qh, qh->ferr, 7007, "qhull option warning: missing random perturbation for option 'Rn'\n");
757 0 : lastwarning= s-1;
758 : }else {
759 0 : qh->RANDOMfactor= qh_strtod(s, &s);
760 0 : qh_option(qh, "Random-perturb", NULL, &qh->RANDOMfactor);
761 0 : qh->RANDOMdist= True;
762 : }
763 0 : break;
764 0 : case 'V':
765 0 : if (!isdigit(*s) && *s != '-') {
766 0 : qh_fprintf(qh, qh->ferr, 7008, "qhull option warning: missing visible distance for option 'Vn'\n");
767 0 : lastwarning= s-1;
768 : }else {
769 0 : qh->MINvisible= qh_strtod(s, &s);
770 0 : qh_option(qh, "Visible", NULL, &qh->MINvisible);
771 : }
772 0 : break;
773 0 : case 'U':
774 0 : if (!isdigit(*s) && *s != '-') {
775 0 : qh_fprintf(qh, qh->ferr, 7009, "qhull option warning: missing coplanar distance for option 'Un'\n");
776 0 : lastwarning= s-1;
777 : }else {
778 0 : qh->MAXcoplanar= qh_strtod(s, &s);
779 0 : qh_option(qh, "U-coplanar", NULL, &qh->MAXcoplanar);
780 : }
781 0 : break;
782 0 : case 'W':
783 0 : if (*s == '-') {
784 0 : qh_fprintf(qh, qh->ferr, 6365, "qhull option error: expecting a positive number for outside width 'Wn'. Got '%s'\n", s-1);
785 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
786 0 : }else if (!isdigit(*s)) {
787 0 : qh_fprintf(qh, qh->ferr, 7011, "qhull option warning: missing outside width for option 'Wn'\n");
788 0 : lastwarning= s-1;
789 : }else {
790 0 : qh->MINoutside= qh_strtod(s, &s);
791 0 : qh_option(qh, "W-outside", NULL, &qh->MINoutside);
792 0 : qh->APPROXhull= True;
793 : }
794 0 : break;
795 : /************ sub menus ***************/
796 0 : case 'F':
797 0 : while (*s && !isspace(*s)) {
798 0 : switch (*s++) {
799 0 : case 'a':
800 0 : qh_option(qh, "Farea", NULL, NULL);
801 0 : qh_appendprint(qh, qh_PRINTarea);
802 0 : qh->GETarea= True;
803 0 : break;
804 0 : case 'A':
805 0 : qh_option(qh, "FArea-total", NULL, NULL);
806 0 : qh->GETarea= True;
807 0 : break;
808 0 : case 'c':
809 0 : qh_option(qh, "Fcoplanars", NULL, NULL);
810 0 : qh_appendprint(qh, qh_PRINTcoplanars);
811 0 : break;
812 0 : case 'C':
813 0 : qh_option(qh, "FCentrums", NULL, NULL);
814 0 : qh_appendprint(qh, qh_PRINTcentrums);
815 0 : break;
816 0 : case 'd':
817 0 : qh_option(qh, "Fd-cdd-in", NULL, NULL);
818 0 : qh->CDDinput= True;
819 0 : break;
820 0 : case 'D':
821 0 : qh_option(qh, "FD-cdd-out", NULL, NULL);
822 0 : qh->CDDoutput= True;
823 0 : break;
824 0 : case 'F':
825 0 : qh_option(qh, "FFacets-xridge", NULL, NULL);
826 0 : qh_appendprint(qh, qh_PRINTfacets_xridge);
827 0 : break;
828 0 : case 'i':
829 0 : qh_option(qh, "Finner", NULL, NULL);
830 0 : qh_appendprint(qh, qh_PRINTinner);
831 0 : break;
832 0 : case 'I':
833 0 : qh_option(qh, "FIDs", NULL, NULL);
834 0 : qh_appendprint(qh, qh_PRINTids);
835 0 : break;
836 0 : case 'm':
837 0 : qh_option(qh, "Fmerges", NULL, NULL);
838 0 : qh_appendprint(qh, qh_PRINTmerges);
839 0 : break;
840 0 : case 'M':
841 0 : qh_option(qh, "FMaple", NULL, NULL);
842 0 : qh_appendprint(qh, qh_PRINTmaple);
843 0 : break;
844 0 : case 'n':
845 0 : qh_option(qh, "Fneighbors", NULL, NULL);
846 0 : qh_appendprint(qh, qh_PRINTneighbors);
847 0 : break;
848 0 : case 'N':
849 0 : qh_option(qh, "FNeighbors-vertex", NULL, NULL);
850 0 : qh_appendprint(qh, qh_PRINTvneighbors);
851 0 : break;
852 0 : case 'o':
853 0 : qh_option(qh, "Fouter", NULL, NULL);
854 0 : qh_appendprint(qh, qh_PRINTouter);
855 0 : break;
856 0 : case 'O':
857 0 : if (qh->PRINToptions1st) {
858 0 : qh_option(qh, "FOptions", NULL, NULL);
859 0 : qh_appendprint(qh, qh_PRINToptions);
860 : }else
861 0 : qh->PRINToptions1st= True;
862 0 : break;
863 0 : case 'p':
864 0 : qh_option(qh, "Fpoint-intersect", NULL, NULL);
865 0 : qh_appendprint(qh, qh_PRINTpointintersect);
866 0 : break;
867 0 : case 'P':
868 0 : qh_option(qh, "FPoint-nearest", NULL, NULL);
869 0 : qh_appendprint(qh, qh_PRINTpointnearest);
870 0 : break;
871 0 : case 'Q':
872 0 : qh_option(qh, "FQhull", NULL, NULL);
873 0 : qh_appendprint(qh, qh_PRINTqhull);
874 0 : break;
875 0 : case 's':
876 0 : qh_option(qh, "Fsummary", NULL, NULL);
877 0 : qh_appendprint(qh, qh_PRINTsummary);
878 0 : break;
879 0 : case 'S':
880 0 : qh_option(qh, "FSize", NULL, NULL);
881 0 : qh_appendprint(qh, qh_PRINTsize);
882 0 : qh->GETarea= True;
883 0 : break;
884 0 : case 't':
885 0 : qh_option(qh, "Ftriangles", NULL, NULL);
886 0 : qh_appendprint(qh, qh_PRINTtriangles);
887 0 : break;
888 0 : case 'v':
889 : /* option set in qh_initqhull_globals */
890 0 : qh_appendprint(qh, qh_PRINTvertices);
891 0 : break;
892 0 : case 'V':
893 0 : qh_option(qh, "FVertex-average", NULL, NULL);
894 0 : qh_appendprint(qh, qh_PRINTaverage);
895 0 : break;
896 0 : case 'x':
897 0 : qh_option(qh, "Fxtremes", NULL, NULL);
898 0 : qh_appendprint(qh, qh_PRINTextremes);
899 0 : break;
900 0 : default:
901 0 : s--;
902 0 : qh_fprintf(qh, qh->ferr, 7012, "qhull option warning: unknown 'F' output option 'F%c', skip to next space\n", (int)s[0]);
903 0 : lastwarning= s-1;
904 0 : while (*++s && !isspace(*s));
905 0 : break;
906 : }
907 : }
908 0 : break;
909 0 : case 'G':
910 0 : isgeom= True;
911 0 : qh_appendprint(qh, qh_PRINTgeom);
912 0 : while (*s && !isspace(*s)) {
913 0 : switch (*s++) {
914 0 : case 'a':
915 0 : qh_option(qh, "Gall-points", NULL, NULL);
916 0 : qh->PRINTdots= True;
917 0 : break;
918 0 : case 'c':
919 0 : qh_option(qh, "Gcentrums", NULL, NULL);
920 0 : qh->PRINTcentrums= True;
921 0 : break;
922 0 : case 'h':
923 0 : qh_option(qh, "Gintersections", NULL, NULL);
924 0 : qh->DOintersections= True;
925 0 : break;
926 0 : case 'i':
927 0 : qh_option(qh, "Ginner", NULL, NULL);
928 0 : qh->PRINTinner= True;
929 0 : break;
930 0 : case 'n':
931 0 : qh_option(qh, "Gno-planes", NULL, NULL);
932 0 : qh->PRINTnoplanes= True;
933 0 : break;
934 0 : case 'o':
935 0 : qh_option(qh, "Gouter", NULL, NULL);
936 0 : qh->PRINTouter= True;
937 0 : break;
938 0 : case 'p':
939 0 : qh_option(qh, "Gpoints", NULL, NULL);
940 0 : qh->PRINTcoplanar= True;
941 0 : break;
942 0 : case 'r':
943 0 : qh_option(qh, "Gridges", NULL, NULL);
944 0 : qh->PRINTridges= True;
945 0 : break;
946 0 : case 't':
947 0 : qh_option(qh, "Gtransparent", NULL, NULL);
948 0 : qh->PRINTtransparent= True;
949 0 : break;
950 0 : case 'v':
951 0 : qh_option(qh, "Gvertices", NULL, NULL);
952 0 : qh->PRINTspheres= True;
953 0 : break;
954 0 : case 'D':
955 0 : if (!isdigit(*s)) {
956 0 : qh_fprintf(qh, qh->ferr, 7004, "qhull option warning: missing dimension for option 'GDn'\n");
957 0 : lastwarning= s-2;
958 : }else {
959 0 : if (qh->DROPdim >= 0) {
960 0 : qh_fprintf(qh, qh->ferr, 7013, "qhull option warning: can only drop one dimension. Previous 'GD%d' ignored\n",
961 : qh->DROPdim);
962 0 : lastwarning= s-2;
963 : }
964 0 : qh->DROPdim= qh_strtol(s, &s);
965 0 : qh_option(qh, "GDrop-dim", &qh->DROPdim, NULL);
966 : }
967 0 : break;
968 0 : default:
969 0 : s--;
970 0 : qh_fprintf(qh, qh->ferr, 7014, "qhull option warning: unknown 'G' geomview option 'G%c', skip to next space\n", (int)s[0]);
971 0 : lastwarning= s-1;
972 0 : while (*++s && !isspace(*s));
973 0 : break;
974 : }
975 : }
976 0 : break;
977 0 : case 'P':
978 0 : while (*s && !isspace(*s)) {
979 0 : switch (*s++) {
980 0 : case 'd': case 'D': /* see qh_initthresholds() */
981 0 : key= s[-1];
982 0 : i= qh_strtol(s, &s);
983 0 : r= 0;
984 0 : if (*s == ':') {
985 0 : s++;
986 0 : r= qh_strtod(s, &s);
987 : }
988 0 : if (key == 'd')
989 0 : qh_option(qh, "Pdrop-facets-dim-less", &i, &r);
990 : else
991 0 : qh_option(qh, "PDrop-facets-dim-more", &i, &r);
992 0 : break;
993 0 : case 'g':
994 0 : qh_option(qh, "Pgood-facets", NULL, NULL);
995 0 : qh->PRINTgood= True;
996 0 : break;
997 0 : case 'G':
998 0 : qh_option(qh, "PGood-facet-neighbors", NULL, NULL);
999 0 : qh->PRINTneighbors= True;
1000 0 : break;
1001 0 : case 'o':
1002 0 : qh_option(qh, "Poutput-forced", NULL, NULL);
1003 0 : qh->FORCEoutput= True;
1004 0 : break;
1005 0 : case 'p':
1006 0 : qh_option(qh, "Pprecision-ignore", NULL, NULL);
1007 0 : qh->PRINTprecision= False;
1008 0 : break;
1009 0 : case 'A':
1010 0 : if (!isdigit(*s)) {
1011 0 : qh_fprintf(qh, qh->ferr, 7006, "qhull option warning: missing facet count for keep area option 'PAn'\n");
1012 0 : lastwarning= s-2;
1013 : }else {
1014 0 : qh->KEEParea= qh_strtol(s, &s);
1015 0 : qh_option(qh, "PArea-keep", &qh->KEEParea, NULL);
1016 0 : qh->GETarea= True;
1017 : }
1018 0 : break;
1019 0 : case 'F':
1020 0 : if (!isdigit(*s)) {
1021 0 : qh_fprintf(qh, qh->ferr, 7010, "qhull option warning: missing facet area for option 'PFn'\n");
1022 0 : lastwarning= s-2;
1023 : }else {
1024 0 : qh->KEEPminArea= qh_strtod(s, &s);
1025 0 : qh_option(qh, "PFacet-area-keep", NULL, &qh->KEEPminArea);
1026 0 : qh->GETarea= True;
1027 : }
1028 0 : break;
1029 0 : case 'M':
1030 0 : if (!isdigit(*s)) {
1031 0 : qh_fprintf(qh, qh->ferr, 7090, "qhull option warning: missing merge count for option 'PMn'\n");
1032 0 : lastwarning= s-2;
1033 : }else {
1034 0 : qh->KEEPmerge= qh_strtol(s, &s);
1035 0 : qh_option(qh, "PMerge-keep", &qh->KEEPmerge, NULL);
1036 : }
1037 0 : break;
1038 0 : default:
1039 0 : s--;
1040 0 : qh_fprintf(qh, qh->ferr, 7015, "qhull option warning: unknown 'P' print option 'P%c', skip to next space\n", (int)s[0]);
1041 0 : lastwarning= s-1;
1042 0 : while (*++s && !isspace(*s));
1043 0 : break;
1044 : }
1045 : }
1046 0 : break;
1047 20 : case 'Q':
1048 20 : lastproject= -1;
1049 40 : while (*s && !isspace(*s)) {
1050 20 : switch (*s++) {
1051 0 : case 'a':
1052 0 : qh_option(qh, "Qallow-short", NULL, NULL);
1053 0 : qh->ALLOWshort= True;
1054 0 : break;
1055 5 : case 'b': case 'B': /* handled by qh_initthresholds */
1056 5 : key= s[-1];
1057 5 : if (key == 'b' && *s == 'B') {
1058 0 : s++;
1059 0 : r= qh_DEFAULTbox;
1060 0 : qh->SCALEinput= True;
1061 0 : qh_option(qh, "QbBound-unit-box", NULL, &r);
1062 0 : break;
1063 : }
1064 5 : if (key == 'b' && *s == 'b') {
1065 5 : s++;
1066 5 : qh->SCALElast= True;
1067 5 : qh_option(qh, "Qbbound-last", NULL, NULL);
1068 5 : break;
1069 : }
1070 0 : k= qh_strtol(s, &s);
1071 0 : r= 0.0;
1072 0 : wasproject= False;
1073 0 : if (*s == ':') {
1074 0 : s++;
1075 0 : if ((r= qh_strtod(s, &s)) == 0.0) {
1076 0 : t= s; /* need true dimension for memory allocation */
1077 0 : while (*t && !isspace(*t)) {
1078 0 : if (toupper(*t++) == 'B'
1079 0 : && k == qh_strtol(t, &t)
1080 0 : && *t++ == ':'
1081 0 : && qh_strtod(t, &t) == 0.0) {
1082 0 : qh->PROJECTinput++;
1083 0 : trace2((qh, qh->ferr, 2004, "qh_initflags: project dimension %d\n", k));
1084 0 : qh_option(qh, "Qb-project-dim", &k, NULL);
1085 0 : wasproject= True;
1086 0 : lastproject= k;
1087 0 : break;
1088 : }
1089 : }
1090 : }
1091 : }
1092 0 : if (!wasproject) {
1093 0 : if (lastproject == k && r == 0.0)
1094 0 : lastproject= -1; /* doesn't catch all possible sequences */
1095 0 : else if (key == 'b') {
1096 0 : qh->SCALEinput= True;
1097 0 : if (r == 0.0)
1098 0 : r= -qh_DEFAULTbox;
1099 0 : qh_option(qh, "Qbound-dim-low", &k, &r);
1100 : }else {
1101 0 : qh->SCALEinput= True;
1102 0 : if (r == 0.0)
1103 0 : r= qh_DEFAULTbox;
1104 0 : qh_option(qh, "QBound-dim-high", &k, &r);
1105 : }
1106 : }
1107 0 : break;
1108 5 : case 'c':
1109 5 : qh_option(qh, "Qcoplanar-keep", NULL, NULL);
1110 5 : qh->KEEPcoplanar= True;
1111 5 : break;
1112 0 : case 'f':
1113 0 : qh_option(qh, "Qfurthest-outside", NULL, NULL);
1114 0 : qh->BESToutside= True;
1115 0 : break;
1116 0 : case 'g':
1117 0 : qh_option(qh, "Qgood-facets-only", NULL, NULL);
1118 0 : qh->ONLYgood= True;
1119 0 : break;
1120 0 : case 'i':
1121 0 : qh_option(qh, "Qinterior-keep", NULL, NULL);
1122 0 : qh->KEEPinside= True;
1123 0 : break;
1124 0 : case 'm':
1125 0 : qh_option(qh, "Qmax-outside-only", NULL, NULL);
1126 0 : qh->ONLYmax= True;
1127 0 : break;
1128 0 : case 'r':
1129 0 : qh_option(qh, "Qrandom-outside", NULL, NULL);
1130 0 : qh->RANDOMoutside= True;
1131 0 : break;
1132 0 : case 's':
1133 0 : qh_option(qh, "Qsearch-initial-simplex", NULL, NULL);
1134 0 : qh->ALLpoints= True;
1135 0 : break;
1136 5 : case 't':
1137 5 : qh_option(qh, "Qtriangulate", NULL, NULL);
1138 5 : qh->TRIangulate= True;
1139 5 : break;
1140 0 : case 'T':
1141 0 : qh_option(qh, "QTestPoints", NULL, NULL);
1142 0 : if (!isdigit(*s)) {
1143 0 : qh_fprintf(qh, qh->ferr, 7091, "qhull option warning: missing number of test points for option 'QTn'\n");
1144 0 : lastwarning= s-2;
1145 : }else {
1146 0 : qh->TESTpoints= qh_strtol(s, &s);
1147 0 : qh_option(qh, "QTestPoints", &qh->TESTpoints, NULL);
1148 : }
1149 0 : break;
1150 0 : case 'u':
1151 0 : qh_option(qh, "QupperDelaunay", NULL, NULL);
1152 0 : qh->UPPERdelaunay= True;
1153 0 : break;
1154 0 : case 'v':
1155 0 : qh_option(qh, "Qvertex-neighbors-convex", NULL, NULL);
1156 0 : qh->TESTvneighbors= True;
1157 0 : break;
1158 0 : case 'x':
1159 0 : qh_option(qh, "Qxact-merge", NULL, NULL);
1160 0 : qh->MERGEexact= True;
1161 0 : break;
1162 5 : case 'z':
1163 5 : qh_option(qh, "Qz-infinity-point", NULL, NULL);
1164 5 : qh->ATinfinity= True;
1165 5 : break;
1166 0 : case '0':
1167 0 : qh_option(qh, "Q0-no-premerge", NULL, NULL);
1168 0 : qh->NOpremerge= True;
1169 0 : break;
1170 0 : case '1':
1171 0 : if (!isdigit(*s)) {
1172 0 : qh_option(qh, "Q1-angle-merge", NULL, NULL);
1173 0 : qh->ANGLEmerge= True;
1174 0 : break;
1175 : }
1176 0 : switch (*s++) {
1177 0 : case '0':
1178 0 : qh_option(qh, "Q10-no-narrow", NULL, NULL);
1179 0 : qh->NOnarrow= True;
1180 0 : break;
1181 0 : case '1':
1182 0 : qh_option(qh, "Q11-trinormals Qtriangulate", NULL, NULL);
1183 0 : qh->TRInormals= True;
1184 0 : qh->TRIangulate= True;
1185 0 : break;
1186 0 : case '2':
1187 0 : qh_option(qh, "Q12-allow-wide", NULL, NULL);
1188 0 : qh->ALLOWwide= True;
1189 0 : break;
1190 0 : case '4':
1191 : #ifndef qh_NOmerge
1192 0 : qh_option(qh, "Q14-merge-pinched-vertices", NULL, NULL);
1193 0 : qh->MERGEpinched= True;
1194 : #else
1195 : /* ignore 'Q14' for q_benchmark testing of difficult cases for Qhull */
1196 : qh_fprintf(qh, qh->ferr, 7099, "qhull option warning: option 'Q14-merge-pinched' disabled due to qh_NOmerge\n");
1197 : #endif
1198 0 : break;
1199 0 : case '7':
1200 0 : qh_option(qh, "Q15-check-duplicates", NULL, NULL);
1201 0 : qh->CHECKduplicates= True;
1202 0 : break;
1203 0 : default:
1204 0 : s--;
1205 0 : qh_fprintf(qh, qh->ferr, 7016, "qhull option warning: unknown 'Q' qhull option 'Q1%c', skip to next space\n", (int)s[0]);
1206 0 : lastwarning= s-1;
1207 0 : while (*++s && !isspace(*s));
1208 0 : break;
1209 : }
1210 0 : break;
1211 0 : case '2':
1212 0 : qh_option(qh, "Q2-no-merge-independent", NULL, NULL);
1213 0 : qh->MERGEindependent= False;
1214 0 : goto LABELcheckdigit;
1215 : break; /* no gcc warnings */
1216 0 : case '3':
1217 0 : qh_option(qh, "Q3-no-merge-vertices", NULL, NULL);
1218 0 : qh->MERGEvertices= False;
1219 0 : LABELcheckdigit:
1220 0 : if (isdigit(*s)) {
1221 0 : qh_fprintf(qh, qh->ferr, 7017, "qhull option warning: can not follow '1', '2', or '3' with a digit. 'Q%c%c' skipped\n", *(s-1), *s);
1222 0 : lastwarning= s-2;
1223 0 : s++;
1224 : }
1225 0 : break;
1226 0 : case '4':
1227 0 : qh_option(qh, "Q4-avoid-old-into-new", NULL, NULL);
1228 0 : qh->AVOIDold= True;
1229 0 : break;
1230 0 : case '5':
1231 0 : qh_option(qh, "Q5-no-check-outer", NULL, NULL);
1232 0 : qh->SKIPcheckmax= True;
1233 0 : break;
1234 0 : case '6':
1235 0 : qh_option(qh, "Q6-no-concave-merge", NULL, NULL);
1236 0 : qh->SKIPconvex= True;
1237 0 : break;
1238 0 : case '7':
1239 0 : qh_option(qh, "Q7-no-breadth-first", NULL, NULL);
1240 0 : qh->VIRTUALmemory= True;
1241 0 : break;
1242 0 : case '8':
1243 0 : qh_option(qh, "Q8-no-near-inside", NULL, NULL);
1244 0 : qh->NOnearinside= True;
1245 0 : break;
1246 0 : case '9':
1247 0 : qh_option(qh, "Q9-pick-furthest", NULL, NULL);
1248 0 : qh->PICKfurthest= True;
1249 0 : break;
1250 0 : case 'G':
1251 0 : i= qh_strtol(s, &t);
1252 0 : if (qh->GOODpoint) {
1253 0 : qh_fprintf(qh, qh->ferr, 7018, "qhull option warning: good point already defined for option 'QGn'. Ignored\n");
1254 0 : lastwarning= s-2;
1255 0 : }else if (s == t) {
1256 0 : qh_fprintf(qh, qh->ferr, 7019, "qhull option warning: missing good point id for option 'QGn'. Ignored\n");
1257 0 : lastwarning= s-2;
1258 0 : }else if (i < 0 || *s == '-') {
1259 0 : qh->GOODpoint= i-1;
1260 0 : qh_option(qh, "QGood-if-dont-see-point", &i, NULL);
1261 : }else {
1262 0 : qh->GOODpoint= i+1;
1263 0 : qh_option(qh, "QGood-if-see-point", &i, NULL);
1264 : }
1265 0 : s= t;
1266 0 : break;
1267 0 : case 'J':
1268 0 : if (!isdigit(*s) && *s != '-')
1269 0 : qh->JOGGLEmax= 0.0;
1270 : else {
1271 0 : qh->JOGGLEmax= (realT) qh_strtod(s, &s);
1272 0 : qh_option(qh, "QJoggle", NULL, &qh->JOGGLEmax);
1273 : }
1274 0 : break;
1275 0 : case 'R':
1276 0 : if (!isdigit(*s) && *s != '-') {
1277 0 : qh_fprintf(qh, qh->ferr, 7020, "qhull option warning: missing random seed for option 'QRn'\n");
1278 0 : lastwarning= s-2;
1279 : }else {
1280 0 : qh->ROTATErandom= i= qh_strtol(s, &s);
1281 0 : if (i > 0)
1282 0 : qh_option(qh, "QRotate-id", &i, NULL );
1283 0 : else if (i < -1)
1284 0 : qh_option(qh, "QRandom-seed", &i, NULL );
1285 : }
1286 0 : break;
1287 0 : case 'V':
1288 0 : i= qh_strtol(s, &t);
1289 0 : if (qh->GOODvertex) {
1290 0 : qh_fprintf(qh, qh->ferr, 7021, "qhull option warning: good vertex already defined for option 'QVn'. Ignored\n");
1291 0 : lastwarning= s-2;
1292 0 : }else if (s == t) {
1293 0 : qh_fprintf(qh, qh->ferr, 7022, "qhull option warning: no good point id given for option 'QVn'. Ignored\n");
1294 0 : lastwarning= s-2;
1295 0 : }else if (i < 0) {
1296 0 : qh->GOODvertex= i - 1;
1297 0 : qh_option(qh, "QV-good-facets-not-point", &i, NULL);
1298 : }else {
1299 0 : qh_option(qh, "QV-good-facets-point", &i, NULL);
1300 0 : qh->GOODvertex= i + 1;
1301 : }
1302 0 : s= t;
1303 0 : break;
1304 0 : case 'w':
1305 0 : qh_option(qh, "Qwarn-allow", NULL, NULL);
1306 0 : qh->ALLOWwarning= True;
1307 0 : break;
1308 0 : default:
1309 0 : s--;
1310 0 : qh_fprintf(qh, qh->ferr, 7023, "qhull option warning: unknown 'Q' qhull option 'Q%c', skip to next space\n", (int)s[0]);
1311 0 : lastwarning= s-1;
1312 0 : while (*++s && !isspace(*s));
1313 0 : break;
1314 : }
1315 : }
1316 20 : break;
1317 0 : case 'T':
1318 0 : while (*s && !isspace(*s)) {
1319 0 : if (isdigit(*s) || *s == '-')
1320 0 : qh->IStracing= qh_strtol(s, &s);
1321 0 : else switch (*s++) {
1322 0 : case 'a':
1323 0 : qh_option(qh, "Tannotate-output", NULL, NULL);
1324 0 : qh->ANNOTATEoutput= True;
1325 0 : break;
1326 0 : case 'c':
1327 0 : qh_option(qh, "Tcheck-frequently", NULL, NULL);
1328 0 : qh->CHECKfrequently= True;
1329 0 : break;
1330 0 : case 'f':
1331 0 : qh_option(qh, "Tflush", NULL, NULL);
1332 0 : qh->FLUSHprint= True;
1333 0 : break;
1334 0 : case 's':
1335 0 : qh_option(qh, "Tstatistics", NULL, NULL);
1336 0 : qh->PRINTstatistics= True;
1337 0 : break;
1338 0 : case 'v':
1339 0 : qh_option(qh, "Tverify", NULL, NULL);
1340 0 : qh->VERIFYoutput= True;
1341 0 : break;
1342 0 : case 'z':
1343 0 : if (qh->ferr == qh_FILEstderr) {
1344 : /* The C++ interface captures the output in qh_fprint_qhull() */
1345 0 : qh_option(qh, "Tz-stdout", NULL, NULL);
1346 0 : qh->USEstdout= True;
1347 0 : }else if (!qh->fout) {
1348 0 : qh_fprintf(qh, qh->ferr, 7024, "qhull option warning: output file undefined(stdout). Option 'Tz' ignored.\n");
1349 0 : lastwarning= s-2;
1350 : }else {
1351 0 : qh_option(qh, "Tz-stdout", NULL, NULL);
1352 0 : qh->USEstdout= True;
1353 0 : qh->ferr= qh->fout;
1354 0 : qh->qhmem.ferr= qh->fout;
1355 : }
1356 0 : break;
1357 0 : case 'C':
1358 0 : if (!isdigit(*s)) {
1359 0 : qh_fprintf(qh, qh->ferr, 7025, "qhull option warning: missing point id for cone for trace option 'TCn'\n");
1360 0 : lastwarning= s-2;
1361 : }else {
1362 0 : i= qh_strtol(s, &s);
1363 0 : qh_option(qh, "TCone-stop", &i, NULL);
1364 0 : qh->STOPcone= i + 1;
1365 : }
1366 0 : break;
1367 0 : case 'F':
1368 0 : if (!isdigit(*s)) {
1369 0 : qh_fprintf(qh, qh->ferr, 7026, "qhull option warning: missing frequency count for trace option 'TFn'\n");
1370 0 : lastwarning= s-2;
1371 : }else {
1372 0 : qh->REPORTfreq= qh_strtol(s, &s);
1373 0 : qh_option(qh, "TFacet-log", &qh->REPORTfreq, NULL);
1374 0 : qh->REPORTfreq2= qh->REPORTfreq/2; /* for tracemerging() */
1375 : }
1376 0 : break;
1377 0 : case 'I':
1378 0 : while (isspace(*s))
1379 0 : s++;
1380 0 : t= qh_skipfilename(qh, s);
1381 : {
1382 : char filename[qh_FILENAMElen];
1383 :
1384 0 : qh_copyfilename(qh, filename, (int)sizeof(filename), s, (int)(t-s)); /* WARN64 */
1385 0 : s= t;
1386 0 : if (!freopen(filename, "r", stdin)) {
1387 0 : qh_fprintf(qh, qh->ferr, 6041, "qhull option error: cannot open 'TI' file \"%s\"\n", filename);
1388 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1389 : }else {
1390 0 : qh_option(qh, "TInput-file", NULL, NULL);
1391 0 : qh_option(qh, filename, NULL, NULL);
1392 : }
1393 : }
1394 0 : break;
1395 0 : case 'O':
1396 0 : while (isspace(*s))
1397 0 : s++;
1398 0 : t= qh_skipfilename(qh, s);
1399 : {
1400 : char filename[qh_FILENAMElen];
1401 :
1402 0 : qh_copyfilename(qh, filename, (int)sizeof(filename), s, (int)(t-s)); /* WARN64 */
1403 0 : if (!qh->fout) {
1404 0 : qh_fprintf(qh, qh->ferr, 7092, "qhull option warning: qh.fout was not set by caller of qh_initflags. Cannot use option 'TO' to redirect output. Ignoring option 'TO'\n");
1405 0 : lastwarning= s-2;
1406 0 : }else if (!freopen(filename, "w", qh->fout)) {
1407 0 : qh_fprintf(qh, qh->ferr, 6044, "qhull option error: cannot open file \"%s\" for writing as option 'TO'. It is already in use or read-only\n", filename);
1408 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1409 : }else {
1410 0 : qh_option(qh, "TOutput-file", NULL, NULL);
1411 0 : qh_option(qh, filename, NULL, NULL);
1412 : }
1413 0 : s= t;
1414 : }
1415 0 : break;
1416 0 : case 'A':
1417 0 : if (!isdigit(*s)) {
1418 0 : qh_fprintf(qh, qh->ferr, 7093, "qhull option warning: missing count of added points for trace option 'TAn'\n");
1419 0 : lastwarning= s-2;
1420 : }else {
1421 0 : i= qh_strtol(s, &t);
1422 0 : qh->STOPadd= i + 1;
1423 0 : qh_option(qh, "TA-stop-add", &i, NULL);
1424 : }
1425 0 : s= t;
1426 0 : break;
1427 0 : case 'P':
1428 0 : if (*s == '-') {
1429 0 : if (s[1] == '1' && !isdigit(s[2])) {
1430 0 : s += 2;
1431 0 : qh->TRACEpoint= qh_IDunknown; /* qh_buildhull done */
1432 0 : qh_option(qh, "Trace-point", &qh->TRACEpoint, NULL);
1433 : }else {
1434 0 : qh_fprintf(qh, qh->ferr, 7100, "qhull option warning: negative point id for trace option 'TPn'. Expecting 'TP-1' for tracing after qh_buildhull and qh_postmerge\n");
1435 0 : lastwarning= s-2;
1436 0 : while (isdigit(*(++s)))
1437 : ; /* skip digits */
1438 : }
1439 0 : }else if (!isdigit(*s)) {
1440 0 : qh_fprintf(qh, qh->ferr, 7029, "qhull option warning: missing point id or -1 for trace option 'TPn'\n");
1441 0 : lastwarning= s-2;
1442 : }else {
1443 0 : qh->TRACEpoint= qh_strtol(s, &s);
1444 0 : qh_option(qh, "Trace-point", &qh->TRACEpoint, NULL);
1445 : }
1446 0 : break;
1447 0 : case 'M':
1448 0 : if (!isdigit(*s)) {
1449 0 : qh_fprintf(qh, qh->ferr, 7030, "qhull option warning: missing merge id for trace option 'TMn'\n");
1450 0 : lastwarning= s-2;
1451 : }else {
1452 0 : qh->TRACEmerge= qh_strtol(s, &s);
1453 0 : qh_option(qh, "Trace-merge", &qh->TRACEmerge, NULL);
1454 : }
1455 0 : break;
1456 0 : case 'R':
1457 0 : if (!isdigit(*s)) {
1458 0 : qh_fprintf(qh, qh->ferr, 7031, "qhull option warning: missing rerun count for trace option 'TRn'\n");
1459 0 : lastwarning= s-2;
1460 : }else {
1461 0 : qh->RERUN= qh_strtol(s, &s);
1462 0 : qh_option(qh, "TRerun", &qh->RERUN, NULL);
1463 : }
1464 0 : break;
1465 0 : case 'V':
1466 0 : i= qh_strtol(s, &t);
1467 0 : if (s == t) {
1468 0 : qh_fprintf(qh, qh->ferr, 7032, "qhull option warning: missing furthest point id for trace option 'TVn'\n");
1469 0 : lastwarning= s-2;
1470 0 : }else if (i < 0) {
1471 0 : qh->STOPpoint= i - 1;
1472 0 : qh_option(qh, "TV-stop-before-point", &i, NULL);
1473 : }else {
1474 0 : qh->STOPpoint= i + 1;
1475 0 : qh_option(qh, "TV-stop-after-point", &i, NULL);
1476 : }
1477 0 : s= t;
1478 0 : break;
1479 0 : case 'W':
1480 0 : if (!isdigit(*s)) {
1481 0 : qh_fprintf(qh, qh->ferr, 7033, "qhull option warning: missing max width for trace option 'TWn'\n");
1482 0 : lastwarning= s-2;
1483 : }else {
1484 0 : qh->TRACEdist= (realT) qh_strtod(s, &s);
1485 0 : qh_option(qh, "TWide-trace", NULL, &qh->TRACEdist);
1486 : }
1487 0 : break;
1488 0 : default:
1489 0 : s--;
1490 0 : qh_fprintf(qh, qh->ferr, 7034, "qhull option warning: unknown 'T' trace option 'T%c', skip to next space\n", (int)s[0]);
1491 0 : lastwarning= s-2;
1492 0 : while (*++s && !isspace(*s));
1493 0 : break;
1494 : }
1495 : }
1496 0 : break;
1497 0 : default:
1498 0 : qh_fprintf(qh, qh->ferr, 7094, "qhull option warning: unknown option '%c'(%x)\n",
1499 0 : (int)s[-1], (int)s[-1]);
1500 0 : lastwarning= s-2;
1501 0 : break;
1502 : }
1503 25 : if (s-1 == prev_s && *s && !isspace(*s)) {
1504 0 : qh_fprintf(qh, qh->ferr, 7036, "qhull option warning: missing space after option '%c'(%x), reserved for sub-options, ignoring '%c' options to next space\n",
1505 0 : (int)*prev_s, (int)*prev_s, (int)*prev_s);
1506 0 : lastwarning= s-1;
1507 0 : while (*s && !isspace(*s))
1508 0 : s++;
1509 : }
1510 : }
1511 5 : if (qh->STOPcone && qh->JOGGLEmax < REALmax/2) {
1512 0 : qh_fprintf(qh, qh->ferr, 7078, "qhull option warning: 'TCn' (stopCone) ignored when used with 'QJn' (joggle)\n");
1513 0 : lastwarning= command;
1514 : }
1515 5 : if (isgeom && !qh->FORCEoutput && qh->PRINTout[1]) {
1516 0 : qh_fprintf(qh, qh->ferr, 7037, "qhull option warning: additional output formats ('Fc',etc.) are not compatible with Geomview ('G'). Use option 'Po' to override\n");
1517 0 : lastwarning= command;
1518 : }
1519 5 : if (lastwarning && !qh->ALLOWwarning) {
1520 0 : qh_fprintf(qh, qh->ferr, 6035, "qhull option error: see previous warnings, use 'Qw' to override: '%s' (last offset %d)\n",
1521 0 : command, (int)(lastwarning-command));
1522 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1523 : }
1524 5 : trace4((qh, qh->ferr, 4093, "qh_initflags: option flags initialized\n"));
1525 : /* set derived values in qh_initqhull_globals */
1526 5 : } /* initflags */
1527 :
1528 :
1529 : /*-<a href="qh-globa_r.htm#TOC"
1530 : >-------------------------------</a><a name="initqhull_buffers">-</a>
1531 :
1532 : qh_initqhull_buffers(qh)
1533 : initialize global memory buffers
1534 :
1535 : notes:
1536 : must match qh_freebuffers()
1537 : */
1538 4 : void qh_initqhull_buffers(qhT *qh) {
1539 : int k;
1540 :
1541 4 : qh->TEMPsize= (qh->qhmem.LASTsize - (int)sizeof(setT))/SETelemsize;
1542 4 : if (qh->TEMPsize <= 0 || qh->TEMPsize > qh->qhmem.LASTsize)
1543 0 : qh->TEMPsize= 8; /* e.g., if qh_NOmem */
1544 4 : qh->other_points= qh_setnew(qh, qh->TEMPsize);
1545 4 : qh->del_vertices= qh_setnew(qh, qh->TEMPsize);
1546 4 : qh->coplanarfacetset= qh_setnew(qh, qh->TEMPsize);
1547 4 : qh->NEARzero= (realT *)qh_memalloc(qh, qh->hull_dim * (int)sizeof(realT));
1548 4 : qh->lower_threshold= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
1549 4 : qh->upper_threshold= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
1550 4 : qh->lower_bound= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
1551 4 : qh->upper_bound= (realT *)qh_memalloc(qh, (qh->input_dim+1) * (int)sizeof(realT));
1552 16 : for (k=qh->input_dim+1; k--; ) { /* duplicated in qh_initqhull_buffers and qh_clear_outputflags */
1553 12 : qh->lower_threshold[k]= -REALmax;
1554 12 : qh->upper_threshold[k]= REALmax;
1555 12 : qh->lower_bound[k]= -REALmax;
1556 12 : qh->upper_bound[k]= REALmax;
1557 : }
1558 4 : qh->gm_matrix= (coordT *)qh_memalloc(qh, (qh->hull_dim+1) * qh->hull_dim * (int)sizeof(coordT));
1559 4 : qh->gm_row= (coordT **)qh_memalloc(qh, (qh->hull_dim+1) * (int)sizeof(coordT *));
1560 4 : } /* initqhull_buffers */
1561 :
1562 : /*-<a href="qh-globa_r.htm#TOC"
1563 : >-------------------------------</a><a name="initqhull_globals">-</a>
1564 :
1565 : qh_initqhull_globals(qh, points, numpoints, dim, ismalloc )
1566 : initialize globals
1567 : if ismalloc
1568 : points were malloc'd and qhull should free at end
1569 :
1570 : returns:
1571 : sets qh.first_point, num_points, input_dim, hull_dim and others
1572 : seeds random number generator (seed=1 if tracing)
1573 : modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
1574 : adjust user flags as needed
1575 : also checks DIM3 dependencies and constants
1576 :
1577 : notes:
1578 : do not use qh_point() since an input transformation may move them elsewhere
1579 : qh_initqhull_start() sets default values for non-zero globals
1580 : consider duplicate error checks in qh_readpoints. It is called before qh_initqhull_globals
1581 :
1582 : design:
1583 : initialize points array from input arguments
1584 : test for qh.ZEROcentrum
1585 : (i.e., use opposite vertex instead of cetrum for convexity testing)
1586 : initialize qh.CENTERtype, qh.normal_size,
1587 : qh.center_size, qh.TRACEpoint/level,
1588 : initialize and test random numbers
1589 : qh_initqhull_outputflags() -- adjust and test output flags
1590 : */
1591 5 : void qh_initqhull_globals(qhT *qh, coordT *points, int numpoints, int dim, boolT ismalloc) {
1592 5 : int seed, pointsneeded, extra= 0, i, randi, k;
1593 : realT randr;
1594 : realT factorial;
1595 :
1596 : time_t timedata;
1597 :
1598 5 : trace0((qh, qh->ferr, 13, "qh_initqhull_globals: for %s | %s\n", qh->rbox_command,
1599 : qh->qhull_command));
1600 5 : if (numpoints < 1 || numpoints > qh_POINTSmax) {
1601 0 : qh_fprintf(qh, qh->ferr, 6412, "qhull input error (qh_initqhull_globals): expecting between 1 and %d points. Got %d %d-d points\n",
1602 : qh_POINTSmax, numpoints, dim);
1603 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1604 : /* same error message in qh_readpoints */
1605 : }
1606 5 : qh->POINTSmalloc= ismalloc;
1607 5 : qh->first_point= points;
1608 5 : qh->num_points= numpoints;
1609 5 : qh->hull_dim= qh->input_dim= dim;
1610 5 : if (!qh->NOpremerge && !qh->MERGEexact && !qh->PREmerge && qh->JOGGLEmax > REALmax/2) {
1611 5 : qh->MERGING= True;
1612 5 : if (qh->hull_dim <= 4) {
1613 5 : qh->PREmerge= True;
1614 5 : qh_option(qh, "_pre-merge", NULL, NULL);
1615 : }else {
1616 0 : qh->MERGEexact= True;
1617 0 : qh_option(qh, "Qxact-merge", NULL, NULL);
1618 : }
1619 0 : }else if (qh->MERGEexact)
1620 0 : qh->MERGING= True;
1621 5 : if (qh->NOpremerge && (qh->MERGEexact || qh->PREmerge))
1622 0 : qh_fprintf(qh, qh->ferr, 7095, "qhull option warning: 'Q0-no-premerge' ignored due to exact merge ('Qx') or pre-merge ('C-n' or 'A-n')\n");
1623 5 : if (!qh->NOpremerge && qh->JOGGLEmax > REALmax/2) {
1624 : #ifdef qh_NOmerge
1625 : qh->JOGGLEmax= 0.0;
1626 : #endif
1627 : }
1628 5 : if (qh->TRIangulate && qh->JOGGLEmax < REALmax/2 && !qh->PREmerge && !qh->POSTmerge && qh->PRINTprecision)
1629 0 : qh_fprintf(qh, qh->ferr, 7038, "qhull option warning: joggle ('QJ') produces simplicial output (i.e., triangles in 2-D). Unless merging is requested, option 'Qt' has no effect\n");
1630 5 : if (qh->JOGGLEmax < REALmax/2 && qh->DELAUNAY && !qh->SCALEinput && !qh->SCALElast) {
1631 0 : qh->SCALElast= True;
1632 0 : qh_option(qh, "Qbbound-last-qj", NULL, NULL);
1633 : }
1634 5 : if (qh->MERGING && !qh->POSTmerge && qh->premerge_cos > REALmax/2
1635 5 : && qh->premerge_centrum == 0.0) {
1636 5 : qh->ZEROcentrum= True;
1637 5 : qh->ZEROall_ok= True;
1638 5 : qh_option(qh, "_zero-centrum", NULL, NULL);
1639 : }
1640 : if (qh->JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh->PRINTprecision)
1641 : qh_fprintf(qh, qh->ferr, 7039, "qhull warning: real epsilon, %2.2g, is probably too large for joggle('QJn')\nRecompile with double precision reals(see user_r.h).\n",
1642 : REALepsilon);
1643 : #ifdef qh_NOmerge
1644 : if (qh->MERGING) {
1645 : qh_fprintf(qh, qh->ferr, 6045, "qhull option error: merging not installed (qh_NOmerge) for 'Qx', 'Cn' or 'An')\n");
1646 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1647 : }
1648 : #endif
1649 5 : if (qh->DELAUNAY && qh->KEEPcoplanar && !qh->KEEPinside) {
1650 5 : qh->KEEPinside= True;
1651 5 : qh_option(qh, "Qinterior-keep", NULL, NULL);
1652 : }
1653 5 : if (qh->VORONOI && !qh->DELAUNAY) {
1654 0 : qh_fprintf(qh, qh->ferr, 6038, "qhull internal error (qh_initqhull_globals): if qh.VORONOI is set, qh.DELAUNAY must be set. Qhull constructs the Delaunay triangulation in order to compute the Voronoi diagram\n");
1655 0 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
1656 : }
1657 5 : if (qh->DELAUNAY && qh->HALFspace) {
1658 0 : qh_fprintf(qh, qh->ferr, 6046, "qhull option error: can not use Delaunay('d') or Voronoi('v') with halfspace intersection('H')\n");
1659 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1660 : /* same error message in qh_readpoints */
1661 : }
1662 5 : if (!qh->DELAUNAY && (qh->UPPERdelaunay || qh->ATinfinity)) {
1663 0 : qh_fprintf(qh, qh->ferr, 6047, "qhull option error: use upper-Delaunay('Qu') or infinity-point('Qz') with Delaunay('d') or Voronoi('v')\n");
1664 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1665 : }
1666 5 : if (qh->UPPERdelaunay && qh->ATinfinity) {
1667 0 : qh_fprintf(qh, qh->ferr, 6048, "qhull option error: can not use infinity-point('Qz') with upper-Delaunay('Qu')\n");
1668 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1669 : }
1670 5 : if (qh->MERGEpinched && qh->ONLYgood) {
1671 0 : qh_fprintf(qh, qh->ferr, 6362, "qhull option error: can not use merge-pinched-vertices ('Q14') with good-facets-only ('Qg')\n");
1672 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1673 : }
1674 5 : if (qh->MERGEpinched && qh->hull_dim == 2) {
1675 0 : trace2((qh, qh->ferr, 2108, "qh_initqhull_globals: disable qh.MERGEpinched for 2-d. It has no effect"))
1676 0 : qh->MERGEpinched= False;
1677 : }
1678 5 : if (qh->SCALElast && !qh->DELAUNAY && qh->PRINTprecision)
1679 0 : qh_fprintf(qh, qh->ferr, 7040, "qhull option warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
1680 5 : qh->DOcheckmax= (!qh->SKIPcheckmax && (qh->MERGING || qh->APPROXhull));
1681 5 : qh->KEEPnearinside= (qh->DOcheckmax && !(qh->KEEPinside && qh->KEEPcoplanar)
1682 10 : && !qh->NOnearinside);
1683 5 : if (qh->MERGING)
1684 5 : qh->CENTERtype= qh_AScentrum;
1685 0 : else if (qh->VORONOI)
1686 0 : qh->CENTERtype= qh_ASvoronoi;
1687 5 : if (qh->TESTvneighbors && !qh->MERGING) {
1688 0 : qh_fprintf(qh, qh->ferr, 6049, "qhull option error: test vertex neighbors('Qv') needs a merge option\n");
1689 0 : qh_errexit(qh, qh_ERRinput, NULL ,NULL);
1690 : }
1691 5 : if (qh->PROJECTinput || (qh->DELAUNAY && qh->PROJECTdelaunay)) {
1692 5 : qh->hull_dim -= qh->PROJECTinput;
1693 5 : if (qh->DELAUNAY) {
1694 5 : qh->hull_dim++;
1695 5 : if (qh->ATinfinity)
1696 5 : extra= 1;
1697 : }
1698 : }
1699 5 : if (qh->hull_dim <= 1) {
1700 0 : qh_fprintf(qh, qh->ferr, 6050, "qhull error: dimension %d must be > 1\n", qh->hull_dim);
1701 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1702 : }
1703 10 : for (k=2, factorial=1.0; k < qh->hull_dim; k++)
1704 5 : factorial *= k;
1705 5 : qh->AREAfactor= 1.0 / factorial;
1706 5 : trace2((qh, qh->ferr, 2005, "qh_initqhull_globals: initialize globals. input_dim %d, numpoints %d, malloc? %d, projected %d to hull_dim %d\n",
1707 : qh->input_dim, numpoints, ismalloc, qh->PROJECTinput, qh->hull_dim));
1708 5 : qh->normal_size= qh->hull_dim * (int)sizeof(coordT);
1709 5 : qh->center_size= qh->normal_size - (int)sizeof(coordT);
1710 5 : pointsneeded= qh->hull_dim+1;
1711 5 : if (qh->hull_dim > qh_DIMmergeVertex) {
1712 0 : qh->MERGEvertices= False;
1713 0 : qh_option(qh, "Q3-no-merge-vertices-dim-high", NULL, NULL);
1714 : }
1715 5 : if (qh->GOODpoint)
1716 0 : pointsneeded++;
1717 : #ifdef qh_NOtrace
1718 : if (qh->IStracing || qh->TRACEmerge || qh->TRACEpoint != qh_IDnone || qh->TRACEdist < REALmax/2) {
1719 : qh_fprintf(qh, qh->ferr, 6051, "qhull option error: tracing is not installed (qh_NOtrace in user_r.h). Trace options 'Tn', 'TMn', 'TPn' and 'TWn' mostly removed. Continue with 'Qw' (allow warning)\n");
1720 : if (!qh->ALLOWwarning)
1721 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1722 : }
1723 : #endif
1724 5 : if (qh->RERUN > 1) {
1725 0 : qh->TRACElastrun= qh->IStracing; /* qh_build_withrestart duplicates next conditional */
1726 0 : if (qh->IStracing && qh->IStracing != -1) {
1727 0 : qh_fprintf(qh, qh->ferr, 8162, "qh_initqhull_globals: trace last of TR%d runs at level %d\n", qh->RERUN, qh->IStracing);
1728 0 : qh->IStracing= 0;
1729 : }
1730 5 : }else if (qh->TRACEpoint != qh_IDnone || qh->TRACEdist < REALmax/2 || qh->TRACEmerge) {
1731 0 : qh->TRACElevel= (qh->IStracing ? qh->IStracing : 3);
1732 0 : qh->IStracing= 0;
1733 : }
1734 5 : if (qh->ROTATErandom == 0 || qh->ROTATErandom == -1) {
1735 : /* coverity[store_truncates_time_t] */
1736 0 : seed= (int)time(&timedata);
1737 0 : if (qh->ROTATErandom == -1) {
1738 0 : seed= -seed;
1739 0 : qh_option(qh, "QRandom-seed", &seed, NULL );
1740 : }else
1741 0 : qh_option(qh, "QRotate-random", &seed, NULL);
1742 0 : qh->ROTATErandom= seed;
1743 : }
1744 5 : seed= qh->ROTATErandom;
1745 5 : if (seed == INT_MIN) /* default value */
1746 5 : seed= 1;
1747 0 : else if (seed < 0)
1748 0 : seed= -seed;
1749 5 : qh_RANDOMseed_(qh, seed);
1750 5 : randr= 0.0;
1751 5005 : for (i=1000; i--; ) {
1752 5000 : randi= qh_RANDOMint;
1753 5000 : randr += randi;
1754 5000 : if (randi > qh_RANDOMmax) {
1755 0 : qh_fprintf(qh, qh->ferr, 8036, "\
1756 : qhull configuration error (qh_RANDOMmax in user_r.h): random integer %d > qh_RANDOMmax (%.8g)\n",
1757 : randi, qh_RANDOMmax);
1758 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1759 : }
1760 : }
1761 5 : qh_RANDOMseed_(qh, seed);
1762 5 : randr= randr/1000;
1763 5 : if (randr < qh_RANDOMmax * 0.1
1764 5 : || randr > qh_RANDOMmax * 0.9)
1765 0 : qh_fprintf(qh, qh->ferr, 8037, "\
1766 : qhull configuration warning (qh_RANDOMmax in user_r.h): average of 1000 random integers (%.2g) is much different than expected (%.2g). Is qh_RANDOMmax (%.2g) wrong?\n",
1767 : randr, qh_RANDOMmax * 0.5, qh_RANDOMmax);
1768 5 : qh->RANDOMa= 2.0 * qh->RANDOMfactor/qh_RANDOMmax;
1769 5 : qh->RANDOMb= 1.0 - qh->RANDOMfactor;
1770 : if (qh_HASHfactor < 1.1) {
1771 : qh_fprintf(qh, qh->ferr, 6052, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1. Qhull uses linear hash probing\n",
1772 : qh_HASHfactor);
1773 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
1774 : }
1775 5 : if (numpoints+extra < pointsneeded) {
1776 1 : qh_fprintf(qh, qh->ferr, 6214, "qhull input error: not enough points(%d) to construct initial simplex (need %d)\n",
1777 : numpoints, pointsneeded);
1778 1 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1779 : }
1780 4 : qh_initqhull_outputflags(qh);
1781 4 : } /* initqhull_globals */
1782 :
1783 : /*-<a href="qh-globa_r.htm#TOC"
1784 : >-------------------------------</a><a name="initqhull_mem">-</a>
1785 :
1786 : qh_initqhull_mem(qh )
1787 : initialize mem_r.c for qhull
1788 : qh.hull_dim and qh.normal_size determine some of the allocation sizes
1789 : if qh.MERGING,
1790 : includes ridgeT
1791 : calls qh_user_memsizes (user_r.c) to add up to 10 additional sizes for quick allocation
1792 : (see numsizes below)
1793 :
1794 : returns:
1795 : mem_r.c already for qh_memalloc/qh_memfree (errors if called beforehand)
1796 :
1797 : notes:
1798 : qh_produceoutput() prints memsizes
1799 :
1800 : */
1801 4 : void qh_initqhull_mem(qhT *qh) {
1802 : int numsizes;
1803 : int i;
1804 :
1805 4 : numsizes= 8+10;
1806 4 : qh_meminitbuffers(qh, qh->IStracing, qh_MEMalign, numsizes,
1807 : qh_MEMbufsize, qh_MEMinitbuf);
1808 4 : qh_memsize(qh, (int)sizeof(vertexT));
1809 4 : if (qh->MERGING) {
1810 4 : qh_memsize(qh, (int)sizeof(ridgeT));
1811 4 : qh_memsize(qh, (int)sizeof(mergeT));
1812 : }
1813 4 : qh_memsize(qh, (int)sizeof(facetT));
1814 4 : i= (int)sizeof(setT) + (qh->hull_dim - 1) * SETelemsize; /* ridge.vertices */
1815 4 : qh_memsize(qh, i);
1816 4 : qh_memsize(qh, qh->normal_size); /* normal */
1817 4 : i += SETelemsize; /* facet.vertices, .ridges, .neighbors */
1818 4 : qh_memsize(qh, i);
1819 4 : qh_user_memsizes(qh);
1820 4 : qh_memsetup(qh);
1821 4 : } /* initqhull_mem */
1822 :
1823 : /*-<a href="qh-globa_r.htm#TOC"
1824 : >-------------------------------</a><a name="initqhull_outputflags">-</a>
1825 :
1826 : qh_initqhull_outputflags
1827 : initialize flags concerned with output
1828 :
1829 : returns:
1830 : adjust user flags as needed
1831 :
1832 : see:
1833 : qh_clear_outputflags() resets the flags
1834 :
1835 : design:
1836 : test for qh.PRINTgood (i.e., only print 'good' facets)
1837 : check for conflicting print output options
1838 : */
1839 4 : void qh_initqhull_outputflags(qhT *qh) {
1840 4 : boolT printgeom= False, printmath= False, printcoplanar= False;
1841 : int i;
1842 :
1843 4 : trace3((qh, qh->ferr, 3024, "qh_initqhull_outputflags: %s\n", qh->qhull_command));
1844 4 : if (!(qh->PRINTgood || qh->PRINTneighbors)) {
1845 4 : if (qh->DELAUNAY || qh->KEEParea || qh->KEEPminArea < REALmax/2 || qh->KEEPmerge
1846 0 : || (!qh->ONLYgood && (qh->GOODvertex || qh->GOODpoint))) {
1847 4 : qh->PRINTgood= True;
1848 4 : qh_option(qh, "Pgood", NULL, NULL);
1849 : }
1850 : }
1851 4 : if (qh->PRINTtransparent) {
1852 0 : if (qh->hull_dim != 4 || !qh->DELAUNAY || qh->VORONOI || qh->DROPdim >= 0) {
1853 0 : qh_fprintf(qh, qh->ferr, 6215, "qhull option error: transparent Delaunay('Gt') needs 3-d Delaunay('d') w/o 'GDn'\n");
1854 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1855 : }
1856 0 : qh->DROPdim= 3;
1857 0 : qh->PRINTridges= True;
1858 : }
1859 120 : for (i=qh_PRINTEND; i--; ) {
1860 116 : if (qh->PRINTout[i] == qh_PRINTgeom)
1861 0 : printgeom= True;
1862 116 : else if (qh->PRINTout[i] == qh_PRINTmathematica || qh->PRINTout[i] == qh_PRINTmaple)
1863 0 : printmath= True;
1864 116 : else if (qh->PRINTout[i] == qh_PRINTcoplanars)
1865 0 : printcoplanar= True;
1866 116 : else if (qh->PRINTout[i] == qh_PRINTpointnearest)
1867 0 : printcoplanar= True;
1868 116 : else if (qh->PRINTout[i] == qh_PRINTpointintersect && !qh->HALFspace) {
1869 0 : qh_fprintf(qh, qh->ferr, 6053, "qhull option error: option 'Fp' is only used for \nhalfspace intersection('Hn,n,n').\n");
1870 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1871 116 : }else if (qh->PRINTout[i] == qh_PRINTtriangles && (qh->HALFspace || qh->VORONOI)) {
1872 0 : qh_fprintf(qh, qh->ferr, 6054, "qhull option error: option 'Ft' is not available for Voronoi vertices ('v') or halfspace intersection ('H')\n");
1873 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1874 116 : }else if (qh->PRINTout[i] == qh_PRINTcentrums && qh->VORONOI) {
1875 0 : qh_fprintf(qh, qh->ferr, 6055, "qhull option error: option 'FC' is not available for Voronoi vertices('v')\n");
1876 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1877 116 : }else if (qh->PRINTout[i] == qh_PRINTvertices) {
1878 0 : if (qh->VORONOI)
1879 0 : qh_option(qh, "Fvoronoi", NULL, NULL);
1880 : else
1881 0 : qh_option(qh, "Fvertices", NULL, NULL);
1882 : }
1883 : }
1884 4 : if (printcoplanar && qh->DELAUNAY && qh->JOGGLEmax < REALmax/2) {
1885 0 : if (qh->PRINTprecision)
1886 0 : qh_fprintf(qh, qh->ferr, 7041, "qhull option warning: 'QJ' (joggle) will usually prevent coincident input sites for options 'Fc' and 'FP'\n");
1887 : }
1888 4 : if (printmath && (qh->hull_dim > 3 || qh->VORONOI)) {
1889 0 : qh_fprintf(qh, qh->ferr, 6056, "qhull option error: Mathematica and Maple output is only available for 2-d and 3-d convex hulls and 2-d Delaunay triangulations\n");
1890 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1891 : }
1892 4 : if (printgeom) {
1893 0 : if (qh->hull_dim > 4) {
1894 0 : qh_fprintf(qh, qh->ferr, 6057, "qhull option error: Geomview output is only available for 2-d, 3-d and 4-d\n");
1895 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1896 : }
1897 0 : if (qh->PRINTnoplanes && !(qh->PRINTcoplanar + qh->PRINTcentrums
1898 0 : + qh->PRINTdots + qh->PRINTspheres + qh->DOintersections + qh->PRINTridges)) {
1899 0 : qh_fprintf(qh, qh->ferr, 6058, "qhull option error: no output specified for Geomview\n");
1900 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1901 : }
1902 0 : if (qh->VORONOI && (qh->hull_dim > 3 || qh->DROPdim >= 0)) {
1903 0 : qh_fprintf(qh, qh->ferr, 6059, "qhull option error: Geomview output for Voronoi diagrams only for 2-d\n");
1904 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
1905 : }
1906 : /* can not warn about furthest-site Geomview output: no lower_threshold */
1907 0 : if (qh->hull_dim == 4 && qh->DROPdim == -1 &&
1908 0 : (qh->PRINTcoplanar || qh->PRINTspheres || qh->PRINTcentrums)) {
1909 0 : qh_fprintf(qh, qh->ferr, 7042, "qhull option warning: coplanars, vertices, and centrums output not available for 4-d output(ignored). Could use 'GDn' instead.\n");
1910 0 : qh->PRINTcoplanar= qh->PRINTspheres= qh->PRINTcentrums= False;
1911 : }
1912 : }
1913 4 : if (!qh->KEEPcoplanar && !qh->KEEPinside && !qh->ONLYgood) {
1914 0 : if ((qh->PRINTcoplanar && qh->PRINTspheres) || printcoplanar) {
1915 0 : if (qh->QHULLfinished) {
1916 0 : qh_fprintf(qh, qh->ferr, 7072, "qhull output warning: ignoring coplanar points, option 'Qc' was not set for the first run of qhull.\n");
1917 : }else {
1918 0 : qh->KEEPcoplanar= True;
1919 0 : qh_option(qh, "Qcoplanar", NULL, NULL);
1920 : }
1921 : }
1922 : }
1923 4 : qh->PRINTdim= qh->hull_dim;
1924 4 : if (qh->DROPdim >=0) { /* after Geomview checks */
1925 0 : if (qh->DROPdim < qh->hull_dim) {
1926 0 : qh->PRINTdim--;
1927 0 : if (!printgeom || qh->hull_dim < 3)
1928 0 : qh_fprintf(qh, qh->ferr, 7043, "qhull option warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh->DROPdim);
1929 : }else
1930 0 : qh->DROPdim= -1;
1931 4 : }else if (qh->VORONOI) {
1932 0 : qh->DROPdim= qh->hull_dim-1;
1933 0 : qh->PRINTdim= qh->hull_dim-1;
1934 : }
1935 4 : } /* qh_initqhull_outputflags */
1936 :
1937 : /*-<a href="qh-globa_r.htm#TOC"
1938 : >-------------------------------</a><a name="initqhull_start">-</a>
1939 :
1940 : qh_initqhull_start(qh, infile, outfile, errfile )
1941 : allocate memory if needed and call qh_initqhull_start2()
1942 : */
1943 5 : void qh_initqhull_start(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile) {
1944 :
1945 5 : qh_initstatistics(qh);
1946 5 : qh_initqhull_start2(qh, infile, outfile, errfile);
1947 5 : } /* initqhull_start */
1948 :
1949 : /*-<a href="qh-globa_r.htm#TOC"
1950 : >-------------------------------</a><a name="initqhull_start2">-</a>
1951 :
1952 : qh_initqhull_start2(qh, infile, outfile, errfile )
1953 : start initialization of qhull
1954 : initialize statistics, stdio, default values for global variables
1955 : assumes qh is allocated
1956 : notes:
1957 : report errors elsewhere, error handling and g_qhull_output [Qhull.cpp, QhullQh()] not in initialized
1958 : see:
1959 : qh_maxmin() determines the precision constants
1960 : qh_freeqhull()
1961 : */
1962 5 : void qh_initqhull_start2(qhT *qh, FILE *infile, FILE *outfile, FILE *errfile) {
1963 : time_t timedata;
1964 : int seed;
1965 :
1966 5 : qh_CPUclock; /* start the clock(for qh_clock). One-shot. */
1967 : /* memset is the same in qh_freeqhull() and qh_initqhull_start2() */
1968 5 : memset((char *)qh, 0, sizeof(qhT)-sizeof(qhmemT)-sizeof(qhstatT)); /* every field is 0, FALSE, NULL */
1969 5 : qh->NOerrexit= True;
1970 5 : qh->DROPdim= -1;
1971 5 : qh->ferr= errfile;
1972 5 : qh->fin= infile;
1973 5 : qh->fout= outfile;
1974 5 : qh->furthest_id= qh_IDunknown;
1975 : #ifndef qh_NOmerge
1976 5 : qh->JOGGLEmax= REALmax;
1977 : #else
1978 : qh->JOGGLEmax= 0.0; /* Joggle ('QJ') if qh_NOmerge */
1979 : #endif
1980 5 : qh->KEEPminArea= REALmax;
1981 5 : qh->last_low= REALmax;
1982 5 : qh->last_high= REALmax;
1983 5 : qh->last_newhigh= REALmax;
1984 5 : qh->last_random= 1; /* reentrant only */
1985 5 : qh->lastcpu= 0.0;
1986 5 : qh->max_outside= 0.0;
1987 5 : qh->max_vertex= 0.0;
1988 5 : qh->MAXabs_coord= 0.0;
1989 5 : qh->MAXsumcoord= 0.0;
1990 5 : qh->MAXwidth= -REALmax;
1991 5 : qh->MERGEindependent= True;
1992 5 : qh->MINdenom_1= fmax_(1.0/REALmax, REALmin); /* used by qh_scalepoints */
1993 5 : qh->MINoutside= 0.0;
1994 5 : qh->MINvisible= REALmax;
1995 5 : qh->MAXcoplanar= REALmax;
1996 5 : qh->outside_err= REALmax;
1997 5 : qh->premerge_centrum= 0.0;
1998 5 : qh->premerge_cos= REALmax;
1999 5 : qh->PRINTprecision= True;
2000 5 : qh->PRINTradius= 0.0;
2001 5 : qh->postmerge_cos= REALmax;
2002 5 : qh->postmerge_centrum= 0.0;
2003 5 : qh->ROTATErandom= INT_MIN;
2004 5 : qh->MERGEvertices= True;
2005 5 : qh->totarea= 0.0;
2006 5 : qh->totvol= 0.0;
2007 5 : qh->TRACEdist= REALmax;
2008 5 : qh->TRACEpoint= qh_IDnone; /* recompile to trace a point, or use 'TPn' */
2009 5 : qh->tracefacet_id= UINT_MAX; /* recompile to trace a facet, set to UINT_MAX when done, see userprintf_r.c/qh_fprintf */
2010 5 : qh->traceridge_id= UINT_MAX; /* recompile to trace a ridge, set to UINT_MAX when done, see userprintf_r.c/qh_fprintf */
2011 5 : qh->tracevertex_id= UINT_MAX; /* recompile to trace a vertex, set to UINT_MAX when done, see userprintf_r.c/qh_fprintf */
2012 : /* coverity[store_truncates_time_t] */
2013 5 : seed= (int)time(&timedata);
2014 5 : qh_RANDOMseed_(qh, seed);
2015 5 : qh->run_id= qh_RANDOMint;
2016 5 : if(!qh->run_id)
2017 0 : qh->run_id++; /* guarantee non-zero */
2018 5 : qh_option(qh, "run-id", &qh->run_id, NULL);
2019 5 : strcat(qh->qhull, "qhull");
2020 5 : } /* initqhull_start2 */
2021 :
2022 : /*-<a href="qh-globa_r.htm#TOC"
2023 : >-------------------------------</a><a name="initthresholds">-</a>
2024 :
2025 : qh_initthresholds(qh, commandString )
2026 : set thresholds for printing and scaling from commandString
2027 :
2028 : returns:
2029 : sets qh.GOODthreshold or qh.SPLITthreshold if 'Pd0D1' used
2030 :
2031 : see:
2032 : qh_initflags(), 'Qbk' 'QBk' 'Pdk' and 'PDk'
2033 : qh_inthresholds()
2034 :
2035 : design:
2036 : for each 'Pdn' or 'PDn' option
2037 : check syntax
2038 : set qh.lower_threshold or qh.upper_threshold
2039 : set qh.GOODthreshold if an unbounded threshold is used
2040 : set qh.SPLITthreshold if a bounded threshold is used
2041 : */
2042 4 : void qh_initthresholds(qhT *qh, char *command) {
2043 : realT value;
2044 : int idx, maxdim, k;
2045 4 : char *s= command; /* non-const due to strtol */
2046 4 : char *lastoption, *lastwarning= NULL;
2047 : char key;
2048 :
2049 4 : maxdim= qh->input_dim;
2050 4 : if (qh->DELAUNAY && (qh->PROJECTdelaunay || qh->PROJECTinput))
2051 4 : maxdim++;
2052 28 : while (*s) {
2053 24 : if (*s == '-')
2054 0 : s++;
2055 24 : if (*s == 'P') {
2056 0 : lastoption= s++;
2057 0 : while (*s && !isspace(key= *s++)) {
2058 0 : if (key == 'd' || key == 'D') {
2059 0 : if (!isdigit(*s)) {
2060 0 : qh_fprintf(qh, qh->ferr, 7044, "qhull option warning: no dimension given for Print option 'P%c' at: %s. Ignored\n",
2061 : key, s-1);
2062 0 : lastwarning= lastoption;
2063 0 : continue;
2064 : }
2065 0 : idx= qh_strtol(s, &s);
2066 0 : if (idx >= qh->hull_dim) {
2067 0 : qh_fprintf(qh, qh->ferr, 7045, "qhull option warning: dimension %d for Print option 'P%c' is >= %d. Ignored\n",
2068 : idx, key, qh->hull_dim);
2069 0 : lastwarning= lastoption;
2070 0 : continue;
2071 : }
2072 0 : if (*s == ':') {
2073 0 : s++;
2074 0 : value= qh_strtod(s, &s);
2075 0 : if (fabs((double)value) > 1.0) {
2076 0 : qh_fprintf(qh, qh->ferr, 7046, "qhull option warning: value %2.4g for Print option 'P%c' is > +1 or < -1. Ignored\n",
2077 : value, key);
2078 0 : lastwarning= lastoption;
2079 0 : continue;
2080 : }
2081 : }else
2082 0 : value= 0.0;
2083 0 : if (key == 'd')
2084 0 : qh->lower_threshold[idx]= value;
2085 : else
2086 0 : qh->upper_threshold[idx]= value;
2087 : }
2088 : }
2089 24 : }else if (*s == 'Q') {
2090 16 : lastoption= s++;
2091 32 : while (*s && !isspace(key= *s++)) {
2092 16 : if (key == 'b' && *s == 'B') {
2093 0 : s++;
2094 0 : for (k=maxdim; k--; ) {
2095 0 : qh->lower_bound[k]= -qh_DEFAULTbox;
2096 0 : qh->upper_bound[k]= qh_DEFAULTbox;
2097 : }
2098 16 : }else if (key == 'b' && *s == 'b')
2099 4 : s++;
2100 12 : else if (key == 'b' || key == 'B') {
2101 0 : if (!isdigit(*s)) {
2102 0 : qh_fprintf(qh, qh->ferr, 7047, "qhull option warning: no dimension given for Qhull option 'Q%c'\n",
2103 : key);
2104 0 : lastwarning= lastoption;
2105 0 : continue;
2106 : }
2107 0 : idx= qh_strtol(s, &s);
2108 0 : if (idx >= maxdim) {
2109 0 : qh_fprintf(qh, qh->ferr, 7048, "qhull option warning: dimension %d for Qhull option 'Q%c' is >= %d. Ignored\n",
2110 : idx, key, maxdim);
2111 0 : lastwarning= lastoption;
2112 0 : continue;
2113 : }
2114 0 : if (*s == ':') {
2115 0 : s++;
2116 0 : value= qh_strtod(s, &s);
2117 0 : }else if (key == 'b')
2118 0 : value= -qh_DEFAULTbox;
2119 : else
2120 0 : value= qh_DEFAULTbox;
2121 0 : if (key == 'b')
2122 0 : qh->lower_bound[idx]= value;
2123 : else
2124 0 : qh->upper_bound[idx]= value;
2125 : }
2126 : }
2127 : }else {
2128 32 : while (*s && !isspace(*s))
2129 24 : s++;
2130 : }
2131 32 : while (isspace(*s))
2132 8 : s++;
2133 : }
2134 16 : for (k=qh->hull_dim; k--; ) {
2135 12 : if (qh->lower_threshold[k] > -REALmax/2) {
2136 0 : qh->GOODthreshold= True;
2137 0 : if (qh->upper_threshold[k] < REALmax/2) {
2138 0 : qh->SPLITthresholds= True;
2139 0 : qh->GOODthreshold= False;
2140 0 : break;
2141 : }
2142 12 : }else if (qh->upper_threshold[k] < REALmax/2)
2143 0 : qh->GOODthreshold= True;
2144 : }
2145 4 : if (lastwarning && !qh->ALLOWwarning) {
2146 0 : qh_fprintf(qh, qh->ferr, 6036, "qhull option error: see previous warnings, use 'Qw' to override: '%s' (last offset %d)\n",
2147 0 : command, (int)(lastwarning-command));
2148 0 : qh_errexit(qh, qh_ERRinput, NULL, NULL);
2149 : }
2150 4 : } /* initthresholds */
2151 :
2152 : /*-<a href="qh-globa_r.htm#TOC"
2153 : >-------------------------------</a><a name="lib_check">-</a>
2154 :
2155 : qh_lib_check( qhullLibraryType, qhTsize, vertexTsize, ridgeTsize, facetTsize, setTsize, qhmemTsize )
2156 : Report error if library does not agree with caller
2157 :
2158 : notes:
2159 : NOerrors -- qh_lib_check can not call qh_errexit()
2160 : */
2161 5 : void qh_lib_check(int qhullLibraryType, int qhTsize, int vertexTsize, int ridgeTsize, int facetTsize, int setTsize, int qhmemTsize) {
2162 5 : int last_errcode= qh_ERRnone;
2163 :
2164 : #if defined(_MSC_VER) && defined(_DEBUG) && defined(QHULL_CRTDBG) /* user_r.h */
2165 : /*_CrtSetBreakAlloc(744);*/ /* Break at memalloc {744}, or 'watch' _crtBreakAlloc */
2166 : _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_DELAY_FREE_MEM_DF | _CRTDBG_LEAK_CHECK_DF | _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) );
2167 : _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
2168 : _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR );
2169 : _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
2170 : _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
2171 : _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG );
2172 : _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
2173 : #endif
2174 :
2175 5 : if (qhullLibraryType==QHULL_NON_REENTRANT) { /* 0 */
2176 0 : qh_fprintf_stderr(6257, "qh_lib_check: Incorrect qhull library called. Caller uses non-reentrant Qhull with a static qhT. Qhull library is reentrant.\n");
2177 0 : last_errcode= 6257;
2178 5 : }else if (qhullLibraryType==QHULL_QH_POINTER) { /* 1 */
2179 0 : qh_fprintf_stderr(6258, "qh_lib_check: Incorrect qhull library called. Caller uses non-reentrant Qhull with a dynamic qhT via qh_QHpointer. Qhull library is reentrant.\n");
2180 0 : last_errcode= 6258;
2181 5 : }else if (qhullLibraryType != QHULL_REENTRANT) { /* 2 */
2182 0 : qh_fprintf_stderr(6262, "qh_lib_check: Expecting qhullLibraryType QHULL_NON_REENTRANT(0), QHULL_QH_POINTER(1), or QHULL_REENTRANT(2). Got %d\n", qhullLibraryType);
2183 0 : last_errcode= 6262;
2184 : }
2185 5 : if (qhTsize != (int)sizeof(qhT)) {
2186 0 : qh_fprintf_stderr(6249, "qh_lib_check: Incorrect qhull library called. Size of qhT for caller is %d, but for qhull library is %d.\n", qhTsize, (int)sizeof(qhT));
2187 0 : last_errcode= 6249;
2188 : }
2189 5 : if (vertexTsize != (int)sizeof(vertexT)) {
2190 0 : qh_fprintf_stderr(6250, "qh_lib_check: Incorrect qhull library called. Size of vertexT for caller is %d, but for qhull library is %d.\n", vertexTsize, (int)sizeof(vertexT));
2191 0 : last_errcode= 6250;
2192 : }
2193 5 : if (ridgeTsize != (int)sizeof(ridgeT)) {
2194 0 : qh_fprintf_stderr(6251, "qh_lib_check: Incorrect qhull library called. Size of ridgeT for caller is %d, but for qhull library is %d.\n", ridgeTsize, (int)sizeof(ridgeT));
2195 0 : last_errcode= 6251;
2196 : }
2197 5 : if (facetTsize != (int)sizeof(facetT)) {
2198 0 : qh_fprintf_stderr(6252, "qh_lib_check: Incorrect qhull library called. Size of facetT for caller is %d, but for qhull library is %d.\n", facetTsize, (int)sizeof(facetT));
2199 0 : last_errcode= 6252;
2200 : }
2201 5 : if (setTsize && setTsize != (int)sizeof(setT)) {
2202 0 : qh_fprintf_stderr(6253, "qh_lib_check: Incorrect qhull library called. Size of setT for caller is %d, but for qhull library is %d.\n", setTsize, (int)sizeof(setT));
2203 0 : last_errcode= 6253;
2204 : }
2205 5 : if (qhmemTsize && qhmemTsize != sizeof(qhmemT)) {
2206 0 : qh_fprintf_stderr(6254, "qh_lib_check: Incorrect qhull library called. Size of qhmemT for caller is %d, but for qhull library is %d.\n", qhmemTsize, (int)sizeof(qhmemT));
2207 0 : last_errcode= 6254;
2208 : }
2209 5 : if (last_errcode) {
2210 0 : qh_fprintf_stderr(6259, "qhull internal error (qh_lib_check): Cannot continue due to QH%d. '%s' is not reentrant (e.g., qhull.so) or out-of-date. Exit with %d\n",
2211 : last_errcode, qh_version2, last_errcode - 6200);
2212 0 : qh_exit(last_errcode - 6200); /* can not use qh_errexit(), must be less than 255 */
2213 : }
2214 5 : } /* lib_check */
2215 :
2216 : /*-<a href="qh-globa_r.htm#TOC"
2217 : >-------------------------------</a><a name="option">-</a>
2218 :
2219 : qh_option(qh, option, intVal, realVal )
2220 : add an option description to qh.qhull_options
2221 :
2222 : notes:
2223 : NOerrors -- qh_option can not call qh_errexit() [qh_initqhull_start2]
2224 : will be printed with statistics ('Ts') and errors
2225 : strlen(option) < 40
2226 : */
2227 79 : void qh_option(qhT *qh, const char *option, int *i, realT *r) {
2228 : char buf[200];
2229 : int buflen, remainder;
2230 :
2231 79 : if (strlen(option) > sizeof(buf)-30-30) {
2232 0 : qh_fprintf(qh, qh->ferr, 6408, "qhull internal error (qh_option): option (%d chars) has more than %d chars. May overflow temporary buffer. Option '%s'\n",
2233 0 : (int)strlen(option), (int)sizeof(buf)-30-30, option);
2234 0 : qh_errexit(qh, qh_ERRqhull, NULL, NULL);
2235 : }
2236 79 : sprintf(buf, " %s", option);
2237 79 : if (i)
2238 5 : sprintf(buf+strlen(buf), " %d", *i);
2239 79 : if (r)
2240 30 : sprintf(buf+strlen(buf), " %2.2g", *r);
2241 79 : buflen= (int)strlen(buf); /* WARN64 */
2242 79 : qh->qhull_optionlen += buflen;
2243 79 : remainder= (int)(sizeof(qh->qhull_options) - strlen(qh->qhull_options)) - 1; /* WARN64 */
2244 79 : maximize_(remainder, 0);
2245 79 : if (qh->qhull_optionlen >= qh_OPTIONline && remainder > 0) {
2246 15 : strncat(qh->qhull_options, "\n", (unsigned int)remainder);
2247 15 : --remainder;
2248 15 : qh->qhull_optionlen= buflen;
2249 : }
2250 79 : if (buflen > remainder) {
2251 0 : trace1((qh, qh->ferr, 1058, "qh_option: option would overflow qh.qhull_options. Truncated '%s'\n", buf));
2252 : }
2253 79 : strncat(qh->qhull_options, buf, (unsigned int)remainder);
2254 79 : } /* option */
2255 :
2256 : /*-<a href="qh-globa_r.htm#TOC"
2257 : >-------------------------------</a><a name="zero">-</a>
2258 :
2259 : qh_zero( qh, errfile )
2260 : Initialize and zero Qhull's memory for qh_new_qhull()
2261 :
2262 : notes:
2263 : Not needed in global_r.c because static variables are initialized to zero
2264 : */
2265 0 : void qh_zero(qhT *qh, FILE *errfile) {
2266 0 : memset((char *)qh, 0, sizeof(qhT)); /* every field is 0, FALSE, NULL */
2267 0 : qh->NOerrexit= True;
2268 0 : qh_meminit(qh, errfile);
2269 0 : } /* zero */
2270 :
|