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