00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "qhull_a.h"
00017
00018 #ifdef USE_DMALLOC
00019 #include "dmalloc.h"
00020 #endif
00021
00022
00023
00024 #if qh_QHpointer
00025 qhT *qh_qh= NULL;
00026 #else
00027 qhT qh_qh;
00028
00029
00030 #endif
00031
00032
00033
00034
00035
00036
00037
00038 void qh_appendprint (qh_PRINT format) {
00039 int i;
00040
00041 for (i=0; i < qh_PRINTEND; i++) {
00042 if (qh PRINTout[i] == format)
00043 break;
00044 if (!qh PRINTout[i]) {
00045 qh PRINTout[i]= format;
00046 break;
00047 }
00048 }
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 void qh_freebuffers (void) {
00061
00062 trace5((qh ferr, "qh_freebuffers: freeing up global memory buffers\n"));
00063
00064 qh_memfree (qh NEARzero, qh hull_dim * sizeof(realT));
00065 qh_memfree (qh lower_threshold, (qh input_dim+1) * sizeof(realT));
00066 qh_memfree (qh upper_threshold, (qh input_dim+1) * sizeof(realT));
00067 qh_memfree (qh lower_bound, (qh input_dim+1) * sizeof(realT));
00068 qh_memfree (qh upper_bound, (qh input_dim+1) * sizeof(realT));
00069 qh_memfree (qh gm_matrix, (qh hull_dim+1) * qh hull_dim * sizeof(coordT));
00070 qh_memfree (qh gm_row, (qh hull_dim+1) * sizeof(coordT *));
00071 qh NEARzero= qh lower_threshold= qh upper_threshold= NULL;
00072 qh lower_bound= qh upper_bound= NULL;
00073 qh gm_matrix= NULL;
00074 qh gm_row= NULL;
00075 qh_setfree (&qh other_points);
00076 qh_setfree (&qh del_vertices);
00077 qh_setfree (&qh searchset);
00078 if (qh line)
00079 free (qh line);
00080 if (qh half_space)
00081 free (qh half_space);
00082 if (qh temp_malloc)
00083 free (qh temp_malloc);
00084 if (qh feasible_point)
00085 free (qh feasible_point);
00086 if (qh feasible_string)
00087 free (qh feasible_string);
00088 qh line= qh feasible_string= NULL;
00089 qh half_space= qh feasible_point= qh temp_malloc= NULL;
00090
00091 if (qh first_point && qh POINTSmalloc) {
00092 free(qh first_point);
00093 qh first_point= NULL;
00094 }
00095 if (qh input_points && qh input_malloc) {
00096 free (qh input_points);
00097 qh input_points= NULL;
00098 }
00099 trace5((qh ferr, "qh_freebuffers: finished\n"));
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 void qh_freebuild (boolT allmem) {
00125 facetT *facet;
00126 vertexT *vertex;
00127 ridgeT *ridge, **ridgep;
00128 mergeT *merge, **mergep;
00129
00130 trace1((qh ferr, "qh_freebuild: free memory from qh_inithull and qh_buildhull\n"));
00131 if (qh del_vertices)
00132 qh_settruncate (qh del_vertices, 0);
00133 if (allmem) {
00134 qh_clearcenters (qh_ASnone);
00135 while ((vertex= qh vertex_list)) {
00136 if (vertex->next)
00137 qh_delvertex (vertex);
00138 else {
00139 qh_memfree (vertex, sizeof(vertexT));
00140 qh newvertex_list= qh vertex_list= NULL;
00141 }
00142 }
00143 }else if (qh VERTEXneighbors) {
00144 FORALLvertices
00145 qh_setfreelong (&(vertex->neighbors));
00146 }
00147 qh VERTEXneighbors= False;
00148 qh GOODclosest= NULL;
00149 if (allmem) {
00150 FORALLfacets {
00151 FOREACHridge_(facet->ridges)
00152 ridge->seen= False;
00153 }
00154 FORALLfacets {
00155 if (facet->visible) {
00156 FOREACHridge_(facet->ridges) {
00157 if (!otherfacet_(ridge, facet)->visible)
00158 ridge->seen= True;
00159 }
00160 }
00161 }
00162 while ((facet= qh facet_list)) {
00163 FOREACHridge_(facet->ridges) {
00164 if (ridge->seen) {
00165 qh_setfree(&(ridge->vertices));
00166 qh_memfree(ridge, sizeof(ridgeT));
00167 }else
00168 ridge->seen= True;
00169 }
00170 qh_setfree (&(facet->outsideset));
00171 qh_setfree (&(facet->coplanarset));
00172 qh_setfree (&(facet->neighbors));
00173 qh_setfree (&(facet->ridges));
00174 qh_setfree (&(facet->vertices));
00175 if (facet->next)
00176 qh_delfacet (facet);
00177 else {
00178 qh_memfree (facet, sizeof(facetT));
00179 qh visible_list= qh newfacet_list= qh facet_list= NULL;
00180 }
00181 }
00182 }else {
00183 FORALLfacets {
00184 qh_setfreelong (&(facet->outsideset));
00185 qh_setfreelong (&(facet->coplanarset));
00186 if (!facet->simplicial) {
00187 qh_setfreelong (&(facet->neighbors));
00188 qh_setfreelong (&(facet->ridges));
00189 qh_setfreelong (&(facet->vertices));
00190 }
00191 }
00192 }
00193 qh_setfree (&(qh hash_table));
00194 qh_memfree (qh interior_point, qh normal_size);
00195 qh interior_point= NULL;
00196 FOREACHmerge_(qh facet_mergeset)
00197 qh_memfree (merge, sizeof(mergeT));
00198 qh facet_mergeset= NULL;
00199 qh degen_mergeset= NULL;
00200 qh_settempfree_all();
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 void qh_freeqhull (boolT allmem) {
00220
00221 trace1((qh ferr, "qh_freeqhull: free global memory\n"));
00222 qh NOerrexit= True;
00223 qh_freebuild (allmem);
00224 qh_freebuffers();
00225 qh_freestatistics();
00226 #if qh_QHpointer
00227 free (qh_qh);
00228 qh_qh= NULL;
00229 #endif
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250 void qh_init_A (FILE *infile, FILE *outfile, FILE *errfile, int argc, char *argv[]) {
00251 qh_meminit (errfile);
00252 qh_initqhull_start (infile, outfile, errfile);
00253 qh_init_qhull_command (argc, argv);
00254 }
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 void qh_init_B (coordT *points, int numpoints, int dim, boolT ismalloc) {
00298 qh_initqhull_globals (points, numpoints, dim, ismalloc);
00299 qh_initqhull_mem();
00300
00301 qh_initqhull_buffers();
00302 qh_initthresholds (qh qhull_command);
00303 if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay))
00304 qh_projectinput();
00305 if (qh SCALEinput)
00306 qh_scaleinput();
00307 if (qh ROTATErandom >= 0) {
00308 qh_randommatrix (qh gm_matrix, qh hull_dim, qh gm_row);
00309 if (qh DELAUNAY) {
00310 int k, lastk= qh hull_dim-1;
00311 for (k= 0; k < lastk; k++) {
00312 qh gm_row[k][lastk]= 0.0;
00313 qh gm_row[lastk][k]= 0.0;
00314 }
00315 qh gm_row[lastk][lastk]= 1.0;
00316 }
00317 qh_gram_schmidt (qh hull_dim, qh gm_row);
00318 qh_rotateinput (qh gm_row);
00319 }
00320 }
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336 void qh_init_qhull_command(int argc, char *argv[]) {
00337 int i;
00338 char *s;
00339
00340 if (argc) {
00341 if ((s= strrchr( argv[0], '\\')))
00342 strcpy (qh qhull_command, s+1);
00343 else
00344 strcpy (qh qhull_command, argv[0]);
00345 if ((s= strstr (qh qhull_command, ".EXE"))
00346 || (s= strstr (qh qhull_command, ".exe")))
00347 *s= '\0';
00348 }
00349 for (i=1; i < argc; i++) {
00350 if (strlen (qh qhull_command) + strlen(argv[i]) + 1 < sizeof(qh qhull_command)) {
00351 strcat (qh qhull_command, " ");
00352 strcat (qh qhull_command, argv[i]);
00353 }else {
00354 fprintf (qh ferr, "qhull input error: more than %d characters in command line\n",
00355 (int)sizeof(qh qhull_command));
00356 exit (1);
00357 }
00358 }
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392 void qh_initflags(char *command) {
00393 int k, i, lastproject;
00394 char *s= command, *t, *prev_s, *start, key;
00395 boolT isgeom= False, wasproject;
00396 realT r;
00397
00398 if (command != &qh qhull_command[0]) {
00399 *qh qhull_command= '\0';
00400 strncat( qh qhull_command, command, sizeof( qh qhull_command));
00401 }
00402 while (*s && !isspace(*s))
00403 s++;
00404 while (*s) {
00405 while (*s && isspace(*s))
00406 s++;
00407 if (*s == '-')
00408 s++;
00409 if (!*s)
00410 break;
00411 prev_s= s;
00412 switch (*s++) {
00413 case 'd':
00414 qh_option ("delaunay", NULL, NULL);
00415 qh DELAUNAY= True;
00416 break;
00417 case 'f':
00418 qh_option ("facets", NULL, NULL);
00419 qh_appendprint (qh_PRINTfacets);
00420 break;
00421 case 'i':
00422 qh_option ("incidence", NULL, NULL);
00423 qh_appendprint (qh_PRINTincidences);
00424 break;
00425 case 'm':
00426 qh_option ("mathematica", NULL, NULL);
00427 qh_appendprint (qh_PRINTmathematica);
00428 break;
00429 case 'n':
00430 qh_option ("normals", NULL, NULL);
00431 qh_appendprint (qh_PRINTnormals);
00432 break;
00433 case 'o':
00434 qh_option ("offFile", NULL, NULL);
00435 qh_appendprint (qh_PRINToff);
00436 break;
00437 case 'p':
00438 qh_option ("points", NULL, NULL);
00439 qh_appendprint (qh_PRINTpoints);
00440 break;
00441 case 's':
00442 qh_option ("summary", NULL, NULL);
00443 qh PRINTsummary= True;
00444 break;
00445 case 'v':
00446 qh_option ("voronoi", NULL, NULL);
00447 qh VORONOI= True;
00448 qh DELAUNAY= True;
00449 break;
00450 case 'A':
00451 if (!isdigit(*s) && *s != '.' && *s != '-')
00452 fprintf(qh ferr, "qhull warning: no maximum cosine angle given for option 'An'. Ignored.\n");
00453 else {
00454 if (*s == '-') {
00455 qh premerge_cos= -qh_strtod (s, &s);
00456 qh_option ("Angle-premerge-", NULL, &qh premerge_cos);
00457 qh PREmerge= True;
00458 }else {
00459 qh postmerge_cos= qh_strtod (s, &s);
00460 qh_option ("Angle-postmerge", NULL, &qh postmerge_cos);
00461 qh POSTmerge= True;
00462 }
00463 qh MERGING= True;
00464 }
00465 break;
00466 case 'C':
00467 if (!isdigit(*s) && *s != '.' && *s != '-')
00468 fprintf(qh ferr, "qhull warning: no centrum radius given for option 'Cn'. Ignored.\n");
00469 else {
00470 if (*s == '-') {
00471 qh premerge_centrum= -qh_strtod (s, &s);
00472 qh_option ("Centrum-premerge-", NULL, &qh premerge_centrum);
00473 qh PREmerge= True;
00474 }else {
00475 qh postmerge_centrum= qh_strtod (s, &s);
00476 qh_option ("Centrum-postmerge", NULL, &qh postmerge_centrum);
00477 qh POSTmerge= True;
00478 }
00479 qh MERGING= True;
00480 }
00481 break;
00482 case 'E':
00483 if (*s == '-')
00484 fprintf(qh ferr, "qhull warning: negative maximum roundoff given for option 'An'. Ignored.\n");
00485 else if (!isdigit(*s))
00486 fprintf(qh ferr, "qhull warning: no maximum roundoff given for option 'En'. Ignored.\n");
00487 else {
00488 qh DISTround= qh_strtod (s, &s);
00489 qh_option ("Error-roundoff", NULL, &qh DISTround);
00490 qh SETroundoff= True;
00491 }
00492 break;
00493 case 'H':
00494 start= s;
00495 qh HALFspace= True;
00496 qh_strtod (s, &t);
00497 while (t > s) {
00498 if (*t && !isspace (*t)) {
00499 if (*t == ',')
00500 t++;
00501 else
00502 fprintf (qh ferr, "qhull warning: origin for Halfspace intersection should be 'Hn,n,n,...'\n");
00503 }
00504 s= t;
00505 qh_strtod (s, &t);
00506 }
00507 if (start < t) {
00508 if (!(qh feasible_string= (char*)calloc (t-start+1, 1))) {
00509 fprintf(qh ferr, "qhull error: insufficient memory for 'Hn,n,n'\n");
00510 qh_errexit(qh_ERRmem, NULL, NULL);
00511 }
00512 strncpy (qh feasible_string, start, t-start);
00513 qh_option ("Halfspace-about", NULL, NULL);
00514 qh_option (qh feasible_string, NULL, NULL);
00515 }else
00516 qh_option ("Halfspace", NULL, NULL);
00517 break;
00518 case 'R':
00519 if (!isdigit(*s))
00520 fprintf(qh ferr, "qhull warning: missing random perturbation for option 'Rn'. Ignored\n");
00521 else {
00522 qh RANDOMfactor= qh_strtod (s, &s);
00523 qh_option ("Random_perturb", NULL, &qh RANDOMfactor);
00524 qh RANDOMdist= True;
00525 }
00526 break;
00527 case 'V':
00528 if (!isdigit(*s) && *s != '-')
00529 fprintf(qh ferr, "qhull warning: missing visible distance for option 'Vn'. Ignored\n");
00530 else {
00531 qh MINvisible= qh_strtod (s, &s);
00532 qh_option ("Visible", NULL, &qh MINvisible);
00533 }
00534 break;
00535 case 'U':
00536 if (!isdigit(*s) && *s != '-')
00537 fprintf(qh ferr, "qhull warning: missing coplanar distance for option 'Un'. Ignored\n");
00538 else {
00539 qh MAXcoplanar= qh_strtod (s, &s);
00540 qh_option ("U-coplanar", NULL, &qh MAXcoplanar);
00541 }
00542 break;
00543 case 'W':
00544 if (*s == '-')
00545 fprintf(qh ferr, "qhull warning: negative outside width for option 'Wn'. Ignored.\n");
00546 else if (!isdigit(*s))
00547 fprintf(qh ferr, "qhull warning: missing outside width for option 'Wn'. Ignored\n");
00548 else {
00549 qh MINoutside= qh_strtod (s, &s);
00550 qh_option ("W-outside", NULL, &qh MINoutside);
00551 qh APPROXhull= True;
00552 }
00553 break;
00554
00555 case 'F':
00556 while (*s && !isspace(*s)) {
00557 switch(*s++) {
00558 case 'a':
00559 qh_option ("Farea", NULL, NULL);
00560 qh_appendprint (qh_PRINTarea);
00561 qh GETarea= True;
00562 break;
00563 case 'A':
00564 qh_option ("FArea-total", NULL, NULL);
00565 qh GETarea= True;
00566 break;
00567 case 'c':
00568 qh_option ("Fcoplanars", NULL, NULL);
00569 qh_appendprint (qh_PRINTcoplanars);
00570 break;
00571 case 'C':
00572 qh_option ("FCentrums", NULL, NULL);
00573 qh_appendprint (qh_PRINTcentrums);
00574 break;
00575 case 'd':
00576 qh_option ("Fd-cdd-in", NULL, NULL);
00577 qh CDDinput= True;
00578 break;
00579 case 'D':
00580 qh_option ("FD-cdd-out", NULL, NULL);
00581 qh CDDoutput= True;
00582 break;
00583 case 'F':
00584 qh_option ("FFacets-xridge", NULL, NULL);
00585 qh_appendprint (qh_PRINTfacets_xridge);
00586 break;
00587 case 'i':
00588 qh_option ("Finner", NULL, NULL);
00589 qh_appendprint (qh_PRINTinner);
00590 break;
00591 case 'I':
00592 qh_option ("FIds", NULL, NULL);
00593 qh_appendprint (qh_PRINTids);
00594 break;
00595 case 'm':
00596 qh_option ("Fmerges", NULL, NULL);
00597 qh_appendprint (qh_PRINTmerges);
00598 break;
00599 case 'n':
00600 qh_option ("Fneighbors", NULL, NULL);
00601 qh_appendprint (qh_PRINTneighbors);
00602 break;
00603 case 'N':
00604 qh_option ("FNeighbors-vertex", NULL, NULL);
00605 qh_appendprint (qh_PRINTvneighbors);
00606 break;
00607 case 'o':
00608 qh_option ("Fouter", NULL, NULL);
00609 qh_appendprint (qh_PRINTouter);
00610 break;
00611 case 'O':
00612 if (qh PRINToptions1st) {
00613 qh_option ("FOptions", NULL, NULL);
00614 qh_appendprint (qh_PRINToptions);
00615 }else
00616 qh PRINToptions1st= True;
00617 break;
00618 case 'p':
00619 qh_option ("Fpoint-intersect", NULL, NULL);
00620 qh_appendprint (qh_PRINTpointintersect);
00621 break;
00622 case 'P':
00623 qh_option ("FPoint-nearest", NULL, NULL);
00624 qh_appendprint (qh_PRINTpointnearest);
00625 break;
00626 case 'Q':
00627 qh_option ("FQhull", NULL, NULL);
00628 qh_appendprint (qh_PRINTqhull);
00629 break;
00630 case 's':
00631 qh_option ("Fsummary", NULL, NULL);
00632 qh_appendprint (qh_PRINTsummary);
00633 break;
00634 case 'S':
00635 qh_option ("FSize", NULL, NULL);
00636 qh_appendprint (qh_PRINTsize);
00637 qh GETarea= True;
00638 break;
00639 case 't':
00640 qh_option ("Ftriangles", NULL, NULL);
00641 qh_appendprint (qh_PRINTtriangles);
00642 break;
00643 case 'v':
00644
00645 qh_appendprint (qh_PRINTvertices);
00646 break;
00647 case 'V':
00648 qh_option ("FVertex-average", NULL, NULL);
00649 qh_appendprint (qh_PRINTaverage);
00650 break;
00651 case 'x':
00652 qh_option ("Fxtremes", NULL, NULL);
00653 qh_appendprint (qh_PRINTextremes);
00654 break;
00655 default:
00656 s--;
00657 fprintf (qh ferr, "qhull warning: unknown 'F' output option %c, rest ignored\n", (int)s[-1]);
00658 while (*++s && !isspace(*s));
00659 break;
00660 }
00661 }
00662 break;
00663 case 'G':
00664 isgeom= True;
00665 qh_appendprint (qh_PRINTgeom);
00666 while (*s && !isspace(*s)) {
00667 switch(*s++) {
00668 case 'a':
00669 qh_option ("Gall-points", NULL, NULL);
00670 qh PRINTdots= True;
00671 break;
00672 case 'c':
00673 qh_option ("Gcentrums", NULL, NULL);
00674 qh PRINTcentrums= True;
00675 break;
00676 case 'h':
00677 qh_option ("Gintersections", NULL, NULL);
00678 qh DOintersections= True;
00679 break;
00680 case 'i':
00681 qh_option ("Ginner", NULL, NULL);
00682 qh PRINTinner= True;
00683 break;
00684 case 'n':
00685 qh_option ("Gno-planes", NULL, NULL);
00686 qh PRINTnoplanes= True;
00687 break;
00688 case 'o':
00689 qh_option ("Gouter", NULL, NULL);
00690 qh PRINTouter= True;
00691 break;
00692 case 'p':
00693 qh_option ("Gpoints", NULL, NULL);
00694 qh PRINTcoplanar= True;
00695 break;
00696 case 'r':
00697 qh_option ("Gridges", NULL, NULL);
00698 qh PRINTridges= True;
00699 break;
00700 case 't':
00701 qh_option ("Gtransparent", NULL, NULL);
00702 qh PRINTtransparent= True;
00703 break;
00704 case 'v':
00705 qh_option ("Gvertices", NULL, NULL);
00706 qh PRINTspheres= True;
00707 break;
00708 case 'D':
00709 if (!isdigit (*s))
00710 fprintf (qh ferr, "qhull input error: missing dimension for option 'GDn'\n");
00711 else {
00712 if (qh DROPdim >= 0)
00713 fprintf (qh ferr, "qhull warning: can only drop one dimension. Previous 'GD%d' ignored\n",
00714 qh DROPdim);
00715 qh DROPdim= qh_strtol (s, &s);
00716 qh_option ("GDrop-dim", &qh DROPdim, NULL);
00717 }
00718 break;
00719 default:
00720 s--;
00721 fprintf (qh ferr, "qhull warning: unknown 'G' print option %c, rest ignored\n", (int)s[0]);
00722 while (*++s && !isspace(*s));
00723 break;
00724 }
00725 }
00726 break;
00727 case 'P':
00728 while (*s && !isspace(*s)) {
00729 switch(*s++) {
00730 case 'd': case 'D':
00731 key= s[-1];
00732 i= qh_strtol (s, &s);
00733 r= 0;
00734 if (*s == ':') {
00735 s++;
00736 r= qh_strtod (s, &s);
00737 }
00738 if (key == 'd')
00739 qh_option ("Pdrop-facets-dim-less", &i, &r);
00740 else
00741 qh_option ("PDrop-facets-dim-more", &i, &r);
00742 break;
00743 case 'g':
00744 qh_option ("Pgood-facets", NULL, NULL);
00745 qh PRINTgood= True;
00746 break;
00747 case 'G':
00748 qh_option ("PGood-facet-neighbors", NULL, NULL);
00749 qh PRINTneighbors= True;
00750 break;
00751 case 'o':
00752 qh_option ("Poutput-forced", NULL, NULL);
00753 qh FORCEoutput= True;
00754 break;
00755 case 'p':
00756 qh_option ("Pprecision-ignore", NULL, NULL);
00757 qh PRINTprecision= False;
00758 break;
00759 case 'A':
00760 if (!isdigit (*s))
00761 fprintf (qh ferr, "qhull input error: missing facet count for keep area option 'PAn'\n");
00762 else {
00763 qh KEEParea= qh_strtol (s, &s);
00764 qh_option ("PArea-keep", &qh KEEParea, NULL);
00765 qh GETarea= True;
00766 }
00767 break;
00768 case 'F':
00769 if (!isdigit (*s))
00770 fprintf (qh ferr, "qhull input error: missing facet area for option 'PFn'\n");
00771 else {
00772 qh KEEPminArea= qh_strtod (s, &s);
00773 qh_option ("PFacet-area-keep", NULL, &qh KEEPminArea);
00774 qh GETarea= True;
00775 }
00776 break;
00777 case 'M':
00778 if (!isdigit (*s))
00779 fprintf (qh ferr, "qhull input error: missing merge count for option 'PMn'\n");
00780 else {
00781 qh KEEPmerge= qh_strtol (s, &s);
00782 qh_option ("PMerge-keep", &qh KEEPmerge, NULL);
00783 }
00784 break;
00785 default:
00786 s--;
00787 fprintf (qh ferr, "qhull warning: unknown 'P' print option %c, rest ignored\n", (int)s[-1]);
00788 while (*++s && !isspace(*s));
00789 break;
00790 }
00791 }
00792 break;
00793 case 'Q':
00794 lastproject= -1;
00795 while (*s && !isspace(*s)) {
00796 switch(*s++) {
00797 case 'b': case 'B':
00798 key= s[-1];
00799 if (key == 'b' && *s == 'B') {
00800 s++;
00801 r= qh_DEFAULTbox;
00802 qh SCALEinput= True;
00803 qh_option ("QbBound-unit-box", NULL, &r);
00804 break;
00805 }
00806 if (key == 'b' && *s == 'b') {
00807 s++;
00808 qh SCALElast= True;
00809 qh_option ("Qbbound-last", NULL, NULL);
00810 break;
00811 }
00812 k= qh_strtol (s, &s);
00813 r= 0.0;
00814 wasproject= False;
00815 if (*s == ':') {
00816 s++;
00817 if ((r= qh_strtod(s, &s)) == 0.0) {
00818 t= s;
00819 while (*t && !isspace(*t)) {
00820 if (toupper(*t++) == 'B'
00821 && k == qh_strtol (t, &t)
00822 && *t++ == ':'
00823 && qh_strtod(t, &t) == 0.0) {
00824 qh PROJECTinput++;
00825 trace2((qh ferr, "qh_initflags: project dimension %d\n", k));
00826 qh_option ("Qb-project-dim", &k, NULL);
00827 wasproject= True;
00828 lastproject= k;
00829 break;
00830 }
00831 }
00832 }
00833 }
00834 if (!wasproject) {
00835 if (lastproject == k && r == 0.0)
00836 lastproject= -1;
00837 else if (key == 'b') {
00838 qh SCALEinput= True;
00839 if (r == 0.0)
00840 r= -qh_DEFAULTbox;
00841 qh_option ("Qbound-dim-low", &k, &r);
00842 }else {
00843 qh SCALEinput= True;
00844 if (r == 0.0)
00845 r= qh_DEFAULTbox;
00846 qh_option ("QBound-dim-high", &k, &r);
00847 }
00848 }
00849 break;
00850 case 'c':
00851 qh_option ("Qcoplanar-keep", NULL, NULL);
00852 qh KEEPcoplanar= True;
00853 break;
00854 case 'f':
00855 qh_option ("Qfurthest-outside", NULL, NULL);
00856 qh BESToutside= True;
00857 break;
00858 case 'g':
00859 qh_option ("Qgood-facets-only", NULL, NULL);
00860 qh ONLYgood= True;
00861 break;
00862 case 'i':
00863 qh_option ("Qinterior-keep", NULL, NULL);
00864 qh KEEPinside= True;
00865 break;
00866 case 'm':
00867 qh_option ("Qmax-outside-only", NULL, NULL);
00868 qh ONLYmax= True;
00869 break;
00870 case 'r':
00871 qh_option ("Qrandom-outside", NULL, NULL);
00872 qh RANDOMoutside= True;
00873 break;
00874 case 's':
00875 qh_option ("Qsearch-initial-simplex", NULL, NULL);
00876 qh ALLpoints= True;
00877 break;
00878 case 'u':
00879 qh_option ("QupperDelaunay", NULL, NULL);
00880 qh UPPERdelaunay= True;
00881 break;
00882 case 'v':
00883 qh_option ("Qvertex-neighbors-convex", NULL, NULL);
00884 qh TESTvneighbors= True;
00885 break;
00886 case 'x':
00887 qh_option ("Qxact-merge", NULL, NULL);
00888 qh MERGEexact= True;
00889 qh MERGING= True;
00890 break;
00891 case 'z':
00892 qh_option ("Qz-infinity-point", NULL, NULL);
00893 qh ATinfinity= True;
00894 break;
00895 case '0':
00896 qh_option ("Q0-no-premerge", NULL, NULL);
00897 qh NOpremerge= True;
00898 break;
00899 case '1':
00900 qh_option ("Q1-no-angle-sort", NULL, NULL);
00901 qh ANGLEmerge= False;
00902 goto LABELcheckdigit;
00903 break;
00904 case '2':
00905 qh_option ("Q2-no-merge-independent", NULL, NULL);
00906 qh MERGEindependent= False;
00907 goto LABELcheckdigit;
00908 break;
00909 case '3':
00910 qh_option ("Q3-no-merge-vertices", NULL, NULL);
00911 qh MERGEvertices= False;
00912 LABELcheckdigit:
00913 if (isdigit(*s))
00914 fprintf (qh ferr, "qhull warning: can not follow '1', '2', or '3' with a digit. '%c' skipped.\n",
00915 *s++);
00916 break;
00917 case '4':
00918 qh_option ("Q4-avoid-old-into-new", NULL, NULL);
00919 qh AVOIDold= True;
00920 break;
00921 case '5':
00922 qh_option ("Q5-no-check-outer", NULL, NULL);
00923 qh SKIPcheckmax= True;
00924 break;
00925 case '6':
00926 qh_option ("Q6-no-concave-merge", NULL, NULL);
00927 qh SKIPconvex= True;
00928 break;
00929 case '7':
00930 qh_option ("Q7-no-breadth-first", NULL, NULL);
00931 qh VIRTUALmemory= True;
00932 break;
00933 case '8':
00934 qh_option ("Q8-no-near-inside", NULL, NULL);
00935 qh NOnearinside= True;
00936 break;
00937 case '9':
00938 qh_option ("Q9-pick-furthest", NULL, NULL);
00939 qh PICKfurthest= True;
00940 break;
00941 case 'G':
00942 i= qh_strtol (s, &t);
00943 if (qh GOODpoint)
00944 fprintf (qh ferr, "qhull warning: good point already defined for option 'QGn'. Ignored\n");
00945 else if (s == t)
00946 fprintf (qh ferr, "qhull warning: missing good point id for option 'QGn'. Ignored\n");
00947 else if (i < 0 || *s == '-') {
00948 qh GOODpoint= i-1;
00949 qh_option ("QGood-if-dont-see-point", &i, NULL);
00950 }else {
00951 qh GOODpoint= i+1;
00952 qh_option ("QGood-if-see-point", &i, NULL);
00953 }
00954 s= t;
00955 break;
00956 case 'J':
00957 if (!isdigit(*s) && *s != '-')
00958 qh JOGGLEmax= 0.0;
00959 else {
00960 qh JOGGLEmax= (realT) qh_strtod (s, &s);
00961 qh_option ("QJoggle", NULL, &qh JOGGLEmax);
00962 }
00963 break;
00964 case 'R':
00965 if (!isdigit(*s) && *s != '-')
00966 fprintf (qh ferr, "qhull warning: missing random seed for option 'QRn'. Ignored\n");
00967 else {
00968 qh ROTATErandom= i= qh_strtol(s, &s);
00969 if (i > 0)
00970 qh_option ("QRotate-id", &i, NULL );
00971 else if (i < -1)
00972 qh_option ("QRandom-seed", &i, NULL );
00973 }
00974 break;
00975 case 'V':
00976 i= qh_strtol (s, &t);
00977 if (qh GOODvertex)
00978 fprintf (qh ferr, "qhull warning: good vertex already defined for option 'QVn'. Ignored\n");
00979 else if (s == t)
00980 fprintf (qh ferr, "qhull warning: no good point id given for option 'QVn'. Ignored\n");
00981 else if (i < 0) {
00982 qh GOODvertex= i - 1;
00983 qh_option ("QV-good-facets-not-point", &i, NULL);
00984 }else {
00985 qh_option ("QV-good-facets-point", &i, NULL);
00986 qh GOODvertex= i + 1;
00987 }
00988 s= t;
00989 break;
00990 default:
00991 fprintf (qh ferr, "qhull warning: unknown 'Q' qhull option %c, rest ignored\n", (int)s[-1]);
00992 while (*++s && !isspace(*s));
00993 break;
00994 }
00995 }
00996 break;
00997 case 'T':
00998 while (*s && !isspace(*s)) {
00999 if (isdigit(*s) || *s == '-')
01000 qh IStracing= qh_strtol(s, &s);
01001 else switch(*s++) {
01002 case 'c':
01003 qh_option ("Tcheck-frequently", NULL, NULL);
01004 qh CHECKfrequently= True;
01005 break;
01006 case 's':
01007 qh_option ("Tstatistics", NULL, NULL);
01008 qh PRINTstatistics= True;
01009 break;
01010 case 'v':
01011 qh_option ("Tverify", NULL, NULL);
01012 qh VERIFYoutput= True;
01013 break;
01014 case 'z':
01015 qh_option ("Tz-stdout", NULL, NULL);
01016 qh ferr= qh fout;
01017 qhmem.ferr= qh fout;
01018 break;
01019 case 'C':
01020 if (!isdigit(*s))
01021 fprintf (qh ferr, "qhull warning: missing point id for cone for trace option 'TCn'. Ignored\n");
01022 else {
01023 i= qh_strtol (s, &s);
01024 qh_option ("TCone-stop", &i, NULL);
01025 qh STOPcone= i + 1;
01026 }
01027 break;
01028 case 'F':
01029 if (!isdigit(*s))
01030 fprintf (qh ferr, "qhull warning: missing frequency count for trace option 'TFn'. Ignored\n");
01031 else {
01032 qh REPORTfreq= qh_strtol (s, &s);
01033 qh_option ("TFacet-log", &qh REPORTfreq, NULL);
01034 qh REPORTfreq2= qh REPORTfreq/2;
01035 }
01036 break;
01037 case 'O':
01038 if (s[0] != ' ' || s[1] == '\"' || isspace (s[1])) {
01039 s++;
01040 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");
01041 }else {
01042 char filename[500], *t= filename;
01043 boolT isquote= False;
01044
01045 s++;
01046 if (*s == '\'') {
01047 isquote= True;
01048 s++;
01049 }
01050 while (*s) {
01051 if (t - filename >= sizeof (filename)-2) {
01052 fprintf (qh ferr, "qhull error: filename for 'TO' too long.\n");
01053 qh_errexit (qh_ERRinput, NULL, NULL);
01054 }
01055 if (isquote) {
01056 if (*s == '\'') {
01057 s++;
01058 isquote= False;
01059 break;
01060 }
01061 }else if (isspace (*s))
01062 break;
01063 *(t++)= *s++;
01064 }
01065 *t= '\0';
01066 if (isquote)
01067 fprintf (qh ferr, "qhull error: missing end quote for option 'TO'. Rest of line ignored.\n");
01068 else if (!freopen (filename, "w", stdout)) {
01069 fprintf (qh ferr, "qhull error: could not open file \"%s\".", filename);
01070 qh_errexit (qh_ERRinput, NULL, NULL);
01071 }else {
01072 qh_option ("TOutput-file", NULL, NULL);
01073 qh_option (filename, NULL, NULL);
01074 }
01075 }
01076 break;
01077 case 'P':
01078 if (!isdigit(*s))
01079 fprintf (qh ferr, "qhull warning: missing point id for trace option 'TPn'. Ignored\n");
01080 else {
01081 qh TRACEpoint= qh_strtol (s, &s);
01082 qh_option ("Trace-point", &qh TRACEpoint, NULL);
01083 }
01084 break;
01085 case 'M':
01086 if (!isdigit(*s))
01087 fprintf (qh ferr, "qhull warning: missing merge id for trace option 'TMn'. Ignored\n");
01088 else {
01089 qh TRACEmerge= qh_strtol (s, &s);
01090 qh_option ("Trace-merge", &qh TRACEmerge, NULL);
01091 }
01092 break;
01093 case 'R':
01094 if (!isdigit(*s))
01095 fprintf (qh ferr, "qhull warning: missing rerun count for trace option 'TRn'. Ignored\n");
01096 else {
01097 qh RERUN= qh_strtol (s, &s);
01098 qh_option ("TRerun", &qh RERUN, NULL);
01099 }
01100 break;
01101 case 'V':
01102 i= qh_strtol (s, &t);
01103 if (s == t)
01104 fprintf (qh ferr, "qhull warning: missing furthest point id for trace option 'TVn'. Ignored\n");
01105 else if (i < 0) {
01106 qh STOPpoint= i - 1;
01107 qh_option ("TV-stop-before-point", &i, NULL);
01108 }else {
01109 qh STOPpoint= i + 1;
01110 qh_option ("TV-stop-after-point", &i, NULL);
01111 }
01112 s= t;
01113 break;
01114 case 'W':
01115 if (!isdigit(*s))
01116 fprintf (qh ferr, "qhull warning: missing max width for trace option 'TWn'. Ignored\n");
01117 else {
01118 qh TRACEdist= (realT) qh_strtod (s, &s);
01119 qh_option ("TWide-trace", NULL, &qh TRACEdist);
01120 }
01121 break;
01122 default:
01123 fprintf (qh ferr, "qhull warning: unknown 'T' trace option %c, rest ignored\n", (int)s[-1]);
01124 while (*++s && !isspace(*s));
01125 break;
01126 }
01127 }
01128 break;
01129 default:
01130 fprintf (qh ferr, "qhull warning: unknown flag %c (%x)\n", (int)s[-1],
01131 (int)s[-1]);
01132 break;
01133 }
01134 if (s-1 == prev_s && *s && !isspace(*s)) {
01135 fprintf (qh ferr, "qhull warning: missing space after flag %c (%x); reserved for menu. Skipped.\n",
01136 (int)*prev_s, (int)*prev_s);
01137 while (*s && !isspace(*s))
01138 s++;
01139 }
01140 }
01141 if (isgeom && !qh FORCEoutput && qh PRINTout[1])
01142 fprintf (qh ferr, "qhull warning: additional output formats are not compatible with Geomview\n");
01143
01144 }
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 void qh_initqhull_buffers (void) {
01157 int k;
01158
01159 qh TEMPsize= (qhmem.LASTsize - sizeof (setT))/SETelemsize;
01160 if (qh TEMPsize <= 0 || qh TEMPsize > qhmem.LASTsize)
01161 qh TEMPsize= 8;
01162 qh other_points= qh_setnew (qh TEMPsize);
01163 qh del_vertices= qh_setnew (qh TEMPsize);
01164 qh searchset= qh_setnew (qh TEMPsize);
01165 qh NEARzero= (realT *)qh_memalloc(qh hull_dim * sizeof(realT));
01166 qh lower_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
01167 qh upper_threshold= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
01168 qh lower_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
01169 qh upper_bound= (realT *)qh_memalloc((qh input_dim+1) * sizeof(realT));
01170 for(k= qh input_dim+1; k--; ) {
01171 qh lower_threshold[k]= -REALmax;
01172 qh upper_threshold[k]= REALmax;
01173 qh lower_bound[k]= -REALmax;
01174 qh upper_bound[k]= REALmax;
01175 }
01176 qh gm_matrix= (coordT *)qh_memalloc((qh hull_dim+1) * qh hull_dim * sizeof(coordT));
01177 qh gm_row= (coordT **)qh_memalloc((qh hull_dim+1) * sizeof(coordT *));
01178 }
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 void qh_initqhull_globals (coordT *points, int numpoints, int dim, boolT ismalloc) {
01212 int seed, pointsneeded, extra= 0, i, randi, k;
01213 boolT printgeom= False, printmath= False, printcoplanar= False;
01214 realT randr;
01215 realT factorial;
01216
01217 time_t timedata;
01218
01219 trace0((qh ferr, "qh_initqhull_globals: for %s | %s\n", qh rbox_command,
01220 qh qhull_command));
01221 qh POINTSmalloc= ismalloc;
01222 qh first_point= points;
01223 qh num_points= numpoints;
01224 qh hull_dim= qh input_dim= dim;
01225 if (!qh NOpremerge && !qh MERGEexact && !qh PREmerge && qh JOGGLEmax > REALmax/2) {
01226 qh MERGING= True;
01227 if (qh hull_dim <= 4) {
01228 qh PREmerge= True;
01229 qh_option ("_pre-merge", NULL, NULL);
01230 }else {
01231 qh MERGEexact= True;
01232 qh_option ("_merge-exact", NULL, NULL);
01233 }
01234 }
01235 if (!qh NOpremerge && qh JOGGLEmax > REALmax/2) {
01236 #ifdef qh_NOmerge
01237 qh JOGGLEmax= 0.0;
01238 #endif
01239 }
01240 if (qh JOGGLEmax < REALmax/2 && qh DELAUNAY && !qh SCALEinput && !qh SCALElast) {
01241 qh SCALElast= True;
01242 qh_option ("Qbbound-last-qj", NULL, NULL);
01243 }
01244 if (qh MERGING && !qh POSTmerge && qh premerge_cos > REALmax/2
01245 && qh premerge_centrum == 0) {
01246 qh ZEROcentrum= True;
01247 qh ZEROall_ok= True;
01248 qh_option ("_zero-centrum", NULL, NULL);
01249 }
01250 if (qh JOGGLEmax < REALmax/2 && REALepsilon > 2e-8 && qh PRINTprecision)
01251 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",
01252 REALepsilon);
01253 #ifdef qh_NOmerge
01254 if (qh MERGING) {
01255 fprintf (qh ferr, "qhull input error: merging not installed (qh_NOmerge + 'Qx', 'Cn' or 'An')\n");
01256 qh_errexit (qh_ERRinput, NULL, NULL);
01257 }
01258 #endif
01259 if ((qh KEEParea || qh KEEPminArea < REALmax/2 || qh KEEPmerge || qh DELAUNAY)
01260 && !(qh PRINTgood || qh PRINTneighbors)) {
01261 qh PRINTgood= True;
01262 qh_option ("Pgood", NULL, NULL);
01263 }
01264 if (qh DELAUNAY && qh KEEPcoplanar && !qh KEEPinside) {
01265 qh KEEPinside= True;
01266 qh_option ("Qinterior-keep", NULL, NULL);
01267 }
01268 if (qh DELAUNAY && qh HALFspace) {
01269 fprintf (qh ferr, "qhull input error: can not use Delaunay ('d') or Voronoi ('v') with halfspace intersection ('H')\n");
01270 qh_errexit (qh_ERRinput, NULL, NULL);
01271 }
01272 if (!qh DELAUNAY && (qh UPPERdelaunay || qh ATinfinity)) {
01273 fprintf (qh ferr, "qhull input error: use upper-Delaunay ('Qu') or infinity-point ('Qz') with Delaunay ('d') or Voronoi ('v')\n");
01274 qh_errexit (qh_ERRinput, NULL, NULL);
01275 }
01276 if (qh UPPERdelaunay && qh ATinfinity) {
01277 fprintf (qh ferr, "qhull input error: can not use infinity-point ('Qz') with upper-Delaunay ('Qu')\n");
01278 qh_errexit (qh_ERRinput, NULL, NULL);
01279 }
01280 if (qh SCALElast && !qh DELAUNAY)
01281 fprintf (qh ferr, "qhull input warning: option 'Qbb' (scale-last-coordinate) is normally used with 'd' or 'v'\n");
01282 qh DOcheckmax= (!qh FORCEoutput && !qh SKIPcheckmax && qh MERGING );
01283 qh KEEPnearinside= (qh DOcheckmax && !(qh KEEPinside && qh KEEPcoplanar)
01284 && !qh NOnearinside);
01285 if (qh MERGING)
01286 qh CENTERtype= qh_AScentrum;
01287 else if (qh VORONOI)
01288 qh CENTERtype= qh_ASvoronoi;
01289 if (qh TESTvneighbors && !qh MERGING) {
01290 fprintf(qh ferr, "qhull input error: test vertex neighbors ('Qv') needs a merge option\n");
01291 qh_errexit (qh_ERRinput, NULL ,NULL);
01292 }
01293 if (qh PROJECTinput || (qh DELAUNAY && qh PROJECTdelaunay)) {
01294 qh hull_dim -= qh PROJECTinput;
01295 if (qh DELAUNAY) {
01296 qh hull_dim++;
01297 extra= 1;
01298 }
01299 }
01300 if (qh hull_dim <= 1) {
01301 fprintf(qh ferr, "qhull error: dimension %d must be > 1\n", qh hull_dim);
01302 qh_errexit (qh_ERRinput, NULL, NULL);
01303 }
01304 for (k= 2, factorial=1.0; k < qh hull_dim; k++)
01305 factorial *= k;
01306 qh AREAfactor= 1.0 / factorial;
01307 trace2((qh ferr, "qh_initqhull_globals: initialize globals. dim %d numpoints %d malloc? %d projected %d to hull_dim %d\n",
01308 dim, numpoints, ismalloc, qh PROJECTinput, qh hull_dim));
01309 qh normal_size= qh hull_dim * sizeof(coordT);
01310 qh center_size= qh normal_size - sizeof(coordT);
01311 pointsneeded= qh hull_dim+1;
01312 if (qh hull_dim > qh_DIMmergeVertex) {
01313 qh MERGEvertices= False;
01314 qh_option ("Q3-no-merge-vertices-dim-high", NULL, NULL);
01315 }
01316 if (qh GOODpoint)
01317 pointsneeded++;
01318 #ifdef qh_NOtrace
01319 if (qh IStracing) {
01320 fprintf (qh ferr, "qhull input error: tracing is not installed (qh_NOtrace in user.h)");
01321 qh_errexit (qh_ERRqhull, NULL, NULL);
01322 }
01323 #endif
01324 if (qh RERUN > 1) {
01325 qh TRACElastrun= qh IStracing;
01326 if (qh IStracing != -1)
01327 qh IStracing= 0;
01328 }else if (qh TRACEpoint != -1 || qh TRACEdist < REALmax/2 || qh TRACEmerge) {
01329 qh TRACElevel= (qh IStracing? qh IStracing : 3);
01330 qh IStracing= 0;
01331 }
01332 if (qh ROTATErandom == 0 || qh ROTATErandom == -1) {
01333 seed= time (&timedata);
01334 if (qh ROTATErandom == -1) {
01335 seed= -seed;
01336 qh_option ("QRandom-seed", &seed, NULL );
01337 }else
01338 qh_option ("QRotate-random", &seed, NULL);
01339 qh ROTATErandom= seed;
01340 }
01341 seed= qh ROTATErandom;
01342 if (seed == INT_MIN)
01343 seed= 1;
01344 else if (seed < 0)
01345 seed= -seed;
01346 qh_RANDOMseed_(seed);
01347 randr= 0.0;
01348 for (i= 1000; i--; ) {
01349 randi= qh_RANDOMint;
01350 randr += randi;
01351 if (randi > qh_RANDOMmax) {
01352 fprintf (qh ferr, "\
01353 qhull configuration error (qh_RANDOMmax in user.h):\n\
01354 random integer %d > qh_RANDOMmax (%.8g)\n",
01355 randi, qh_RANDOMmax);
01356 qh_errexit (qh_ERRinput, NULL, NULL);
01357 }
01358 }
01359 qh_RANDOMseed_(seed);
01360 if (randr/1000 < qh_RANDOMmax/10)
01361 fprintf (qh ferr, "\
01362 qhull configuration warning (qh_RANDOMmax in user.h):\n\
01363 average of 1000 randoms %.2g much less than expected (%.2g).\n\
01364 Is qh_RANDOMmax wrong?\n",
01365 randr/1000, qh_RANDOMmax/2);
01366 qh RANDOMa= 2.0 * qh RANDOMfactor/qh_RANDOMmax;
01367 qh RANDOMb= 1.0 - qh RANDOMfactor;
01368 if (qh_HASHfactor < 1.1) {
01369 fprintf(qh ferr, "qhull internal error (qh_initqhull_globals): qh_HASHfactor %d must be at least 1.1. Qhull uses linear hash probing\n",
01370 qh_HASHfactor);
01371 qh_errexit (qh_ERRqhull, NULL, NULL);
01372 }
01373 if (numpoints+extra < pointsneeded) {
01374 fprintf(qh ferr,"qhull input error: not enough points (%d) to construct initial simplex (need %d)\n",
01375 numpoints, pointsneeded);
01376 qh_errexit(qh_ERRinput, NULL, NULL);
01377 }
01378 if (qh PRINTtransparent) {
01379 if (qh hull_dim != 4 || !qh DELAUNAY || qh VORONOI || qh DROPdim >= 0) {
01380 fprintf(qh ferr,"qhull input error: transparent Delaunay ('Gt') needs 3-d Delaunay ('d') w/o 'GDn'\n");
01381 qh_errexit(qh_ERRinput, NULL, NULL);
01382 }
01383 qh DROPdim = 3;
01384 qh PRINTridges = True;
01385 }
01386 for (i= qh_PRINTEND; i--; ) {
01387 if (qh PRINTout[i] == qh_PRINTgeom)
01388 printgeom= True;
01389 else if (qh PRINTout[i] == qh_PRINTmathematica)
01390 printmath= True;
01391 else if (qh PRINTout[i] == qh_PRINTcoplanars)
01392 printcoplanar= True;
01393 else if (qh PRINTout[i] == qh_PRINTpointnearest)
01394 printcoplanar= True;
01395 else if (qh PRINTout[i] == qh_PRINTpointintersect && !qh HALFspace) {
01396 fprintf (qh ferr, "qhull input error: option 'Fp' is only used for \nhalfspace intersection ('Hn,n,n').\n");
01397 qh_errexit (qh_ERRinput, NULL, NULL);
01398 }else if (qh PRINTout[i] == qh_PRINTtriangles
01399 && (qh HALFspace || qh VORONOI)) {
01400 fprintf (qh ferr, "qhull input error: option 'Ft' is not available for Voronoi vertices or halfspace intersection\n");
01401 qh_errexit (qh_ERRinput, NULL, NULL);
01402 }else if (qh PRINTout[i] == qh_PRINTcentrums && qh VORONOI) {
01403 fprintf (qh ferr, "qhull input error: option 'Fc' is not available for Voronoi vertices ('v')\n");
01404 qh_errexit (qh_ERRinput, NULL, NULL);
01405 }else if (qh PRINTout[i] == qh_PRINTvertices) {
01406 if (qh VORONOI)
01407 qh_option ("Fvoronoi", NULL, NULL);
01408 else
01409 qh_option ("Fvertices", NULL, NULL);
01410 }
01411 }
01412 if (!qh KEEPcoplanar && !qh KEEPinside && !qh ONLYgood) {
01413 if ((qh PRINTcoplanar && qh PRINTspheres) || printcoplanar)
01414 fprintf (qh ferr, "qhull input warning: options 'Fc', 'FP', and 'Gp' need option 'Qc' or 'Qi' to record coplanar/inside points\n");
01415 }
01416 if (printmath && (qh hull_dim > 3 || qh VORONOI || qh HALFspace)) {
01417 fprintf (qh ferr, "qhull input error: Mathematica output is only available for 2-d and 3-d convex hulls and Delaunay triangulations\n");
01418 qh_errexit (qh_ERRinput, NULL, NULL);
01419 }
01420 if (printgeom) {
01421 if (qh hull_dim > 4) {
01422 fprintf (qh ferr, "qhull input error: Geomview output is only available for 2-d, 3-d and 4-d\n");
01423 qh_errexit (qh_ERRinput, NULL, NULL);
01424 }
01425 if (qh PRINTnoplanes && !(qh PRINTcoplanar + qh PRINTcentrums
01426 + qh PRINTdots + qh PRINTspheres + qh DOintersections + qh PRINTridges)) {
01427 fprintf (qh ferr, "qhull input error: no output specified for Geomview\n");
01428 qh_errexit (qh_ERRinput, NULL, NULL);
01429 }
01430 if (qh VORONOI && (qh hull_dim > 3 || qh DROPdim >= 0)) {
01431 fprintf (qh ferr, "qhull input error: Geomview output for Voronoi diagrams only for 2-d\n");
01432 qh_errexit (qh_ERRinput, NULL, NULL);
01433 }
01434
01435 if (qh hull_dim == 4 && qh DROPdim == -1 &&
01436 (qh PRINTcoplanar || qh PRINTspheres || qh PRINTcentrums)) {
01437 fprintf (qh ferr, "qhull input warning: coplanars, vertices, and centrums output not\n\
01438 available for 4-d output (ignored). Could use 'GDn' instead.\n");
01439 qh PRINTcoplanar= qh PRINTspheres= qh PRINTcentrums= False;
01440 }
01441 }
01442 qh PRINTdim= qh hull_dim;
01443 if (qh DROPdim >=0) {
01444 if (qh DROPdim < qh hull_dim) {
01445 qh PRINTdim--;
01446 if (!printgeom || qh hull_dim < 3)
01447 fprintf (qh ferr, "qhull input warning: drop dimension 'GD%d' is only available for 3-d/4-d Geomview\n", qh DROPdim);
01448 }else
01449 qh DROPdim= -1;
01450 }else if (qh VORONOI) {
01451 qh DROPdim= qh hull_dim-1;
01452 qh PRINTdim= qh hull_dim-1;
01453 }
01454 }
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474 void qh_initqhull_mem (void) {
01475 int numsizes;
01476 int i;
01477
01478 numsizes= 8+10;
01479 qh_meminitbuffers (qh IStracing, qh_MEMalign, numsizes,
01480 qh_MEMbufsize,qh_MEMinitbuf);
01481 qh_memsize(sizeof(vertexT));
01482 if (qh MERGING) {
01483 qh_memsize(sizeof(ridgeT));
01484 qh_memsize(sizeof(mergeT));
01485 }
01486 qh_memsize(sizeof(facetT));
01487 qh_memsize(sizeof(hashentryT));
01488 i= sizeof(setT) + (qh hull_dim - 1) * SETelemsize;
01489 qh_memsize(i);
01490 qh_memsize(qh normal_size);
01491 i += SETelemsize;
01492 qh_memsize(i);
01493 qh_user_memsizes();
01494 qh_memsetup();
01495 }
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507 void qh_initqhull_start (FILE *infile, FILE *outfile, FILE *errfile) {
01508
01509 qh_CPUclock;
01510 #if qh_QHpointer
01511 if (!(qh_qh= (qhT *)malloc (sizeof(qhT)))) {
01512 fprintf (errfile, "qhull error (qh_initqhull_globals): insufficient memory\n");
01513 exit (qh_ERRmem);
01514 }
01515 memset((char *)qh_qh, 0, sizeof(qhT));
01516 #else
01517 memset((char *)&qh_qh, 0, sizeof(qhT));
01518 #endif
01519 strcat (qh qhull, "qhull");
01520 qh_initstatistics();
01521 qh ANGLEmerge= True;
01522 qh DROPdim= -1;
01523 qh ferr= errfile;
01524 qh fin= infile;
01525 qh fout= outfile;
01526 qh furthest_id= -1;
01527 qh JOGGLEmax= REALmax;
01528 qh KEEPminArea = REALmax;
01529 qh last_low= REALmax;
01530 qh last_high= REALmax;
01531 qh last_newhigh= REALmax;
01532 qh max_outside= 0.0;
01533 qh max_vertex= 0.0;
01534 qh MAXabs_coord= 0.0;
01535 qh MAXsumcoord= 0.0;
01536 qh MAXwidth= -REALmax;
01537 qh MERGEindependent= True;
01538 qh MINdenom_1= 0.0;
01539 qh MINoutside= 0.0;
01540 qh MINvisible= REALmax;
01541 qh MAXcoplanar= REALmax;
01542 qh outside_err= REALmax;
01543 qh premerge_centrum= 0.0;
01544 qh premerge_cos= REALmax;
01545 qh PRINTprecision= True;
01546 qh PRINTradius= 0.0;
01547 qh postmerge_cos= REALmax;
01548 qh postmerge_centrum= 0.0;
01549 qh rand_seed= 1;
01550 qh ROTATErandom= INT_MIN;
01551 qh MERGEvertices= True;
01552 qh totarea= 0.0;
01553 qh totvol= 0.0;
01554 qh TRACEdist= REALmax;
01555 qh TRACEpoint= -1;
01556 qh tracefacet_id= UINT_MAX;
01557 qh tracevertex_id= UINT_MAX;
01558 }
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580 void qh_initthresholds(char *command) {
01581 realT value;
01582 int index, maxdim, k;
01583 char *s= command;
01584 char key;
01585
01586 maxdim= qh input_dim;
01587 if (qh DELAUNAY && (qh PROJECTdelaunay || qh PROJECTinput))
01588 maxdim++;
01589 while (*s) {
01590 if (*s == '-')
01591 s++;
01592 if (*s == 'P') {
01593 s++;
01594 while (*s && !isspace(key= *s++)) {
01595 if (key == 'd' || key == 'D') {
01596 if (!isdigit(*s)) {
01597 fprintf(qh ferr, "qhull warning: no dimension given for Print option '%c' at: %s. Ignored\n",
01598 key, s-1);
01599 continue;
01600 }
01601 index= qh_strtol (s, &s);
01602 if (index >= qh hull_dim) {
01603 fprintf(qh ferr, "qhull warning: dimension %d for Print option '%c' is >= %d. Ignored\n",
01604 index, key, qh hull_dim);
01605 continue;
01606 }
01607 if (*s == ':') {
01608 s++;
01609 value= qh_strtod(s, &s);
01610 if (fabs((double)value) > 1.0) {
01611 fprintf(qh ferr, "qhull warning: value %2.4g for Print option %c is > +1 or < -1. Ignored\n",
01612 value, key);
01613 continue;
01614 }
01615 }else
01616 value= 0.0;
01617 if (key == 'd')
01618 qh lower_threshold[index]= value;
01619 else
01620 qh upper_threshold[index]= value;
01621 }
01622 }
01623 }else if (*s == 'Q') {
01624 s++;
01625 while (*s && !isspace(key= *s++)) {
01626 if (key == 'b' && *s == 'B') {
01627 s++;
01628 for (k=maxdim; k--; ) {
01629 qh lower_bound[k]= -qh_DEFAULTbox;
01630 qh upper_bound[k]= qh_DEFAULTbox;
01631 }
01632 }else if (key == 'b' && *s == 'b')
01633 s++;
01634 else if (key == 'b' || key == 'B') {
01635 if (!isdigit(*s)) {
01636 fprintf(qh ferr, "qhull warning: no dimension given for Qhull option %c. Ignored\n",
01637 key);
01638 continue;
01639 }
01640 index= qh_strtol (s, &s);
01641 if (index >= maxdim) {
01642 fprintf(qh ferr, "qhull warning: dimension %d for Qhull option %c is >= %d. Ignored\n",
01643 index, key, maxdim);
01644 continue;
01645 }
01646 if (*s == ':') {
01647 s++;
01648 value= qh_strtod(s, &s);
01649 }else if (key == 'b')
01650 value= -qh_DEFAULTbox;
01651 else
01652 value= qh_DEFAULTbox;
01653 if (key == 'b')
01654 qh lower_bound[index]= value;
01655 else
01656 qh upper_bound[index]= value;
01657 }
01658 }
01659 }else {
01660 while (*s && !isspace (*s))
01661 s++;
01662 }
01663 while (isspace (*s))
01664 s++;
01665 }
01666 for (k= qh hull_dim; k--; ) {
01667 if (qh lower_threshold[k] > -REALmax/2) {
01668 qh GOODthreshold= True;
01669 if (qh upper_threshold[k] < REALmax/2) {
01670 qh SPLITthresholds= True;
01671 qh GOODthreshold= False;
01672 break;
01673 }
01674 }else if (qh upper_threshold[k] < REALmax/2)
01675 qh GOODthreshold= True;
01676 }
01677 }
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 void qh_option (char *option, int *i, realT *r) {
01690 char buf[200];
01691 int len, maxlen;
01692
01693 sprintf (buf, " %s", option);
01694 if (i)
01695 sprintf (buf+strlen(buf), " %d", *i);
01696 if (r)
01697 sprintf (buf+strlen(buf), " %2.2g", *r);
01698 len= strlen(buf);
01699 qh qhull_optionlen += len;
01700 maxlen= sizeof (qh qhull_options) - len -1;
01701 maximize_(maxlen, 0);
01702 if (qh qhull_optionlen >= 80 && maxlen > 0) {
01703 qh qhull_optionlen= len;
01704 strncat (qh qhull_options, "\n", maxlen--);
01705 }
01706 strncat (qh qhull_options, buf, maxlen);
01707 }
01708
01709 #if qh_QHpointer
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724 void qh_restore_qhull (qhT **oldqh) {
01725
01726 if (*oldqh && strcmp ((*oldqh)->qhull, "qhull")) {
01727 fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): %p is not a qhull data structure\n",
01728 *oldqh);
01729 qh_errexit (qh_ERRqhull, NULL, NULL);
01730 }
01731 if (qh_qh) {
01732 fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not save or free existing qhull\n");
01733 qh_errexit (qh_ERRqhull, NULL, NULL);
01734 }
01735 if (!*oldqh || !(*oldqh)->old_qhstat) {
01736 fprintf (qhmem.ferr, "qhull internal error (qh_restore_qhull): did not previously save qhull %p\n",
01737 *oldqh);
01738 qh_errexit (qh_ERRqhull, NULL, NULL);
01739 }
01740 qh_qh= *oldqh;
01741 *oldqh= NULL;
01742 qh_qhstat= qh old_qhstat;
01743 qhmem.tempstack= qh old_tempstack;
01744 trace1((qh ferr, "qh_restore_qhull: restored qhull from %p\n", *oldqh));
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763 qhT *qh_save_qhull (void) {
01764 qhT *oldqh;
01765
01766 if (!qh_qh) {
01767 fprintf (qhmem.ferr, "qhull internal error (qh_save_qhull): qhull not initialized\n");
01768 qh_errexit (qh_ERRqhull, NULL, NULL);
01769 }
01770 qh old_qhstat= qh_qhstat;
01771 qh_qhstat= NULL;
01772 qh old_tempstack= qhmem.tempstack;
01773 qhmem.tempstack= NULL;
01774 oldqh= qh_qh;
01775 qh_qh= NULL;
01776 trace1((qhmem.ferr, "qh_save_qhull: saved qhull %p\n", oldqh));
01777 return oldqh;
01778 }
01779
01780 #endif
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791 double qh_strtod (const char *s, char **endp) {
01792 double result;
01793
01794 result= strtod (s, endp);
01795 if (s < (*endp) && (*endp)[-1] == ' ')
01796 (*endp)--;
01797 return result;
01798 }
01799
01800 int qh_strtol (const char *s, char **endp) {
01801 int result;
01802
01803 result= (int) strtol (s, endp, 10);
01804 if (s< (*endp) && (*endp)[-1] == ' ')
01805 (*endp)--;
01806 return result;
01807 }