PageRenderTime 31ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 0ms

/misc/nistmeshlab/meshlab/src/external/qhull-2003.1/src/global.c

https://github.com/lessandro/nbis
C | 1621 lines | 1328 code | 33 blank | 260 comment | 414 complexity | bfe3ed74deac8fa26dcfd78f082e649e MD5 | raw file
  1. /*<html><pre> -<a href="qh-globa.htm"
  2. >-------------------------------</a><a name="TOP">-</a>
  3. global.c
  4. initializes all the globals of the qhull application
  5. see README
  6. see qhull.h for qh.globals and function prototypes
  7. see qhull_a.h for internal functions
  8. copyright (c) 1993-2003, The Geometry Center
  9. */
  10. #include "qhull_a.h"
  11. /*========= qh definition (see qhull.h) =======================*/
  12. #if qh_QHpointer
  13. qhT *qh_qh= NULL; /* pointer to all global variables */
  14. #else
  15. qhT qh_qh; /* all global variables.
  16. Add "= {0}" if this causes a compiler error.
  17. Also qh_qhstat in stat.c and qhmem in mem.c. */
  18. #endif
  19. /*-<a href ="qh-globa.htm#TOC"
  20. >--------------------------------</a><a name="qh_version">-</a>
  21. qh_version
  22. version string by year and date
  23. the revision increases on code changes only
  24. notes:
  25. change date: Changes.txt, Announce.txt, README.txt,
  26. qhull.man, qhull.txt, qhull-news.html, Eudora signatures,
  27. change version: README.txt, qh-get.htm, File_id.diz, Makefile.txt
  28. change year: Copying.txt
  29. check download size
  30. recompile user_eg.c, rbox.c, qhull.c, qconvex.c, qdelaun.c qvoronoi.c, qhalf.c
  31. */
  32. char *qh_version = "2003.1 2003/12/30";
  33. /*-<a href="qh-globa.htm#TOC"
  34. >-------------------------------</a><a name="appendprint">-</a>
  35. qh_appendprint( printFormat )
  36. append printFormat to qh.PRINTout unless already defined
  37. */
  38. void qh_appendprint (qh_PRINT format) {
  39. int i;
  40. for (i=0; i < qh_PRINTEND; i++) {
  41. if (qh PRINTout[i] == format && format != qh_PRINTqhull)
  42. break;
  43. if (!qh PRINTout[i]) {
  44. qh PRINTout[i]= format;
  45. break;
  46. }
  47. }
  48. } /* appendprint */
  49. /*-<a href="qh-globa.htm#TOC"
  50. >-------------------------------</a><a name="checkflags">-</a>
  51. qh_checkflags( commandStr, hiddenFlags )
  52. errors if commandStr contains hiddenFlags
  53. hiddenFlags starts and ends with a space and is space deliminated (checked)
  54. notes:
  55. ignores first word (e.g., "qconvex i")
  56. use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
  57. see:
  58. qh_initflags() initializes Qhull according to commandStr
  59. */
  60. void qh_checkflags(char *command, char *hiddenflags) {
  61. char *s= command, *t, *chkerr, key, opt, prevopt;
  62. char chkkey[]= " ";
  63. char chkopt[]= " ";
  64. char chkopt2[]= " ";
  65. if (*hiddenflags != ' ' || hiddenflags[strlen(hiddenflags)-1] != ' ') {
  66. fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags must start and end with a space: \"%s\"", hiddenflags);
  67. qh_errexit(qh_ERRinput, NULL, NULL);
  68. }
  69. if (strpbrk(hiddenflags, ",\n\r\t")) {
  70. fprintf(qh ferr, "qhull error (qh_checkflags): hiddenflags contains commas, newlines, or tabs: \"%s\"", hiddenflags);
  71. qh_errexit(qh_ERRinput, NULL, NULL);
  72. }
  73. while (*s && !isspace(*s)) /* skip program name */
  74. s++;
  75. while (*s) {
  76. while (*s && isspace(*s))
  77. s++;
  78. if (*s == '-')
  79. s++;
  80. if (!*s)
  81. break;
  82. key = *s++;
  83. chkerr = NULL;
  84. if (key == '\'') { /* TO 'file name' */
  85. t= strchr(s, '\'');
  86. if (!t) {
  87. fprintf(qh ferr, "qhull error (qh_checkflags): missing the 2nd single-quote for:\n%s\n", s-1);
  88. qh_errexit(qh_ERRinput, NULL, NULL);
  89. }
  90. s= t+1;
  91. continue;
  92. }
  93. chkkey[1]= key;
  94. if (strstr(hiddenflags, chkkey)) {
  95. chkerr= chkkey;
  96. }else if (isupper(key)) {
  97. opt= ' ';
  98. prevopt= ' ';
  99. chkopt[1]= key;
  100. chkopt2[1]= key;
  101. while (!chkerr && *s && !isspace(*s)) {
  102. opt= *s++;
  103. if (isalpha(opt)) {
  104. chkopt[2]= opt;
  105. if (strstr(hiddenflags, chkopt))
  106. chkerr= chkopt;
  107. if (prevopt != ' ') {
  108. chkopt2[2]= prevopt;
  109. chkopt2[3]= opt;
  110. if (strstr(hiddenflags, chkopt2))
  111. chkerr= chkopt2;
  112. }
  113. }else if (key == 'Q' && isdigit(opt) && prevopt != 'b'
  114. && (prevopt == ' ' || islower(prevopt))) {
  115. chkopt[2]= opt;
  116. if (strstr(hiddenflags, chkopt))
  117. chkerr= chkopt;
  118. }else {
  119. qh_strtod (s-1, &t);
  120. if (s < t)
  121. s= t;
  122. }
  123. prevopt= opt;
  124. }
  125. }
  126. if (chkerr) {
  127. *chkerr= '\'';
  128. chkerr[strlen(chkerr)-1]= '\'';
  129. fprintf(qh ferr, "qhull error: option %s is not used with this program.\n It may be used with qhull.\n", chkerr);
  130. qh_errexit(qh_ERRinput, NULL, NULL);
  131. }
  132. }
  133. } /* checkflags */
  134. /*-<a href="qh-globa.htm#TOC"
  135. >-------------------------------</a><a name="clock">-</a>
  136. qh_clock()
  137. return user CPU time in 100ths (qh_SECtick)
  138. only defined for qh_CLOCKtype == 2
  139. notes:
  140. use first value to determine time 0
  141. from Stevens '92 8.15
  142. */
  143. unsigned long qh_clock (void) {
  144. #if (qh_CLOCKtype == 2)
  145. struct tms time;
  146. static long clktck; /* initialized first call */
  147. double ratio, cpu;
  148. unsigned long ticks;
  149. if (!clktck) {
  150. if ((clktck= sysconf (_SC_CLK_TCK)) < 0) {
  151. fprintf (qh ferr, "qhull internal error (qh_clock): sysconf() failed. Use qh_CLOCKtype 1 in user.h\n");
  152. qh_errexit (qh_ERRqhull, NULL, NULL);
  153. }
  154. }
  155. if (times (&time) == -1) {
  156. fprintf (qh ferr, "qhull internal error (qh_clock): times() failed. Use qh_CLOCKtype 1 in user.h\n");
  157. qh_errexit (qh_ERRqhull, NULL, NULL);
  158. }
  159. ratio= qh_SECticks / (double)clktck;
  160. ticks= time.tms_utime * ratio;
  161. return ticks;
  162. #else
  163. fprintf (qh ferr, "qhull internal error (qh_clock): use qh_CLOCKtype 2 in user.h\n");
  164. qh_errexit (qh_ERRqhull, NULL, NULL); /* never returns */
  165. return 0;
  166. #endif
  167. } /* clock */
  168. /*-<a href="qh-globa.htm#TOC"
  169. >-------------------------------</a><a name="freebuffers">-</a>
  170. qh_freebuffers()
  171. free up global memory buffers
  172. notes:
  173. must match qh_initbuffers()
  174. */
  175. void qh_freebuffers (void) {
  176. trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n"));
  177. /* allocated by qh_initqhull_buffers */
  178. qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT));
  179. qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT));
  180. qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT));
  181. qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT));
  182. qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT));
  183. qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
  184. qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
  185. qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
  186. qh lower_bound= qh upper_bound= NULL;
  187. qh gm_matrix= NULL;
  188. qh gm_row= NULL;
  189. qh_setfree (&qh other_points);
  190. qh_setfree (&qh del_vertices);
  191. qh_setfree (&qh coplanarset);
  192. if (qh line) /* allocated by qh_readinput, freed if no error */
  193. free (qh line);
  194. if (qh half_space)
  195. free (qh half_space);
  196. if (qh temp_malloc)
  197. free (qh temp_malloc);
  198. if (qh feasible_point) /* allocated by qh_readfeasible */
  199. free (qh feasible_point);
  200. if (qh feasible_string) /* allocated by qh_initflags */
  201. free (qh feasible_string);
  202. qh line= qh feasible_string= NULL;
  203. qh half_space= qh feasible_point= qh temp_malloc= NULL;
  204. /* usually allocated by qh_readinput */
  205. if (qh first_point && qh POINTSmalloc) {
  206. free(qh first_point);
  207. qh first_point= NULL;
  208. }
  209. if (qh input_points && qh input_malloc) { /* set by qh_joggleinput */
  210. free (qh input_points);
  211. qh input_points= NULL;
  212. }
  213. trace5((qh ferr, "qh_freebuffers: finished\n"));
  214. } /* freebuffers */
  215. /*-<a href="qh-globa.htm#TOC"
  216. >-------------------------------</a><a name="freebuild">-</a>
  217. qh_freebuild( allmem )
  218. free global memory used by qh_initbuild and qh_buildhull
  219. if !allmem,
  220. does not free short memory (freed by qh_memfreeshort)
  221. design:
  222. free centrums
  223. free each vertex
  224. mark unattached ridges
  225. for each facet
  226. free ridges
  227. free outside set, coplanar set, neighbor set, ridge set, vertex set
  228. free facet
  229. free hash table
  230. free interior point
  231. free merge set
  232. free temporary sets
  233. */
  234. void qh_freebuild (boolT allmem) {
  235. facetT *facet;
  236. vertexT *vertex;
  237. ridgeT *ridge, **ridgep;
  238. mergeT *merge, **mergep;
  239. trace1((qh ferr, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
  240. if (qh del_vertices)
  241. qh_settruncate (qh del_vertices, 0);
  242. if (allmem) {
  243. qh_clearcenters (qh_ASnone);
  244. while ((vertex= qh vertex_list)) {
  245. if (vertex->next)
  246. qh_delvertex (vertex);
  247. else {
  248. qh_memfree (vertex, sizeof(vertexT));
  249. qh newvertex_list= qh vertex_list= NULL;
  250. }
  251. }
  252. }else if (qh VERTEXneighbors) {
  253. FORALLvertices
  254. qh_setfreelong (&(vertex->neighbors));
  255. }
  256. qh VERTEXneighbors= False;
  257. qh GOODclosest= NULL;
  258. if (allmem) {
  259. FORALLfacets {
  260. FOREACHridge_(facet->ridges)
  261. ridge->seen= False;
  262. }
  263. FORALLfacets {
  264. if (facet->visible) {
  265. FOREACHridge_(facet->ridges) {
  266. if (!otherfacet_(ridge, facet)->visible)
  267. ridge->seen= True; /* an unattached ridge */
  268. }
  269. }
  270. }
  271. while ((facet= qh facet_list)) {
  272. FOREACHridge_(facet->ridges) {
  273. if (ridge->seen) {
  274. qh_setfree(&(ridge->vertices));
  275. qh_memfree(ridge, sizeof(ridgeT));
  276. }else
  277. ridge->seen= True;
  278. }
  279. qh_setfree (&(facet->outsideset));
  280. qh_setfree (&(facet->coplanarset));
  281. qh_setfree (&(facet->neighbors));
  282. qh_setfree (&(facet->ridges));
  283. qh_setfree (&(facet->vertices));
  284. if (facet->next)
  285. qh_delfacet (facet);
  286. else {
  287. qh_memfree (facet, sizeof(facetT));
  288. qh visible_list= qh newfacet_list= qh facet_list= NULL;
  289. }
  290. }
  291. }else {
  292. FORALLfacets {
  293. qh_setfreelong (&(facet->outsideset));
  294. qh_setfreelong (&(facet->coplanarset));
  295. if (!facet->simplicial) {
  296. qh_setfreelong (&(facet->neighbors));
  297. qh_setfreelong (&(facet->ridges));
  298. qh_setfreelong (&(facet->vertices));
  299. }
  300. }
  301. }
  302. qh_setfree (&(qh hash_table));
  303. qh_memfree (qh interior_point, qh normal_size);
  304. qh interior_point= NULL;
  305. FOREACHmerge_(qh facet_mergeset) /* usually empty */
  306. qh_memfree (merge, sizeof(mergeT));
  307. qh facet_mergeset= NULL; /* temp set */
  308. qh degen_mergeset= NULL; /* temp set */
  309. qh_settempfree_all();
  310. } /* freebuild */
  311. /*-<a href="qh-globa.htm#TOC"
  312. >-------------------------------</a><a name="freeqhull">-</a>
  313. qh_freeqhull( allmem )
  314. free global memory
  315. if !allmem,
  316. does not free short memory (freed by qh_memfreeshort)
  317. notes:
  318. sets qh.NOerrexit in case caller forgets to
  319. design:
  320. free global and temporary memory from qh_initbuild and qh_buildhull
  321. free buffers
  322. free statistics
  323. */
  324. void qh_freeqhull (boolT allmem) {
  325. trace1((qh ferr, "qh_freeqhull: free global memory\n"));
  326. qh NOerrexit= True; /* no more setjmp since called at exit */
  327. qh_freebuild (allmem);
  328. qh_freebuffers();
  329. qh_freestatistics();
  330. #if qh_QHpointer
  331. free (qh_qh);
  332. qh_qh= NULL;
  333. #else
  334. memset((char *)&qh_qh, 0, sizeof(qhT));
  335. qh NOerrexit= True;
  336. #endif
  337. } /* freeqhull */
  338. /*-<a href="qh-globa.htm#TOC"
  339. >-------------------------------</a><a name="init_A">-</a>
  340. qh_init_A( infile, outfile, errfile, argc, argv )
  341. initialize memory and stdio files
  342. convert input options to option string (qh.qhull_command)
  343. notes:
  344. infile may be NULL if qh_readpoints() is not called
  345. errfile should always be defined. It is used for reporting
  346. errors. outfile is used for output and format options.
  347. argc/argv may be 0/NULL
  348. called before error handling initialized
  349. qh_errexit() may not be used
  350. */
  351. void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
  352. qh_meminit (errfile);
  353. qh_initqhull_start (infile, outfile, errfile);
  354. qh_init_qhull_command (argc, argv);
  355. } /* init_A */
  356. /*-<a href="qh-globa.htm#TOC"
  357. >-------------------------------</a><a name="init_B">-</a>
  358. qh_init_B( points, numpoints, dim, ismalloc )
  359. initialize globals for points array
  360. points has numpoints dim-dimensional points
  361. points[0] is the first coordinate of the first point
  362. points[1] is the second coordinate of the first point
  363. points[dim] is the first coordinate of the second point
  364. ismalloc=True
  365. Qhull will call free(points) on exit or input transformation
  366. ismalloc=False
  367. Qhull will allocate a new point array if needed for input transformation
  368. qh.qhull_command
  369. is the option string.
  370. It is defined by qh_init_B(), qh_qhull_command(), or qh_initflags
  371. returns:
  372. if qh.PROJECTinput or (qh.DELAUNAY and qh.PROJECTdelaunay)
  373. projects the input to a new point array
  374. if qh.DELAUNAY,
  375. qh.hull_dim is increased by one
  376. if qh.ATinfinity,
  377. qh_projectinput adds point-at-infinity for Delaunay tri.
  378. if qh.SCALEinput
  379. changes the upper and lower bounds of the input, see qh_scaleinput()
  380. if qh.ROTATEinput
  381. rotates the input by a random rotation, see qh_rotateinput()
  382. if qh.DELAUNAY
  383. rotates about the last coordinate
  384. notes:
  385. called after points are defined
  386. qh_errexit() may be used
  387. */
  388. void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc) {
  389. qh_initqhull_globals (points, numpoints, dim, ismalloc);
  390. if (qhmem.LASTsize == 0)
  391. qh_initqhull_mem();
  392. /* mem.c and qset.c are initialized */
  393. qh_initqhull_buffers();
  394. qh_initthresholds (qh qhull_command);
  395. if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
  396. qh_projectinput();
  397. if (qh SCALEinput)
  398. qh_scaleinput();
  399. if (qh ROTATErandom >= 0) {
  400. qh_randommatrix (qh gm_matrix, qh hull_dim, qh gm_row);
  401. if (qh DELAUNAY) {
  402. int k, lastk= qh hull_dim-1;
  403. for (k= 0; k < lastk; k++) {
  404. qh gm_row[k][lastk]= 0.0;
  405. qh gm_row[lastk][k]= 0.0;
  406. }
  407. qh gm_row[lastk][lastk]= 1.0;
  408. }
  409. qh_gram_schmidt (qh hull_dim, qh gm_row);
  410. qh_rotateinput (qh gm_row);
  411. }
  412. } /* init_B */
  413. /*-<a href="qh-globa.htm#TOC"
  414. >-------------------------------</a><a name="init_qhull_command">-</a>
  415. qh_init_qhull_command( argc, argv )
  416. build qh.qhull_command from argc/argv
  417. returns:
  418. a space-deliminated string of options (just as typed)
  419. notes:
  420. makes option string easy to input and output
  421. argc/argv may be 0/NULL
  422. */
  423. void qh_init_qhull_command(int argc, char *argv[]) {
  424. int i;
  425. char *s;
  426. if (argc) {
  427. if ((s= strrchr( argv[0], '\\'))) /* Borland gives full path */
  428. strcpy (qh qhull_command, s+1);
  429. else
  430. strcpy (qh qhull_command, argv[0]);
  431. if ((s= strstr (qh qhull_command, ".EXE"))
  432. || (s= strstr (qh qhull_command, ".exe")))
  433. *s= '\0';
  434. }
  435. for (i=1; i < argc; i++) {
  436. if (strlen (qh qhull_command) + strlen(argv[i]) + 1 < sizeof(qh qhull_command)) {
  437. strcat (qh qhull_command, " ");
  438. strcat (qh qhull_command, argv[i]);
  439. }else {
  440. fprintf (qh ferr, "qhull input error: more than %d characters in command line\n",
  441. (int)sizeof(qh qhull_command));
  442. exit (1); /* can not use qh_errexit */
  443. }
  444. }
  445. } /* init_qhull_command */
  446. /*-<a href="qh-globa.htm#TOC"
  447. >-------------------------------</a><a name="initflags">-</a>
  448. qh_initflags( commandStr )
  449. set flags and initialized constants from commandStr
  450. returns:
  451. sets qh.qhull_command to command if needed
  452. notes:
  453. ignores first word (e.g., "qhull d")
  454. use qh_strtol/strtod since strtol/strtod may or may not skip trailing spaces
  455. see:
  456. qh_initthresholds() continues processing of 'Pdn' and 'PDn'
  457. 'prompt' in unix.c for documentation
  458. design:
  459. for each space-deliminated option group
  460. if top-level option
  461. check syntax
  462. append approriate option to option string
  463. set appropriate global variable or append printFormat to print options
  464. else
  465. for each sub-option
  466. check syntax
  467. append approriate option to option string
  468. set appropriate global variable or append printFormat to print options
  469. */
  470. void qh_initflags(char *command) {
  471. int k, i, lastproject;
  472. char *s= command, *t, *prev_s, *start, key;
  473. boolT isgeom= False, wasproject;
  474. realT r;
  475. if (command != &qh qhull_command[0]) {
  476. *qh qhull_command= '\0';
  477. strncat( qh qhull_command, command, sizeof( qh qhull_command));
  478. }
  479. while (*s && !isspace(*s)) /* skip program name */
  480. s++;
  481. while (*s) {
  482. while (*s && isspace(*s))
  483. s++;
  484. if (*s == '-')
  485. s++;
  486. if (!*s)
  487. break;
  488. prev_s= s;
  489. switch (*s++) {
  490. case 'd':
  491. qh_option ("delaunay", NULL, NULL);
  492. qh DELAUNAY= True;
  493. break;
  494. case 'f':
  495. qh_option ("facets", NULL, NULL);
  496. qh_appendprint (qh_PRINTfacets);
  497. break;
  498. case 'i':
  499. qh_option ("incidence", NULL, NULL);
  500. qh_appendprint (qh_PRINTincidences);
  501. break;
  502. case 'm':
  503. qh_option ("mathematica", NULL, NULL);
  504. qh_appendprint (qh_PRINTmathematica);
  505. break;
  506. case 'n':
  507. qh_option ("normals", NULL, NULL);
  508. qh_appendprint (qh_PRINTnormals);
  509. break;
  510. case 'o':
  511. qh_option ("offFile", NULL, NULL);
  512. qh_appendprint (qh_PRINToff);
  513. break;
  514. case 'p':
  515. qh_option ("points", NULL, NULL);
  516. qh_appendprint (qh_PRINTpoints);
  517. break;
  518. case 's':
  519. qh_option ("summary", NULL, NULL);
  520. qh PRINTsummary= True;
  521. break;
  522. case 'v':
  523. qh_option ("voronoi", NULL, NULL);
  524. qh VORONOI= True;
  525. qh DELAUNAY= True;
  526. break;
  527. case 'A':
  528. if (!isdigit(*s) && *s != '.' && *s != '-')
  529. fprintf(qh ferr, "qhull warning: no maximum cosine angle given for option 'An'. Ignored.\n");
  530. else {
  531. if (*s == '-') {
  532. qh premerge_cos= -qh_strtod (s, &s);
  533. qh_option ("Angle-premerge-", NULL, &qh premerge_cos);
  534. qh PREmerge= True;
  535. }else {
  536. qh postmerge_cos= qh_strtod (s, &s);
  537. qh_option ("Angle-postmerge", NULL, &qh postmerge_cos);
  538. qh POSTmerge= True;
  539. }
  540. qh MERGING= True;
  541. }
  542. break;
  543. case 'C':
  544. if (!isdigit(*s) && *s != '.' && *s != '-')
  545. fprintf(qh ferr, "qhull warning: no centrum radius given for option 'Cn'. Ignored.\n");
  546. else {
  547. if (*s == '-') {
  548. qh premerge_centrum= -qh_strtod (s, &s);
  549. qh_option ("Centrum-premerge-", NULL, &qh premerge_centrum);
  550. qh PREmerge= True;
  551. }else {
  552. qh postmerge_centrum= qh_strtod (s, &s);
  553. qh_option ("Centrum-postmerge", NULL, &qh postmerge_centrum);
  554. qh POSTmerge= True;
  555. }
  556. qh MERGING= True;
  557. }
  558. break;
  559. case 'E':
  560. if (*s == '-')
  561. fprintf(qh ferr, "qhull warning: negative maximum roundoff given for option 'An'. Ignored.\n");
  562. else if (!isdigit(*s))
  563. fprintf(qh ferr, "qhull warning: no maximum roundoff given for option 'En'. Ignored.\n");
  564. else {
  565. qh DISTround= qh_strtod (s, &s);
  566. qh_option ("Distance-roundoff", NULL, &qh DISTround);
  567. qh SETroundoff= True;
  568. }
  569. break;
  570. case 'H':
  571. start= s;
  572. qh HALFspace= True;
  573. qh_strtod (s, &t);
  574. while (t > s) {
  575. if (*t && !isspace (*t)) {
  576. if (*t == ',')
  577. t++;
  578. else
  579. fprintf (qh ferr, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
  580. }
  581. s= t;
  582. qh_strtod (s, &t);
  583. }
  584. if (start < t) {
  585. if (!(qh feasible_string= (char*)calloc (t-start+1, 1))) {
  586. fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
  587. qh_errexit(qh_ERRmem, NULL, NULL);
  588. }
  589. strncpy (qh feasible_string, start, t-start);
  590. qh_option ("Halfspace-about", NULL, NULL);
  591. qh_option (qh feasible_string, NULL, NULL);
  592. }else
  593. qh_option ("Halfspace", NULL, NULL);
  594. break;
  595. case 'R':
  596. if (!isdigit(*s))
  597. fprintf(qh ferr, "qhull warning: missing random perturbation for option 'Rn'. Ignored\n");
  598. else {
  599. qh RANDOMfactor= qh_strtod (s, &s);
  600. qh_option ("Random_perturb", NULL, &qh RANDOMfactor);
  601. qh RANDOMdist= True;
  602. }
  603. break;
  604. case 'V':
  605. if (!isdigit(*s) && *s != '-')
  606. fprintf(qh ferr, "qhull warning: missing visible distance for option 'Vn'. Ignored\n");
  607. else {
  608. qh MINvisible= qh_strtod (s, &s);
  609. qh_option ("Visible", NULL, &qh MINvisible);
  610. }
  611. break;
  612. case 'U':
  613. if (!isdigit(*s) && *s != '-')
  614. fprintf(qh ferr, "qhull warning: missing coplanar distance for option 'Un'. Ignored\n");
  615. else {
  616. qh MAXcoplanar= qh_strtod (s, &s);
  617. qh_option ("U-coplanar", NULL, &qh MAXcoplanar);
  618. }
  619. break;
  620. case 'W':
  621. if (*s == '-')
  622. fprintf(qh ferr, "qhull warning: negative outside width for option 'Wn'. Ignored.\n");
  623. else if (!isdigit(*s))
  624. fprintf(qh ferr, "qhull warning: missing outside width for option 'Wn'. Ignored\n");
  625. else {
  626. qh MINoutside= qh_strtod (s, &s);
  627. qh_option ("W-outside", NULL, &qh MINoutside);
  628. qh APPROXhull= True;
  629. }
  630. break;
  631. /************ sub menus ***************/
  632. case 'F':
  633. while (*s && !isspace(*s)) {
  634. switch(*s++) {
  635. case 'a':
  636. qh_option ("Farea", NULL, NULL);
  637. qh_appendprint (qh_PRINTarea);
  638. qh GETarea= True;
  639. break;
  640. case 'A':
  641. qh_option ("FArea-total", NULL, NULL);
  642. qh GETarea= True;
  643. break;
  644. case 'c':
  645. qh_option ("Fcoplanars", NULL, NULL);
  646. qh_appendprint (qh_PRINTcoplanars);
  647. break;
  648. case 'C':
  649. qh_option ("FCentrums", NULL, NULL);
  650. qh_appendprint (qh_PRINTcentrums);
  651. break;
  652. case 'd':
  653. qh_option ("Fd-cdd-in", NULL, NULL);
  654. qh CDDinput= True;
  655. break;
  656. case 'D':
  657. qh_option ("FD-cdd-out", NULL, NULL);
  658. qh CDDoutput= True;
  659. break;
  660. case 'F':
  661. qh_option ("FFacets-xridge", NULL, NULL);
  662. qh_appendprint (qh_PRINTfacets_xridge);
  663. break;
  664. case 'i':
  665. qh_option ("Finner", NULL, NULL);
  666. qh_appendprint (qh_PRINTinner);
  667. break;
  668. case 'I':
  669. qh_option ("FIDs", NULL, NULL);
  670. qh_appendprint (qh_PRINTids);
  671. break;
  672. case 'm':
  673. qh_option ("Fmerges", NULL, NULL);
  674. qh_appendprint (qh_PRINTmerges);
  675. break;
  676. case 'M':
  677. qh_option ("FMaple", NULL, NULL);
  678. qh_appendprint (qh_PRINTmaple);
  679. break;
  680. case 'n':
  681. qh_option ("Fneighbors", NULL, NULL);
  682. qh_appendprint (qh_PRINTneighbors);
  683. break;
  684. case 'N':
  685. qh_option ("FNeighbors-vertex", NULL, NULL);
  686. qh_appendprint (qh_PRINTvneighbors);
  687. break;
  688. case 'o':
  689. qh_option ("Fouter", NULL, NULL);
  690. qh_appendprint (qh_PRINTouter);
  691. break;
  692. case 'O':
  693. if (qh PRINToptions1st) {
  694. qh_option ("FOptions", NULL, NULL);
  695. qh_appendprint (qh_PRINToptions);
  696. }else
  697. qh PRINToptions1st= True;
  698. break;
  699. case 'p':
  700. qh_option ("Fpoint-intersect", NULL, NULL);
  701. qh_appendprint (qh_PRINTpointintersect);
  702. break;
  703. case 'P':
  704. qh_option ("FPoint-nearest", NULL, NULL);
  705. qh_appendprint (qh_PRINTpointnearest);
  706. break;
  707. case 'Q':
  708. qh_option ("FQhull", NULL, NULL);
  709. qh_appendprint (qh_PRINTqhull);
  710. break;
  711. case 's':
  712. qh_option ("Fsummary", NULL, NULL);
  713. qh_appendprint (qh_PRINTsummary);
  714. break;
  715. case 'S':
  716. qh_option ("FSize", NULL, NULL);
  717. qh_appendprint (qh_PRINTsize);
  718. qh GETarea= True;
  719. break;
  720. case 't':
  721. qh_option ("Ftriangles", NULL, NULL);
  722. qh_appendprint (qh_PRINTtriangles);
  723. break;
  724. case 'v':
  725. /* option set in qh_initqhull_globals */
  726. qh_appendprint (qh_PRINTvertices);
  727. break;
  728. case 'V':
  729. qh_option ("FVertex-average", NULL, NULL);
  730. qh_appendprint (qh_PRINTaverage);
  731. break;
  732. case 'x':
  733. qh_option ("Fxtremes", NULL, NULL);
  734. qh_appendprint (qh_PRINTextremes);
  735. break;
  736. default:
  737. s--;
  738. fprintf (qh ferr, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[0]);
  739. while (*++s && !isspace(*s));
  740. break;
  741. }
  742. }
  743. break;
  744. case 'G':
  745. isgeom= True;
  746. qh_appendprint (qh_PRINTgeom);
  747. while (*s && !isspace(*s)) {
  748. switch(*s++) {
  749. case 'a':
  750. qh_option ("Gall-points", NULL, NULL);
  751. qh PRINTdots= True;
  752. break;
  753. case 'c':
  754. qh_option ("Gcentrums", NULL, NULL);
  755. qh PRINTcentrums= True;
  756. break;
  757. case 'h':
  758. qh_option ("Gintersections", NULL, NULL);
  759. qh DOintersections= True;
  760. break;
  761. case 'i':
  762. qh_option ("Ginner", NULL, NULL);
  763. qh PRINTinner= True;
  764. break;
  765. case 'n':
  766. qh_option ("Gno-planes", NULL, NULL);
  767. qh PRINTnoplanes= True;
  768. break;
  769. case 'o':
  770. qh_option ("Gouter", NULL, NULL);
  771. qh PRINTouter= True;
  772. break;
  773. case 'p':
  774. qh_option ("Gpoints", NULL, NULL);
  775. qh PRINTcoplanar= True;
  776. break;
  777. case 'r':
  778. qh_option ("Gridges", NULL, NULL);
  779. qh PRINTridges= True;
  780. break;
  781. case 't':
  782. qh_option ("Gtransparent", NULL, NULL);
  783. qh PRINTtransparent= True;
  784. break;
  785. case 'v':
  786. qh_option ("Gvertices", NULL, NULL);
  787. qh PRINTspheres= True;
  788. break;
  789. case 'D':
  790. if (!isdigit (*s))
  791. fprintf (qh ferr, "qhull input error: missing dimension for option 'GDn'\n");
  792. else {
  793. if (qh DROPdim >= 0)
  794. fprintf (qh ferr, "qhull warning: can only drop one dimension. Previous 'GD%d' ignored\n",
  795. qh DROPdim);
  796. qh DROPdim= qh_strtol (s, &s);
  797. qh_option ("GDrop-dim", &qh DROPdim, NULL);
  798. }
  799. break;
  800. default:
  801. s--;
  802. fprintf (qh ferr, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
  803. while (*++s && !isspace(*s));
  804. break;
  805. }
  806. }
  807. break;
  808. case 'P':
  809. while (*s && !isspace(*s)) {
  810. switch(*s++) {
  811. case 'd': case 'D': /* see qh_initthresholds() */
  812. key= s[-1];
  813. i= qh_strtol (s, &s);
  814. r= 0;
  815. if (*s == ':') {
  816. s++;
  817. r= qh_strtod (s, &s);
  818. }
  819. if (key == 'd')
  820. qh_option ("Pdrop-facets-dim-less", &i, &r);
  821. else
  822. qh_option ("PDrop-facets-dim-more", &i, &r);
  823. break;
  824. case 'g':
  825. qh_option ("Pgood-facets", NULL, NULL);
  826. qh PRINTgood= True;
  827. break;
  828. case 'G':
  829. qh_option ("PGood-facet-neighbors", NULL, NULL);
  830. qh PRINTneighbors= True;
  831. break;
  832. case 'o':
  833. qh_option ("Poutput-forced", NULL, NULL);
  834. qh FORCEoutput= True;
  835. break;
  836. case 'p':
  837. qh_option ("Pprecision-ignore", NULL, NULL);
  838. qh PRINTprecision= False;
  839. break;
  840. case 'A':
  841. if (!isdigit (*s))
  842. fprintf (qh ferr, "qhull input error: missing facet count for keep area option 'PAn'\n");
  843. else {
  844. qh KEEParea= qh_strtol (s, &s);
  845. qh_option ("PArea-keep", &qh KEEParea, NULL);
  846. qh GETarea= True;
  847. }
  848. break;
  849. case 'F':
  850. if (!isdigit (*s))
  851. fprintf (qh ferr, "qhull input error: missing facet area for option 'PFn'\n");
  852. else {
  853. qh KEEPminArea= qh_strtod (s, &s);
  854. qh_option ("PFacet-area-keep", NULL, &qh KEEPminArea);
  855. qh GETarea= True;
  856. }
  857. break;
  858. case 'M':
  859. if (!isdigit (*s))
  860. fprintf (qh ferr, "qhull input error: missing merge count for option 'PMn'\n");
  861. else {
  862. qh KEEPmerge= qh_strtol (s, &s);
  863. qh_option ("PMerge-keep", &qh KEEPmerge, NULL);
  864. }
  865. break;
  866. default:
  867. s--;
  868. fprintf (qh ferr, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[0]);
  869. while (*++s && !isspace(*s));
  870. break;
  871. }
  872. }
  873. break;
  874. case 'Q':
  875. lastproject= -1;
  876. while (*s && !isspace(*s)) {
  877. switch(*s++) {
  878. case 'b': case 'B': /* handled by qh_initthresholds */
  879. key= s[-1];
  880. if (key == 'b' && *s == 'B') {
  881. s++;
  882. r= qh_DEFAULTbox;
  883. qh SCALEinput= True;
  884. qh_option ("QbBound-unit-box", NULL, &r);
  885. break;
  886. }
  887. if (key == 'b' && *s == 'b') {
  888. s++;
  889. qh SCALElast= True;
  890. qh_option ("Qbbound-last", NULL, NULL);
  891. break;
  892. }
  893. k= qh_strtol (s, &s);
  894. r= 0.0;
  895. wasproject= False;
  896. if (*s == ':') {
  897. s++;
  898. if ((r= qh_strtod(s, &s)) == 0.0) {
  899. t= s; /* need true dimension for memory allocation */
  900. while (*t && !isspace(*t)) {
  901. if (toupper(*t++) == 'B'
  902. && k == qh_strtol (t, &t)
  903. && *t++ == ':'
  904. && qh_strtod(t, &t) == 0.0) {
  905. qh PROJECTinput++;
  906. trace2((qh ferr, "qh_initflags: project dimension %d\n", k));
  907. qh_option ("Qb-project-dim", &k, NULL);
  908. wasproject= True;
  909. lastproject= k;
  910. break;
  911. }
  912. }
  913. }
  914. }
  915. if (!wasproject) {
  916. if (lastproject == k && r == 0.0)
  917. lastproject= -1; /* doesn't catch all possible sequences */
  918. else if (key == 'b') {
  919. qh SCALEinput= True;
  920. if (r == 0.0)
  921. r= -qh_DEFAULTbox;
  922. qh_option ("Qbound-dim-low", &k, &r);
  923. }else {
  924. qh SCALEinput= True;
  925. if (r == 0.0)
  926. r= qh_DEFAULTbox;
  927. qh_option ("QBound-dim-high", &k, &r);
  928. }
  929. }
  930. break;
  931. case 'c':
  932. qh_option ("Qcoplanar-keep", NULL, NULL);
  933. qh KEEPcoplanar= True;
  934. break;
  935. case 'f':
  936. qh_option ("Qfurthest-outside", NULL, NULL);
  937. qh BESToutside= True;
  938. break;
  939. case 'g':
  940. qh_option ("Qgood-facets-only", NULL, NULL);
  941. qh ONLYgood= True;
  942. break;
  943. case 'i':
  944. qh_option ("Qinterior-keep", NULL, NULL);
  945. qh KEEPinside= True;
  946. break;
  947. case 'm':
  948. qh_option ("Qmax-outside-only", NULL, NULL);
  949. qh ONLYmax= True;
  950. break;
  951. case 'r':
  952. qh_option ("Qrandom-outside", NULL, NULL);
  953. qh RANDOMoutside= True;
  954. break;
  955. case 's':
  956. qh_option ("Qsearch-initial-simplex", NULL, NULL);
  957. qh ALLpoints= True;
  958. break;
  959. case 't':
  960. qh_option ("Qtriangulate", NULL, NULL);
  961. qh TRIangulate= True;
  962. break;
  963. case 'T':
  964. qh_option ("QTestPoints", NULL, NULL);
  965. if (!isdigit (*s))
  966. fprintf (qh ferr, "qhull input error: missing number of test points for option 'QTn'\n");
  967. else {
  968. qh TESTpoints= qh_strtol (s, &s);
  969. qh_option ("QTestPoints", &qh TESTpoints, NULL);
  970. }
  971. break;
  972. case 'u':
  973. qh_option ("QupperDelaunay", NULL, NULL);
  974. qh UPPERdelaunay= True;
  975. break;
  976. case 'v':
  977. qh_option ("Qvertex-neighbors-convex", NULL, NULL);
  978. qh TESTvneighbors= True;
  979. break;
  980. case 'x':
  981. qh_option ("Qxact-merge", NULL, NULL);
  982. qh MERGEexact= True;
  983. break;
  984. case 'z':
  985. qh_option ("Qz-infinity-point", NULL, NULL);
  986. qh ATinfinity= True;
  987. break;
  988. case '0':
  989. qh_option ("Q0-no-premerge", NULL, NULL);
  990. qh NOpremerge= True;
  991. break;
  992. case '1':
  993. if (!isdigit(*s)) {
  994. qh_option ("Q1-no-angle-sort", NULL, NULL);
  995. qh ANGLEmerge= False;
  996. break;
  997. }
  998. switch(*s++) {
  999. case '0':
  1000. qh_option ("Q10-no-narrow", NULL, NULL);
  1001. qh NOnarrow= True;
  1002. break;
  1003. case '1':
  1004. qh_option ("Q11-trinormals Qtriangulate", NULL, NULL);
  1005. qh TRInormals= True;
  1006. qh TRIangulate= True;
  1007. break;
  1008. default:
  1009. s--;
  1010. fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option 1%c, rest ignored\n", (int)s[0]);
  1011. while (*++s && !isspace(*s));
  1012. break;
  1013. }
  1014. break;
  1015. case '2':
  1016. qh_option ("Q2-no-merge-independent", NULL, NULL);
  1017. qh MERGEindependent= False;
  1018. goto LABELcheckdigit;
  1019. break; /* no warnings */
  1020. case '3':
  1021. qh_option ("Q3-no-merge-vertices", NULL, NULL);
  1022. qh MERGEvertices= False;
  1023. LABELcheckdigit:
  1024. if (isdigit(*s))
  1025. fprintf (qh ferr, "qhull warning: can not follow '1', '2', or '3' with a digit. '%c' skipped.\n",
  1026. *s++);
  1027. break;
  1028. case '4':
  1029. qh_option ("Q4-avoid-old-into-new", NULL, NULL);
  1030. qh AVOIDold= True;
  1031. break;
  1032. case '5':
  1033. qh_option ("Q5-no-check-outer", NULL, NULL);
  1034. qh SKIPcheckmax= True;
  1035. break;
  1036. case '6':
  1037. qh_option ("Q6-no-concave-merge", NULL, NULL);
  1038. qh SKIPconvex= True;
  1039. break;
  1040. case '7':
  1041. qh_option ("Q7-no-breadth-first", NULL, NULL);
  1042. qh VIRTUALmemory= True;
  1043. break;
  1044. case '8':
  1045. qh_option ("Q8-no-near-inside", NULL, NULL);
  1046. qh NOnearinside= True;
  1047. break;
  1048. case '9':
  1049. qh_option ("Q9-pick-furthest", NULL, NULL);
  1050. qh PICKfurthest= True;
  1051. break;
  1052. case 'G':
  1053. i= qh_strtol (s, &t);
  1054. if (qh GOODpoint)
  1055. fprintf (qh ferr, "qhull warning: good point already defined for option 'QGn'. Ignored\n");
  1056. else if (s == t)
  1057. fprintf (qh ferr, "qhull warning: missing good point id for option 'QGn'. Ignored\n");
  1058. else if (i < 0 || *s == '-') {
  1059. qh GOODpoint= i-1;
  1060. qh_option ("QGood-if-dont-see-point", &i, NULL);
  1061. }else {
  1062. qh GOODpoint= i+1;
  1063. qh_option ("QGood-if-see-point", &i, NULL);
  1064. }
  1065. s= t;
  1066. break;
  1067. case 'J':
  1068. if (!isdigit(*s) && *s != '-')
  1069. qh JOGGLEmax= 0.0;
  1070. else {
  1071. qh JOGGLEmax= (realT) qh_strtod (s, &s);
  1072. qh_option ("QJoggle", NULL, &qh JOGGLEmax);
  1073. }
  1074. break;
  1075. case 'R':
  1076. if (!isdigit(*s) && *s != '-')
  1077. fprintf (qh ferr, "qhull warning: missing random seed for option 'QRn'. Ignored\n");
  1078. else {
  1079. qh ROTATErandom= i= qh_strtol(s, &s);
  1080. if (i > 0)
  1081. qh_option ("QRotate-id", &i, NULL );
  1082. else if (i < -1)
  1083. qh_option ("QRandom-seed", &i, NULL );
  1084. }
  1085. break;
  1086. case 'V':
  1087. i= qh_strtol (s, &t);
  1088. if (qh GOODvertex)
  1089. fprintf (qh ferr, "qhull warning: good vertex already defined for option 'QVn'. Ignored\n");
  1090. else if (s == t)
  1091. fprintf (qh ferr, "qhull warning: no good point id given for option 'QVn'. Ignored\n");
  1092. else if (i < 0) {
  1093. qh GOODvertex= i - 1;
  1094. qh_option ("QV-good-facets-not-point", &i, NULL);
  1095. }else {
  1096. qh_option ("QV-good-facets-point", &i, NULL);
  1097. qh GOODvertex= i + 1;
  1098. }
  1099. s= t;
  1100. break;
  1101. default:
  1102. s--;
  1103. fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[0]);
  1104. while (*++s && !isspace(*s));
  1105. break;
  1106. }
  1107. }
  1108. break;
  1109. case 'T':
  1110. while (*s && !isspace(*s)) {
  1111. if (isdigit(*s) || *s == '-')
  1112. qh IStracing= qh_strtol(s, &s);
  1113. else switch(*s++) {
  1114. case 'c':
  1115. qh_option ("Tcheck-frequently", NULL, NULL);
  1116. qh CHECKfrequently= True;
  1117. break;
  1118. case 's':
  1119. qh_option ("Tstatistics", NULL, NULL);
  1120. qh PRINTstatistics= True;
  1121. break;
  1122. case 'v':
  1123. qh_option ("Tverify", NULL, NULL);
  1124. qh VERIFYoutput= True;
  1125. break;
  1126. case 'z':
  1127. if (!qh fout)
  1128. fprintf (qh ferr, "qhull warning: output file undefined (stdout). Option 'Tz' ignored.\n");
  1129. else {
  1130. qh_option ("Tz-stdout", NULL, NULL);
  1131. qh ferr= qh fout;
  1132. qhmem.ferr= qh fout;
  1133. }
  1134. break;
  1135. case 'C':
  1136. if (!isdigit(*s))
  1137. fprintf (qh ferr, "qhull warning: missing point id for cone for trace option 'TCn'. Ignored\n");
  1138. else {
  1139. i= qh_strtol (s, &s);
  1140. qh_option ("TCone-stop", &i, NULL);
  1141. qh STOPcone= i + 1;
  1142. }
  1143. break;
  1144. case 'F':
  1145. if (!isdigit(*s))
  1146. fprintf (qh ferr, "qhull warning: missing frequency count for trace option 'TFn'. Ignored\n");
  1147. else {
  1148. qh REPORTfreq= qh_strtol (s, &s);
  1149. qh_option ("TFacet-log", &qh REPORTfreq, NULL);
  1150. qh REPORTfreq2= qh REPORTfreq/2; /* for tracemerging() */
  1151. }
  1152. break;
  1153. case 'I':
  1154. if (s[0] != ' ' || s[1] == '\"' || s[1] == '\'' ||isspace (s[1])) {
  1155. s++;
  1156. fprintf (qh ferr, "qhull warning: option 'TI' mistyped.\nUse 'TI', one space, file name, and space or end-of-line.\nDo not use quotes. Option 'FI' ignored.\n");
  1157. }else { /* not a procedure because of qh_option (filename, NULL, NULL); */
  1158. char filename[500], *t= filename;
  1159. s++;
  1160. while (*s) {
  1161. if (t - filename >= sizeof (filename)-2) {
  1162. fprintf (qh ferr, "qhull error: filename for 'TI' too long.\n");
  1163. qh_errexit (qh_ERRinput, NULL, NULL);
  1164. }
  1165. if (isspace (*s))
  1166. break;
  1167. *(t++)= *s++;
  1168. }
  1169. *t= '\0';
  1170. if (!freopen (filename, "r", stdin)) {
  1171. fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
  1172. qh_errexit (qh_ERRinput, NULL, NULL);
  1173. }else {
  1174. qh_option ("TInput-file", NULL, NULL);
  1175. qh_option (filename, NULL, NULL);
  1176. }
  1177. }
  1178. break;
  1179. case 'O':
  1180. if (s[0] != ' ' || s[1] == '\"' || isspace (s[1])) {
  1181. s++;
  1182. fprintf (qh ferr, "qhull warning: option 'TO' mistyped.\nUse 'TO', one space, file name, and space or end-of-line.\nThe file name may be enclosed in single quotes.\nDo not use double quotes. Option 'FO' ignored.\n");
  1183. }else { /* not a procedure because of qh_option (filename, NULL, NULL); */
  1184. char filename[500], *t= filename;
  1185. boolT isquote= False;
  1186. s++;
  1187. if (*s == '\'') {
  1188. isquote= True;
  1189. s++;
  1190. }
  1191. while (*s) {
  1192. if (t - filename >= sizeof (filename)-2) {
  1193. fprintf (qh ferr, "qhull error: filename for 'TO' too long.\n");
  1194. qh_errexit (qh_ERRinput, NULL, NULL);
  1195. }
  1196. if (isquote) {
  1197. if (*s == '\'') {
  1198. s++;
  1199. isquote= False;
  1200. break;
  1201. }
  1202. }else if (isspace (*s))
  1203. break;
  1204. *(t++)= *s++;
  1205. }
  1206. *t= '\0';
  1207. if (isquote)
  1208. fprintf (qh ferr, "qhull error: missing end quote for option 'TO'. Rest of line ignored.\n");
  1209. else if (!freopen (filename, "w", stdout)) {
  1210. fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
  1211. qh_errexit (qh_ERRinput, NULL, NULL);
  1212. }else {
  1213. qh_option ("TOutput-file", NULL, NULL);
  1214. qh_option (filename, NULL, NULL);
  1215. }
  1216. }
  1217. break;
  1218. case 'P':
  1219. if (!isdigit(*s))
  1220. fprintf (qh ferr, "qhull warning: missing point id for trace option 'TPn'. Ignored\n");
  1221. else {
  1222. qh TRACEpoint= qh_strtol (s, &s);
  1223. qh_option ("Trace-point", &qh TRACEpoint, NULL);
  1224. }
  1225. break;
  1226. case 'M':
  1227. if (!isdigit(*s))
  1228. fprintf (qh ferr, "qhull warning: missing merge id for trace option 'TMn'. Ignored\n");
  1229. else {
  1230. qh TRACEmerge= qh_strtol (s, &s);
  1231. qh_option ("Trace-merge", &qh TRACEmerge, NULL);
  1232. }
  1233. break;
  1234. case 'R':
  1235. if (!isdigit(*s))
  1236. fprintf (qh ferr, "qhull warning: missing rerun count for trace option 'TRn'. Ignored\n");
  1237. else {
  1238. qh RERUN= qh_strtol (s, &s);
  1239. qh_option ("TRerun", &qh RERUN, NULL);
  1240. }
  1241. break;
  1242. case 'V':
  1243. i= qh_strtol (s, &t);
  1244. if (s == t)
  1245. fprintf (qh ferr, "qhull warning: missing furthest point id for trace option 'TVn'. Ignored\n");
  1246. else if (i < 0) {
  1247. qh STOPpoint= i - 1;
  1248. qh_option ("TV-stop-before-point", &i, NULL);
  1249. }else {
  1250. qh STOPpoint= i + 1;
  1251. qh_option ("TV-stop-after-point", &i, NULL);
  1252. }
  1253. s= t;
  1254. break;
  1255. case 'W':
  1256. if (!isdigit(*s))
  1257. fprintf (qh ferr, "qhull warning: missing max width for trace option 'TWn'. Ignored\n");
  1258. else {
  1259. qh TRACEdist= (realT) qh_strtod (s, &s);
  1260. qh_option ("TWide-trace", NULL, &qh TRACEdist);
  1261. }
  1262. break;
  1263. default:
  1264. s--;
  1265. fprintf (qh ferr, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[0]);
  1266. while (*++s && !isspace(*s));
  1267. break;
  1268. }
  1269. }
  1270. break;
  1271. default:
  1272. fprintf (qh ferr, "qhull warning: unknown flag %c (%x)\n", (int)s[-1],
  1273. (int)s[-1]);
  1274. break;
  1275. }
  1276. if (s-1 == prev_s && *s && !isspace(*s)) {
  1277. fprintf (qh ferr, "qhull warning: missing space after flag %c (%x); reserved for menu. Skipped.\n",
  1278. (int)*prev_s, (int)*prev_s);
  1279. while (*s && !isspace(*s))
  1280. s++;
  1281. }
  1282. }
  1283. if (isgeom && !qh FORCEoutput && qh PRINTout[1])
  1284. fprintf (qh ferr, "qhull warning: additional output formats are not compatible with Geomview\n");
  1285. /* set derived values in qh_initqhull_globals */
  1286. } /* initflags */
  1287. /*-<a href="qh-globa.htm#TOC"
  1288. >-------------------------------</a><a name="initqhull_buffers">-</a>
  1289. qh_initqhull_buffers()
  1290. initialize global memory buffers
  1291. notes:
  1292. must match qh_freebuffers()
  1293. */
  1294. void qh_initqhull_buffers (void) {
  1295. int k;
  1296. qh TEMPsize= (qhmem.LASTsize - sizeof (setT))/SETelemsize;
  1297. if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
  1298. qh TEMPsize= 8; /* e.g., if qh_NOmem */
  1299. qh other_points= qh_setnew (qh TEMPsize);
  1300. qh del_vertices= qh_setnew (qh TEMPsize);
  1301. qh coplanarset= qh_setnew (qh TEMPsize);
  1302. qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
  1303. qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
  1304. qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
  1305. qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
  1306. qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
  1307. for(k= qh input_dim+1; k--; ) {
  1308. qh lower_threshold[k]= -REALmax;
  1309. qh upper_threshold[k]= REALmax;
  1310. qh lower_bound[k]= -REALmax;
  1311. qh upper_bound[k]= REALmax;
  1312. }
  1313. qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
  1314. qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
  1315. } /* initqhull_buffers */
  1316. /*-<a href="qh-globa.htm#TOC"
  1317. >-------------------------------</a><a name="initqhull_globals">-</a>
  1318. qh_initqhull_globals( points, numpoints, dim, ismalloc )
  1319. initialize globals
  1320. if ismalloc
  1321. points were malloc'd and qhull should free at end
  1322. returns:
  1323. sets qh.first_point, num_points, input_dim, hull_dim and others
  1324. seeds random number generator (seed=1 if tracing)
  1325. modifies qh.hull_dim if ((qh.DELAUNAY and qh.PROJECTdelaunay) or qh.PROJECTinput)
  1326. adjust user flags as needed
  1327. also checks DIM3 dependencies and constants
  1328. notes:
  1329. do not use qh_point() since an input transformation may move them elsewhere
  1330. see:
  1331. qh_initqhull_start() sets default values for non-zero globals
  1332. design:
  1333. initialize points array from input arguments
  1334. test for qh.ZEROcentrum
  1335. (i.e., use opposite vertex instead of cetrum for convexity testing)
  1336. test for qh.PRINTgood (i.e., only print 'good' facets)
  1337. initialize qh.CENTERtype, qh.normal_size,
  1338. qh.center_size, qh.TRACEpoint/level,
  1339. initialize and test random numbers
  1340. check for conflicting print output options
  1341. */
  1342. void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc) {
  1343. int seed, pointsneeded, extra= 0, i, randi, k;
  1344. boolT printgeom= False, printmath= False, printcoplanar= False;
  1345. realT randr;
  1346. realT factorial;
  1347. time_t timedata;
  1348. trace0((qh ferr, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
  1349. qh qhull_command));
  1350. qh POINTSmalloc= ismalloc;
  1351. qh first_point= points;
  1352. qh num_points= numpoints;
  1353. qh hull_dim= qh input_dim= dim;
  1354. if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
  1355. qh MERGING= True;
  1356. if (qh hull_dim <= 4) {
  1357. qh PREmerge= True;
  1358. qh_option ("_pre-merge", NULL, NULL);
  1359. }else {
  1360. qh MERGEexact= True;
  1361. qh_option ("Qxact_merge", NULL, NULL);
  1362. }
  1363. }else if (qh MERGEexact)
  1364. qh MERGING= True;
  1365. if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
  1366. #ifdef qh_NOmerge
  1367. qh JOGGLEmax= 0.0;
  1368. #endif
  1369. }
  1370. if (qh TRIangulate && qh JOGGLEmax < REALmax/2 && qh PRINTprecision)
  1371. fprintf(qh ferr, "qhull warning: joggle ('QJ') always produces simplicial output. Triangulated output ('Qt') does nothing.\n");
  1372. if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
  1373. qh SCALElast= True;
  1374. qh_option ("Qbbound-last-qj", NULL, NULL);
  1375. }
  1376. if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
  1377. && qh premerge_centrum == 0) {
  1378. qh ZEROcentrum= True;
  1379. qh ZEROall_ok= True;
  1380. qh_option ("_zero-centrum", NULL, NULL);
  1381. }
  1382. if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
  1383. fprintf(qh ferr, "qhull warning: real epsilon, %2.2g, is probably too large for joggle ('QJn')\nRecompile with double precision reals (see user.h).\n",
  1384. REALepsilon);
  1385. #ifdef qh_NOmerge
  1386. if (qh MERGING) {
  1387. fprintf (qh ferr, "qhull input error: merging not installed (qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
  1388. qh_errexit (qh_ERRinput, NULL, NULL);
  1389. }
  1390. #endif
  1391. if (!(qh PRINTgood || qh PRINTneighbors)) {
  1392. if (qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY
  1393. || (!qh ONLYgood && (qh GOODvertex || qh GOODpoint))) {
  1394. qh PRINTgood= True;
  1395. qh_option ("Pgood", NULL, NULL);
  1396. }
  1397. }
  1398. if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
  1399. qh KEEPinside= True;
  1400. qh_option ("Qinterior-keep", NULL, NULL);
  1401. }
  1402. if (qh DELAUNAY && qh HALFspace) {
  1403. fprintf (qh ferr, "qhull input error: can not use Delaunay ('d') or Voronoi ('v') with halfspace intersection ('H')\n");
  1404. qh_errexit (qh_ERRinput, NULL, NULL);
  1405. }
  1406. if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
  1407. fprintf (qh ferr, "qhull input error: use upper-Delaunay ('Qu') or infinity-point ('Qz') with Delaunay ('d') or Voronoi ('v')\n");
  1408. qh_errexit (qh_ERRinput, NULL, NULL);
  1409. }
  1410. if (qh UPPERdelaunay && qh ATinfinity) {
  1411. fprintf (qh ferr, "qhull input error: can not use infinity-point ('Qz') with upper-Delaunay ('Qu')\n");
  1412. qh_errexit (qh_ERRinput, NULL, NULL);
  1413. }
  1414. if (qh SCALElast && !qh DELAUNAY && qh PRINTprecision)
  1415. fprintf (qh ferr, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
  1416. qh DOcheckmax= (!qh SKIPcheckmax && qh MERGING );
  1417. qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
  1418. && !qh NOnearinside);
  1419. if (qh MERGING)
  1420. qh CENTERtype= qh_AScentrum;
  1421. else if (qh VORONOI)
  1422. qh CENTERtype= qh_ASvoronoi;
  1423. if (qh TESTvneighbors && !qh MERGING) {
  1424. fprintf(qh ferr, "qhull input error: test vertex neighbors ('Qv') needs a merge option\n");
  1425. qh_errexit (qh_ERRinput, NULL ,NULL);
  1426. }
  1427. if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
  1428. qh hull_dim -= qh PROJECTinput;
  1429. if (qh DELAUNAY) {
  1430. qh hull_dim++;
  1431. extra= 1;
  1432. }
  1433. }
  1434. if (qh hull_dim <= 1) {
  1435. fprintf(qh ferr, "qhull error: dimension %d must be > 1\n", qh hull_dim);
  1436. qh_errexit (qh_ERRinput, NULL, NULL);
  1437. }
  1438. for (k= 2, factorial=1.0; k < qh hull_dim; k++)
  1439. factorial *= k;
  1440. qh AREAfactor= 1.0 / factorial;
  1441. trace2((qh ferr, "qh_initqhull_globals: initialize globals. dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
  1442. dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
  1443. qh normal_size= qh hull_dim * sizeof(coordT);
  1444. qh center_size= qh normal_size - sizeof(coordT);
  1445. pointsneeded= qh hull_dim+1;
  1446. if (qh hull_dim > qh_DIMmergeVertex) {
  1447. qh MERGEvertices= False;
  1448. qh_option ("Q3-no-merge-vertices-dim-high", NULL, NULL);
  1449. }
  1450. if (qh GOODpoint)
  1451. pointsneeded++;
  1452. #ifdef qh_NOtrace
  1453. if (qh IStracing) {
  1454. fprintf (qh ferr, "qhull input error: tracing is not installed (qh_NOtrace in user.h)");
  1455. qh_errexit (qh_ERRqhull, NULL, NULL);
  1456. }
  1457. #endif
  1458. if (qh RERUN > 1) {
  1459. qh TRACElastrun= qh IStracing; /* qh_build_withrestart duplicates next conditional */
  1460. if (qh IStracing != -1)
  1461. qh IStracing= 0;
  1462. }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
  1463. qh TRACElevel= (qh IStracing? qh IStracing : 3);
  1464. qh IStracing= 0;
  1465. }
  1466. if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
  1467. seed= time (&timedata);
  1468. if (qh ROTATErandom == -1) {
  1469. seed= -seed;
  1470. qh_option ("QRandom-seed", &seed, NULL );
  1471. }else
  1472. qh_option ("QRotate-random", &seed, NULL);
  1473. qh ROTATErandom= seed;
  1474. }
  1475. seed= qh ROTATErandom;
  1476. if (seed == INT_MIN) /* default value */
  1477. seed= 1;
  1478. else if (seed < 0)
  1479. seed= -seed;
  1480. qh_RANDOMseed_(seed);
  1481. randr= 0.0;
  1482. for (i= 1000; i--; ) {
  1483. randi= qh_RANDOMint;
  1484. randr += randi;
  1485. if (randi > qh_RANDOMmax) {
  1486. fprintf (qh ferr, "\
  1487. qhull configuration error (qh_RANDOMmax in user.h):\n\
  1488. random integer %d > qh_RANDOMmax (%.8g)\n",
  1489. randi, qh_RANDOMmax);
  1490. qh_errexit (qh_ERRinput, NULL, NULL);
  1491. }
  1492. }
  1493. qh_RANDOMseed_(seed);
  1494. randr = randr/1000;
  1495. if (randr < qh_RANDOMmax/10
  1496. || randr > qh_RANDOMmax * 5)
  1497. fprintf (qh ferr, "\
  1498. qhull configuration warning (qh_RANDOMmax in user.h):\n\
  1499. average of 1000 random integers (%.2g) is much different than expected (%.2g).\n\
  1500. Is qh_RANDOMmax (%.2g) wrong?\n",
  1501. randr, qh_RANDOMmax/2.0, qh_RANDOMmax);
  1502. qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
  1503. qh RANDOMb= 1.0 - qh RANDOMfactor;
  1504. if (qh_HASHfactor < 1.1) {
  1505. fprintf(qh ferr, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1. Qhull uses linear hash probing\n",
  1506. qh_HASHfactor);
  1507. qh_errexit (qh_ERRqhull, NULL, NULL);
  1508. }
  1509. if (numpoints+extra < pointsneeded) {
  1510. fprintf(qh ferr,"qhull input error: not enough points (%d) to construct initial simplex (need %d)\n",
  1511. numpoints, pointsneeded);
  1512. qh_errexit(qh_ERRinput, NULL, NULL);
  1513. }
  1514. if (qh PRINTtransparent) {
  1515. if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
  1516. fprintf(qh ferr,"qhull input error: transparent Delaunay ('Gt') needs 3-d Delaunay ('d') w/o 'GDn'\n");
  1517. qh_errexit(qh_ERRinput, NULL, NULL);
  1518. }
  1519. qh DROPdim = 3;
  1520. qh PRINTridges = True;
  1521. }
  1522. for (i= qh_PRINTEND; i--; ) {
  1523. if (qh PRINTout[i] == qh_PRINTgeom)
  1524. printgeom= True;
  1525. else if (qh PRINTout[i] == qh_PRINTmathematica || qh PRINTout[i] == qh_PRINTmaple)
  1526. printmath= True;
  1527. else if (qh PRINTout[i] == qh_PRINTcoplanars)
  1528. printcoplanar= True;
  1529. else if (qh PRINTout[i] == qh_PRINTpointnearest)
  1530. printcoplanar= True;
  1531. else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
  1532. fprintf (qh ferr, "qhull input error: option 'Fp' is only used for \nhalfspace intersection ('Hn,n,n').\n");
  1533. qh_errexit (qh_ERRinput, NULL, NULL);
  1534. }else if (qh PRINTout[i] == qh_PRINTtriangles && (qh HALFspace || qh VORONOI)) {
  1535. fprintf (qh ferr, "qhull input error: option 'Ft' is not available