rboxlib_r.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  1. /*<html><pre> -<a href="index_r.htm#TOC"
  2. >-------------------------------</a><a name="TOP">-</a>
  3. rboxlib_r.c
  4. Generate input points
  5. notes:
  6. For documentation, see prompt[] of rbox_r.c
  7. 50 points generated for 'rbox D4'
  8. WARNING:
  9. incorrect range if qh_RANDOMmax is defined wrong (user_r.h)
  10. */
  11. #include "libqhull_r.h" /* First for user_r.h */
  12. #include "random_r.h"
  13. #include <ctype.h>
  14. #include <limits.h>
  15. #include <math.h>
  16. #include <setjmp.h>
  17. #include <string.h>
  18. #include <time.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #ifdef _MSC_VER /* Microsoft Visual C++ */
  22. #pragma warning( disable : 4706) /* assignment within conditional expression. */
  23. #pragma warning( disable : 4996) /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
  24. #endif
  25. #define MAXdim 200
  26. #define PI 3.1415926535897932384
  27. /* ------------------------------ prototypes ----------------*/
  28. int qh_roundi(qhT *qh, double a);
  29. void qh_out1(qhT *qh, double a);
  30. void qh_out2n(qhT *qh, double a, double b);
  31. void qh_out3n(qhT *qh, double a, double b, double c);
  32. void qh_outcoord(qhT *qh, int iscdd, double *coord, int dim);
  33. void qh_outcoincident(qhT *qh, int coincidentpoints, double radius, int iscdd, double *coord, int dim);
  34. void qh_rboxpoints2(qhT *qh, char* rbox_command, double **simplex);
  35. void qh_fprintf_rbox(qhT *qh, FILE *fp, int msgcode, const char *fmt, ... );
  36. void qh_free(void *mem);
  37. void *qh_malloc(size_t size);
  38. int qh_rand(qhT *qh);
  39. void qh_srand(qhT *qh, int seed);
  40. /*-<a href="qh-qhull_r.htm#TOC"
  41. >-------------------------------</a><a name="rboxpoints">-</a>
  42. qh_rboxpoints(qh, rbox_command )
  43. Generate points to qh.fout according to rbox options
  44. Report errors on qh.ferr
  45. returns:
  46. 0 (qh_ERRnone) on success
  47. 1 (qh_ERRinput) on input error
  48. 4 (qh_ERRmem) on memory error
  49. 5 (qh_ERRqhull) on internal error
  50. notes:
  51. To avoid using stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user_r.c)
  52. Split out qh_rboxpoints2() to avoid -Wclobbered
  53. design:
  54. Straight line code (consider defining a struct and functions):
  55. Parse arguments into variables
  56. Determine the number of points
  57. Generate the points
  58. */
  59. int qh_rboxpoints(qhT *qh, char* rbox_command) {
  60. int exitcode;
  61. double *simplex;
  62. simplex= NULL;
  63. exitcode= setjmp(qh->rbox_errexit);
  64. if (exitcode) {
  65. /* same code for error exit and normal return. qh.NOerrexit is set */
  66. if (simplex)
  67. qh_free(simplex);
  68. return exitcode;
  69. }
  70. qh_rboxpoints2(qh, rbox_command, &simplex);
  71. /* same code for error exit and normal return */
  72. if (simplex)
  73. qh_free(simplex);
  74. return qh_ERRnone;
  75. } /* rboxpoints */
  76. void qh_rboxpoints2(qhT *qh, char* rbox_command, double **simplex) {
  77. int i,j,k;
  78. int gendim;
  79. int coincidentcount=0, coincidenttotal=0, coincidentpoints=0;
  80. int cubesize, diamondsize, seed=0, count, apex;
  81. int dim=3, numpoints=0, totpoints, addpoints=0;
  82. int issphere=0, isaxis=0, iscdd=0, islens=0, isregular=0, iswidth=0, addcube=0;
  83. int isgap=0, isspiral=0, NOcommand=0, adddiamond=0;
  84. int israndom=0, istime=0;
  85. int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
  86. double width=0.0, gap=0.0, radius=0.0, coincidentradius=0.0;
  87. double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
  88. double *coordp, *simplexp;
  89. int nthroot, mult[MAXdim];
  90. double norm, factor, randr, rangap, tempr, lensangle=0, lensbase=1;
  91. double anglediff, angle, x, y, cube=0.0, diamond=0.0;
  92. double box= qh_DEFAULTbox; /* scale all numbers before output */
  93. double randmax= qh_RANDOMmax;
  94. char command[250], seedbuf[50];
  95. char *s=command, *t, *first_point=NULL;
  96. time_t timedata;
  97. *command= '\0';
  98. strncat(command, rbox_command, sizeof(command)-sizeof(seedbuf)-strlen(command)-1);
  99. while (*s && !isspace(*s)) /* skip program name */
  100. s++;
  101. while (*s) {
  102. while (*s && isspace(*s))
  103. s++;
  104. if (*s == '-')
  105. s++;
  106. if (!*s)
  107. break;
  108. if (isdigit(*s)) {
  109. numpoints= qh_strtol(s, &s);
  110. continue;
  111. }
  112. /* ============= read flags =============== */
  113. switch (*s++) {
  114. case 'c':
  115. addcube= 1;
  116. t= s;
  117. while (isspace(*t))
  118. t++;
  119. if (*t == 'G')
  120. cube= qh_strtod(++t, &s);
  121. break;
  122. case 'd':
  123. adddiamond= 1;
  124. t= s;
  125. while (isspace(*t))
  126. t++;
  127. if (*t == 'G')
  128. diamond= qh_strtod(++t, &s);
  129. break;
  130. case 'h':
  131. iscdd= 1;
  132. break;
  133. case 'l':
  134. isspiral= 1;
  135. break;
  136. case 'n':
  137. NOcommand= 1;
  138. break;
  139. case 'r':
  140. isregular= 1;
  141. break;
  142. case 's':
  143. issphere= 1;
  144. break;
  145. case 't':
  146. istime= 1;
  147. if (isdigit(*s)) {
  148. seed= qh_strtol(s, &s);
  149. israndom= 0;
  150. }else
  151. israndom= 1;
  152. break;
  153. case 'x':
  154. issimplex= 1;
  155. break;
  156. case 'y':
  157. issimplex2= 1;
  158. break;
  159. case 'z':
  160. qh->rbox_isinteger= 1;
  161. break;
  162. case 'B':
  163. box= qh_strtod(s, &s);
  164. isbox= 1;
  165. break;
  166. case 'C':
  167. if (*s)
  168. coincidentpoints= qh_strtol(s, &s);
  169. if (*s == ',') {
  170. ++s;
  171. coincidentradius= qh_strtod(s, &s);
  172. }
  173. if (*s == ',') {
  174. ++s;
  175. coincidenttotal= qh_strtol(s, &s);
  176. }
  177. if (*s && !isspace(*s)) {
  178. qh_fprintf_rbox(qh, qh->ferr, 7080, "rbox error: arguments for 'Cn,r,m' are not 'int', 'float', and 'int'. Remaining string is '%s'\n", s);
  179. qh_errexit_rbox(qh, qh_ERRinput);
  180. }
  181. if (coincidentpoints==0){
  182. qh_fprintf_rbox(qh, qh->ferr, 6268, "rbox error: missing arguments for 'Cn,r,m' where n is the number of coincident points, r is the radius (default 0.0), and m is the number of points\n");
  183. qh_errexit_rbox(qh, qh_ERRinput);
  184. }
  185. if (coincidentpoints<0 || coincidenttotal<0 || coincidentradius<0.0){
  186. qh_fprintf_rbox(qh, qh->ferr, 6269, "rbox error: negative arguments for 'Cn,m,r' where n (%d) is the number of coincident points, m (%d) is the number of points, and r (%.2g) is the radius (default 0.0)\n", coincidentpoints, coincidenttotal, coincidentradius);
  187. qh_errexit_rbox(qh, qh_ERRinput);
  188. }
  189. break;
  190. case 'D':
  191. dim= qh_strtol(s, &s);
  192. if (dim < 1
  193. || dim > MAXdim) {
  194. qh_fprintf_rbox(qh, qh->ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)\n", dim, MAXdim);
  195. qh_errexit_rbox(qh, qh_ERRinput);
  196. }
  197. break;
  198. case 'G':
  199. if (isdigit(*s))
  200. gap= qh_strtod(s, &s);
  201. else
  202. gap= 0.5;
  203. isgap= 1;
  204. break;
  205. case 'L':
  206. if (isdigit(*s))
  207. radius= qh_strtod(s, &s);
  208. else
  209. radius= 10;
  210. islens= 1;
  211. break;
  212. case 'M':
  213. ismesh= 1;
  214. if (*s)
  215. meshn= qh_strtod(s, &s);
  216. if (*s == ',') {
  217. ++s;
  218. meshm= qh_strtod(s, &s);
  219. }else
  220. meshm= 0.0;
  221. if (*s == ',') {
  222. ++s;
  223. meshr= qh_strtod(s, &s);
  224. }else
  225. meshr= sqrt(meshn*meshn + meshm*meshm);
  226. if (*s && !isspace(*s)) {
  227. qh_fprintf_rbox(qh, qh->ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
  228. meshn= 3.0, meshm=4.0, meshr=5.0;
  229. }
  230. break;
  231. case 'O':
  232. qh->rbox_out_offset= qh_strtod(s, &s);
  233. break;
  234. case 'P':
  235. if (!first_point)
  236. first_point= s - 1;
  237. addpoints++;
  238. while (*s && !isspace(*s)) /* read points later */
  239. s++;
  240. break;
  241. case 'W':
  242. width= qh_strtod(s, &s);
  243. iswidth= 1;
  244. break;
  245. case 'Z':
  246. if (isdigit(*s))
  247. radius= qh_strtod(s, &s);
  248. else
  249. radius= 1.0;
  250. isaxis= 1;
  251. break;
  252. default:
  253. qh_fprintf_rbox(qh, qh->ferr, 6352, "rbox error: unknown flag at '%s'.\nExecute 'rbox' without arguments for documentation.\n", s - 1);
  254. qh_errexit_rbox(qh, qh_ERRinput);
  255. }
  256. if (*s && !isspace(*s)) {
  257. qh_fprintf_rbox(qh, qh->ferr, 6353, "rbox error: missing space between flags at %s.\n", s);
  258. qh_errexit_rbox(qh, qh_ERRinput);
  259. }
  260. }
  261. /* ============= defaults, constants, and sizes =============== */
  262. if (qh->rbox_isinteger && !isbox)
  263. box= qh_DEFAULTzbox;
  264. if (addcube) {
  265. tempr= floor(ldexp(1.0,dim)+0.5);
  266. cubesize= (int)tempr;
  267. if (cube == 0.0)
  268. cube= box;
  269. }else
  270. cubesize= 0;
  271. if (adddiamond) {
  272. diamondsize= 2*dim;
  273. if (diamond == 0.0)
  274. diamond= box;
  275. }else
  276. diamondsize= 0;
  277. if (islens) {
  278. if (isaxis) {
  279. qh_fprintf_rbox(qh, qh->ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
  280. qh_errexit_rbox(qh, qh_ERRinput);
  281. }
  282. if (radius <= 1.0) {
  283. qh_fprintf_rbox(qh, qh->ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
  284. radius);
  285. qh_errexit_rbox(qh, qh_ERRinput);
  286. }
  287. lensangle= asin(1.0/radius);
  288. lensbase= radius * cos(lensangle);
  289. }
  290. if (!numpoints) {
  291. if (issimplex2)
  292. ; /* ok */
  293. else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
  294. qh_fprintf_rbox(qh, qh->ferr, 6192, "rbox error: missing count\n");
  295. qh_errexit_rbox(qh, qh_ERRinput);
  296. }else if (adddiamond + addcube + addpoints)
  297. ; /* ok */
  298. else {
  299. numpoints= 50; /* ./rbox D4 is the test case */
  300. issphere= 1;
  301. }
  302. }
  303. if ((issimplex + islens + isspiral + ismesh > 1)
  304. || (issimplex + issphere + isspiral + ismesh > 1)) {
  305. qh_fprintf_rbox(qh, qh->ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
  306. qh_errexit_rbox(qh, qh_ERRinput);
  307. }
  308. if (coincidentpoints>0 && (numpoints == 0 || coincidenttotal > numpoints)) {
  309. qh_fprintf_rbox(qh, qh->ferr, 6270, "rbox error: 'Cn,r,m' requested n coincident points for each of m points. Either there is no points or m (%d) is greater than the number of points (%d).\n", coincidenttotal, numpoints);
  310. qh_errexit_rbox(qh, qh_ERRinput);
  311. }
  312. if (coincidentpoints > 0 && isregular) {
  313. qh_fprintf_rbox(qh, qh->ferr, 6423, "rbox error: 'Cn,r,m' is not implemented for regular points ('r')\n");
  314. qh_errexit_rbox(qh, qh_ERRinput);
  315. }
  316. if (coincidenttotal == 0)
  317. coincidenttotal= numpoints;
  318. /* ============= print header with total points =============== */
  319. if (issimplex || ismesh)
  320. totpoints= numpoints;
  321. else if (issimplex2)
  322. totpoints= numpoints+dim+1;
  323. else if (isregular) {
  324. totpoints= numpoints;
  325. if (dim == 2) {
  326. if (islens)
  327. totpoints += numpoints - 2;
  328. }else if (dim == 3) {
  329. if (islens)
  330. totpoints += 2 * numpoints;
  331. else if (isgap)
  332. totpoints += 1 + numpoints;
  333. else
  334. totpoints += 2;
  335. }
  336. }else
  337. totpoints= numpoints + isaxis;
  338. totpoints += cubesize + diamondsize + addpoints;
  339. totpoints += coincidentpoints*coincidenttotal;
  340. /* ============= seed randoms =============== */
  341. if (istime == 0) {
  342. for (s=command; *s; s++) {
  343. if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
  344. i= 'x';
  345. else
  346. i= *s;
  347. seed= 11*seed + i;
  348. }
  349. }else if (israndom) {
  350. seed= (int)time(&timedata);
  351. sprintf(seedbuf, " t%d", seed); /* appends an extra t, not worth removing */
  352. strncat(command, seedbuf, sizeof(command) - strlen(command) - 1);
  353. t= strstr(command, " t ");
  354. if (t)
  355. strcpy(t+1, t+3); /* remove " t " */
  356. } /* else, seed explicitly set to n */
  357. qh_RANDOMseed_(qh, seed);
  358. /* ============= print header =============== */
  359. if (iscdd)
  360. qh_fprintf_rbox(qh, qh->fout, 9391, "%s\nbegin\n %d %d %s\n",
  361. NOcommand ? "" : command,
  362. totpoints, dim+1,
  363. qh->rbox_isinteger ? "integer" : "real");
  364. else if (NOcommand)
  365. qh_fprintf_rbox(qh, qh->fout, 9392, "%d\n%d\n", dim, totpoints);
  366. else
  367. /* qh_fprintf_rbox special cases 9393 to append 'command' to the RboxPoints.comment() */
  368. qh_fprintf_rbox(qh, qh->fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
  369. /* ============= explicit points =============== */
  370. if ((s= first_point)) {
  371. while (s && *s) { /* 'P' */
  372. count= 0;
  373. if (iscdd)
  374. qh_out1(qh, 1.0);
  375. while (*++s) {
  376. qh_out1(qh, qh_strtod(s, &s));
  377. count++;
  378. if (isspace(*s) || !*s)
  379. break;
  380. if (*s != ',') {
  381. qh_fprintf_rbox(qh, qh->ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
  382. qh_errexit_rbox(qh, qh_ERRinput);
  383. }
  384. }
  385. if (count < dim) {
  386. for (k=dim-count; k--; )
  387. qh_out1(qh, 0.0);
  388. }else if (count > dim) {
  389. qh_fprintf_rbox(qh, qh->ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
  390. count, dim, s);
  391. qh_errexit_rbox(qh, qh_ERRinput);
  392. }
  393. qh_fprintf_rbox(qh, qh->fout, 9394, "\n");
  394. while ((s= strchr(s, 'P'))) {
  395. if (isspace(s[-1]))
  396. break;
  397. }
  398. }
  399. }
  400. /* ============= simplex distribution =============== */
  401. if (issimplex+issimplex2) {
  402. if (!(*simplex= (double *)qh_malloc( (size_t)(dim * (dim+1)) * sizeof(double)))) {
  403. qh_fprintf_rbox(qh, qh->ferr, 6196, "rbox error: insufficient memory for simplex\n");
  404. qh_errexit_rbox(qh, qh_ERRmem); /* qh_ERRmem */
  405. }
  406. simplexp= *simplex;
  407. if (isregular) {
  408. for (i=0; i<dim; i++) {
  409. for (k=0; k<dim; k++)
  410. *(simplexp++)= i==k ? 1.0 : 0.0;
  411. }
  412. for (k=0; k<dim; k++)
  413. *(simplexp++)= -1.0;
  414. }else {
  415. for (i=0; i<dim+1; i++) {
  416. for (k=0; k<dim; k++) {
  417. randr= qh_RANDOMint;
  418. *(simplexp++)= 2.0 * randr/randmax - 1.0;
  419. }
  420. }
  421. }
  422. if (issimplex2) {
  423. simplexp= *simplex;
  424. for (i=0; i<dim+1; i++) {
  425. if (iscdd)
  426. qh_out1(qh, 1.0);
  427. for (k=0; k<dim; k++)
  428. qh_out1(qh, *(simplexp++) * box);
  429. qh_fprintf_rbox(qh, qh->fout, 9395, "\n");
  430. }
  431. }
  432. for (j=0; j<numpoints; j++) {
  433. if (iswidth)
  434. apex= qh_RANDOMint % (dim+1);
  435. else
  436. apex= -1;
  437. for (k=0; k<dim; k++)
  438. coord[k]= 0.0;
  439. norm= 0.0;
  440. for (i=0; i<dim+1; i++) {
  441. randr= qh_RANDOMint;
  442. factor= randr/randmax;
  443. if (i == apex)
  444. factor *= width;
  445. norm += factor;
  446. for (k=0; k<dim; k++) {
  447. simplexp= *simplex + i*dim + k;
  448. coord[k] += factor * (*simplexp);
  449. }
  450. }
  451. for (k=0; k<dim; k++)
  452. coord[k] *= box/norm;
  453. qh_outcoord(qh, iscdd, coord, dim);
  454. if(coincidentcount++ < coincidenttotal)
  455. qh_outcoincident(qh, coincidentpoints, coincidentradius, iscdd, coord, dim);
  456. }
  457. isregular= 0; /* continue with isbox */
  458. numpoints= 0;
  459. }
  460. /* ============= mesh distribution =============== */
  461. if (ismesh) {
  462. nthroot= (int)(pow((double)numpoints, 1.0/dim) + 0.99999);
  463. for (k=dim; k--; )
  464. mult[k]= 0;
  465. for (i=0; i < numpoints; i++) {
  466. coordp= coord;
  467. for (k=0; k < dim; k++) {
  468. if (k == 0)
  469. *(coordp++)= mult[0] * meshn + mult[1] * (-meshm);
  470. else if (k == 1)
  471. *(coordp++)= mult[0] * meshm + mult[1] * meshn;
  472. else
  473. *(coordp++)= mult[k] * meshr;
  474. }
  475. qh_outcoord(qh, iscdd, coord, dim);
  476. if(coincidentcount++ < coincidenttotal)
  477. qh_outcoincident(qh, coincidentpoints, coincidentradius, iscdd, coord, dim);
  478. for (k=0; k < dim; k++) {
  479. if (++mult[k] < nthroot)
  480. break;
  481. mult[k]= 0;
  482. }
  483. }
  484. }
  485. /* ============= regular points for 's' =============== */
  486. else if (isregular && !islens) {
  487. if (dim != 2 && dim != 3) {
  488. qh_fprintf_rbox(qh, qh->ferr, 6197, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
  489. qh_errexit_rbox(qh, qh_ERRinput);
  490. }
  491. if (!isaxis || radius == 0.0) {
  492. isaxis= 1;
  493. radius= 1.0;
  494. }
  495. if (dim == 3) {
  496. if (iscdd)
  497. qh_out1(qh, 1.0);
  498. qh_out3n(qh, 0.0, 0.0, -box);
  499. if (!isgap) {
  500. if (iscdd)
  501. qh_out1(qh, 1.0);
  502. qh_out3n(qh, 0.0, 0.0, box);
  503. }
  504. }
  505. angle= 0.0;
  506. anglediff= 2.0 * PI/numpoints;
  507. for (i=0; i < numpoints; i++) {
  508. angle += anglediff;
  509. x= radius * cos(angle);
  510. y= radius * sin(angle);
  511. if (dim == 2) {
  512. if (iscdd)
  513. qh_out1(qh, 1.0);
  514. qh_out2n(qh, x*box, y*box);
  515. }else {
  516. norm= sqrt(1.0 + x*x + y*y);
  517. if (iscdd)
  518. qh_out1(qh, 1.0);
  519. qh_out3n(qh, box*x/norm, box*y/norm, box/norm);
  520. if (isgap) {
  521. x *= 1-gap;
  522. y *= 1-gap;
  523. norm= sqrt(1.0 + x*x + y*y);
  524. if (iscdd)
  525. qh_out1(qh, 1.0);
  526. qh_out3n(qh, box*x/norm, box*y/norm, box/norm);
  527. }
  528. }
  529. }
  530. }
  531. /* ============= regular points for 'r Ln D2' =============== */
  532. else if (isregular && islens && dim == 2) {
  533. double cos_0;
  534. angle= lensangle;
  535. anglediff= 2 * lensangle/(numpoints - 1);
  536. cos_0= cos(lensangle);
  537. for (i=0; i < numpoints; i++, angle -= anglediff) {
  538. x= radius * sin(angle);
  539. y= radius * (cos(angle) - cos_0);
  540. if (iscdd)
  541. qh_out1(qh, 1.0);
  542. qh_out2n(qh, x*box, y*box);
  543. if (i != 0 && i != numpoints - 1) {
  544. if (iscdd)
  545. qh_out1(qh, 1.0);
  546. qh_out2n(qh, x*box, -y*box);
  547. }
  548. }
  549. }
  550. /* ============= regular points for 'r Ln D3' =============== */
  551. else if (isregular && islens && dim != 2) {
  552. if (dim != 3) {
  553. qh_fprintf_rbox(qh, qh->ferr, 6198, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
  554. qh_errexit_rbox(qh, qh_ERRinput);
  555. }
  556. angle= 0.0;
  557. anglediff= 2* PI/numpoints;
  558. if (!isgap) {
  559. isgap= 1;
  560. gap= 0.5;
  561. }
  562. offset= sqrt(radius * radius - (1-gap)*(1-gap)) - lensbase;
  563. for (i=0; i < numpoints; i++, angle += anglediff) {
  564. x= cos(angle);
  565. y= sin(angle);
  566. if (iscdd)
  567. qh_out1(qh, 1.0);
  568. qh_out3n(qh, box*x, box*y, 0.0);
  569. x *= 1-gap;
  570. y *= 1-gap;
  571. if (iscdd)
  572. qh_out1(qh, 1.0);
  573. qh_out3n(qh, box*x, box*y, box * offset);
  574. if (iscdd)
  575. qh_out1(qh, 1.0);
  576. qh_out3n(qh, box*x, box*y, -box * offset);
  577. }
  578. }
  579. /* ============= apex of 'Zn' distribution + gendim =============== */
  580. else {
  581. if (isaxis) {
  582. gendim= dim-1;
  583. if (iscdd)
  584. qh_out1(qh, 1.0);
  585. for (j=0; j < gendim; j++)
  586. qh_out1(qh, 0.0);
  587. qh_out1(qh, -box);
  588. qh_fprintf_rbox(qh, qh->fout, 9398, "\n");
  589. }else if (islens)
  590. gendim= dim-1;
  591. else
  592. gendim= dim;
  593. /* ============= generate random point in unit cube =============== */
  594. for (i=0; i < numpoints; i++) {
  595. norm= 0.0;
  596. for (j=0; j < gendim; j++) {
  597. randr= qh_RANDOMint;
  598. coord[j]= 2.0 * randr/randmax - 1.0;
  599. norm += coord[j] * coord[j];
  600. }
  601. norm= sqrt(norm);
  602. /* ============= dim-1 point of 'Zn' distribution ========== */
  603. if (isaxis) {
  604. if (!isgap) {
  605. isgap= 1;
  606. gap= 1.0;
  607. }
  608. randr= qh_RANDOMint;
  609. rangap= 1.0 - gap * randr/randmax;
  610. factor= radius * rangap / norm;
  611. for (j=0; j<gendim; j++)
  612. coord[j]= factor * coord[j];
  613. /* ============= dim-1 point of 'Ln s' distribution =========== */
  614. }else if (islens && issphere) {
  615. if (!isgap) {
  616. isgap= 1;
  617. gap= 1.0;
  618. }
  619. randr= qh_RANDOMint;
  620. rangap= 1.0 - gap * randr/randmax;
  621. factor= rangap / norm;
  622. for (j=0; j<gendim; j++)
  623. coord[j]= factor * coord[j];
  624. /* ============= dim-1 point of 'Ln' distribution ========== */
  625. }else if (islens && !issphere) {
  626. if (!isgap) {
  627. isgap= 1;
  628. gap= 1.0;
  629. }
  630. j= qh_RANDOMint % gendim;
  631. if (coord[j] < 0)
  632. coord[j]= -1.0 - coord[j] * gap;
  633. else
  634. coord[j]= 1.0 - coord[j] * gap;
  635. /* ============= point of 'l' distribution =============== */
  636. }else if (isspiral) {
  637. if (dim != 3) {
  638. qh_fprintf_rbox(qh, qh->ferr, 6199, "rbox error: spiral distribution is available only in 3d\n\n");
  639. qh_errexit_rbox(qh, qh_ERRinput);
  640. }
  641. coord[0]= cos(2*PI*i/(numpoints - 1));
  642. coord[1]= sin(2*PI*i/(numpoints - 1));
  643. coord[2]= 2.0*(double)i/(double)(numpoints - 1) - 1.0;
  644. /* ============= point of 's' distribution =============== */
  645. }else if (issphere) {
  646. factor= 1.0/norm;
  647. if (iswidth) {
  648. randr= qh_RANDOMint;
  649. factor *= 1.0 - width * randr/randmax;
  650. }
  651. for (j=0; j<dim; j++)
  652. coord[j]= factor * coord[j];
  653. }
  654. /* ============= project 'Zn s' point in to sphere =============== */
  655. if (isaxis && issphere) {
  656. coord[dim-1]= 1.0;
  657. norm= 1.0;
  658. for (j=0; j<gendim; j++)
  659. norm += coord[j] * coord[j];
  660. norm= sqrt(norm);
  661. for (j=0; j<dim; j++)
  662. coord[j]= coord[j] / norm;
  663. if (iswidth) {
  664. randr= qh_RANDOMint;
  665. coord[dim-1] *= 1 - width * randr/randmax;
  666. }
  667. /* ============= project 'Zn' point onto cube =============== */
  668. }else if (isaxis && !issphere) { /* not very interesting */
  669. randr= qh_RANDOMint;
  670. coord[dim-1]= 2.0 * randr/randmax - 1.0;
  671. /* ============= project 'Ln' point out to sphere =============== */
  672. }else if (islens) {
  673. coord[dim-1]= lensbase;
  674. for (j=0, norm= 0; j<dim; j++)
  675. norm += coord[j] * coord[j];
  676. norm= sqrt(norm);
  677. for (j=0; j<dim; j++)
  678. coord[j]= coord[j] * radius/ norm;
  679. coord[dim-1] -= lensbase;
  680. if (iswidth) {
  681. randr= qh_RANDOMint;
  682. coord[dim-1] *= 1 - width * randr/randmax;
  683. }
  684. if (qh_RANDOMint > randmax/2)
  685. coord[dim-1]= -coord[dim-1];
  686. /* ============= project 'Wn' point toward boundary =============== */
  687. }else if (iswidth && !issphere) {
  688. j= qh_RANDOMint % gendim;
  689. if (coord[j] < 0)
  690. coord[j]= -1.0 - coord[j] * width;
  691. else
  692. coord[j]= 1.0 - coord[j] * width;
  693. }
  694. /* ============= scale point to box =============== */
  695. for (k=0; k<dim; k++)
  696. coord[k]= coord[k] * box;
  697. /* ============= write output =============== */
  698. qh_outcoord(qh, iscdd, coord, dim);
  699. if(coincidentcount++ < coincidenttotal)
  700. qh_outcoincident(qh, coincidentpoints, coincidentradius, iscdd, coord, dim);
  701. }
  702. }
  703. /* ============= write cube vertices =============== */
  704. if (addcube) {
  705. for (j=0; j<cubesize; j++) {
  706. if (iscdd)
  707. qh_out1(qh, 1.0);
  708. for (k=dim-1; k>=0; k--) {
  709. if (j & ( 1 << k))
  710. qh_out1(qh, cube);
  711. else
  712. qh_out1(qh, -cube);
  713. }
  714. qh_fprintf_rbox(qh, qh->fout, 9400, "\n");
  715. }
  716. }
  717. /* ============= write diamond vertices =============== */
  718. if (adddiamond) {
  719. for (j=0; j<diamondsize; j++) {
  720. if (iscdd)
  721. qh_out1(qh, 1.0);
  722. for (k=dim-1; k>=0; k--) {
  723. if (j/2 != k)
  724. qh_out1(qh, 0.0);
  725. else if (j & 0x1)
  726. qh_out1(qh, diamond);
  727. else
  728. qh_out1(qh, -diamond);
  729. }
  730. qh_fprintf_rbox(qh, qh->fout, 9401, "\n");
  731. }
  732. }
  733. if (iscdd)
  734. qh_fprintf_rbox(qh, qh->fout, 9402, "end\nhull\n");
  735. } /* rboxpoints2 */
  736. /*------------------------------------------------
  737. outxxx - output functions for qh_rboxpoints
  738. */
  739. int qh_roundi(qhT *qh, double a) {
  740. if (a < 0.0) {
  741. if (a - 0.5 < INT_MIN) {
  742. qh_fprintf_rbox(qh, qh->ferr, 6200, "rbox input error: negative coordinate %2.2g is too large. Reduce 'Bn'\n", a);
  743. qh_errexit_rbox(qh, qh_ERRinput);
  744. }
  745. return (int)(a - 0.5);
  746. }else {
  747. if (a + 0.5 > INT_MAX) {
  748. qh_fprintf_rbox(qh, qh->ferr, 6201, "rbox input error: coordinate %2.2g is too large. Reduce 'Bn'\n", a);
  749. qh_errexit_rbox(qh, qh_ERRinput);
  750. }
  751. return (int)(a + 0.5);
  752. }
  753. } /* qh_roundi */
  754. void qh_out1(qhT *qh, double a) {
  755. if (qh->rbox_isinteger)
  756. qh_fprintf_rbox(qh, qh->fout, 9403, "%d ", qh_roundi(qh, a+qh->rbox_out_offset));
  757. else
  758. qh_fprintf_rbox(qh, qh->fout, 9404, qh_REAL_1, a+qh->rbox_out_offset);
  759. } /* qh_out1 */
  760. void qh_out2n(qhT *qh, double a, double b) {
  761. if (qh->rbox_isinteger)
  762. qh_fprintf_rbox(qh, qh->fout, 9405, "%d %d\n", qh_roundi(qh, a+qh->rbox_out_offset), qh_roundi(qh, b+qh->rbox_out_offset));
  763. else
  764. qh_fprintf_rbox(qh, qh->fout, 9406, qh_REAL_2n, a+qh->rbox_out_offset, b+qh->rbox_out_offset);
  765. } /* qh_out2n */
  766. void qh_out3n(qhT *qh, double a, double b, double c) {
  767. if (qh->rbox_isinteger)
  768. qh_fprintf_rbox(qh, qh->fout, 9407, "%d %d %d\n", qh_roundi(qh, a+qh->rbox_out_offset), qh_roundi(qh, b+qh->rbox_out_offset), qh_roundi(qh, c+qh->rbox_out_offset));
  769. else
  770. qh_fprintf_rbox(qh, qh->fout, 9408, qh_REAL_3n, a+qh->rbox_out_offset, b+qh->rbox_out_offset, c+qh->rbox_out_offset);
  771. } /* qh_out3n */
  772. void qh_outcoord(qhT *qh, int iscdd, double *coord, int dim) {
  773. double *p= coord;
  774. int k;
  775. if (iscdd)
  776. qh_out1(qh, 1.0);
  777. for (k=0; k < dim; k++)
  778. qh_out1(qh, *(p++));
  779. qh_fprintf_rbox(qh, qh->fout, 9396, "\n");
  780. } /* qh_outcoord */
  781. void qh_outcoincident(qhT *qh, int coincidentpoints, double radius, int iscdd, double *coord, int dim) {
  782. double *p;
  783. double randr, delta;
  784. int i,k;
  785. double randmax= qh_RANDOMmax;
  786. for (i=0; i<coincidentpoints; i++) {
  787. p= coord;
  788. if (iscdd)
  789. qh_out1(qh, 1.0);
  790. for (k=0; k < dim; k++) {
  791. randr= qh_RANDOMint;
  792. delta= 2.0 * randr/randmax - 1.0; /* -1..+1 */
  793. delta *= radius;
  794. qh_out1(qh, *(p++) + delta);
  795. }
  796. qh_fprintf_rbox(qh, qh->fout, 9410, "\n");
  797. }
  798. } /* qh_outcoincident */
  799. /*------------------------------------------------
  800. Only called from qh_rboxpoints2 or qh_fprintf_rbox
  801. qh_fprintf_rbox is only called from qh_rboxpoints2
  802. The largest exitcode is '255' for compatibility with exit()
  803. */
  804. void qh_errexit_rbox(qhT *qh, int exitcode)
  805. {
  806. longjmp(qh->rbox_errexit, exitcode);
  807. } /* qh_errexit_rbox */