global_r.c 82 KB

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