1
/*<html><pre> -<a href="index.htm#TOC"
2
>-------------------------------</a><a name="TOP">-</a>
8
For documentation, see prompt[] of rbox.c
9
50 points generated for 'rbox D4'
12
incorrect range if qh_RANDOMmax is defined wrong (user.h)
27
#ifdef _MSC_VER /* Microsoft Visual C++ */
28
#pragma warning( disable : 4706) /* assignment within conditional expression. */
29
#pragma warning( disable : 4996) /* this function (strncat,sprintf,strcpy) or variable may be unsafe. */
33
#define PI 3.1415926535897932384
35
/* ------------------------------ prototypes ----------------*/
36
int roundi( double a);
38
void out2n( double a, double b);
39
void out3n( double a, double b, double c);
41
void qh_fprintf_rbox(FILE *fp, int msgcode, const char *fmt, ... );
42
void qh_free(void *mem);
43
void *qh_malloc(size_t size);
45
void qh_srand( int seed);
48
/* ------------------------------ globals -------------------*/
50
/* No state is carried between rbox requests */
51
typedef struct rboxT rboxT;
57
jmp_buf errexit; /* exit label for rboxpoints, defined by setjmp(), called by qh_errexit_rbox() */
64
/*-<a href="qh-qhull.htm#TOC"
65
>-------------------------------</a><a name="rboxpoints">-</a>
67
qh_rboxpoints( fout, ferr, rbox_command )
68
Generate points to fout according to rbox options
72
0 (qh_ERRnone) on success
73
1 (qh_ERRinput) on input error
74
4 (qh_ERRmem) on memory error
75
5 (qh_ERRqhull) on internal error
78
To avoid stdio, redefine qh_malloc, qh_free, and qh_fprintf_rbox (user.c)
79
Rbox is not multithreaded.
82
Straight line code (consider defining a struct and functions):
84
Parse arguments into variables
85
Determine the number of points
88
int qh_rboxpoints(FILE* fout, FILE* ferr, char* rbox_command) {
91
int cubesize, diamondsize, seed=0, count, apex;
92
int dim=3 , numpoints= 0, totpoints, addpoints=0;
93
int issphere=0, isaxis=0, iscdd= 0, islens= 0, isregular=0, iswidth=0, addcube=0;
94
int isgap=0, isspiral=0, NOcommand= 0, adddiamond=0;
95
int israndom=0, istime=0;
96
int isbox=0, issimplex=0, issimplex2=0, ismesh=0;
97
double width=0.0, gap=0.0, radius= 0.0;
98
double coord[MAXdim], offset, meshm=3.0, meshn=4.0, meshr=5.0;
99
double *simplex= NULL, *simplexp;
100
int nthroot, mult[MAXdim];
101
double norm, factor, randr, rangap, lensangle= 0, lensbase= 1;
102
double anglediff, angle, x, y, cube= 0.0, diamond= 0.0;
103
double box= qh_DEFAULTbox; /* scale all numbers before output */
104
double randmax= qh_RANDOMmax;
105
char command[200], seedbuf[200];
106
char *s= command, *t, *first_point= NULL;
111
qh_fprintf_rbox(rbox.ferr, 6188, "rbox error: rbox in use by another process. Please lock calls to rbox.\n");
118
exitcode= setjmp(rbox.errexit);
120
/* same code for error exit and normal return */
128
strncat(command, rbox_command, sizeof(command)-strlen(command)-1);
130
while (*s && !isspace(*s)) /* skip program name */
133
while (*s && isspace(*s))
140
numpoints= qh_strtol(s, &s);
143
/* ============= read flags =============== */
151
cube= qh_strtod(++t, &s);
159
diamond= qh_strtod(++t, &s);
179
seed= qh_strtol(s, &s);
194
box= qh_strtod(s, &s);
198
dim= qh_strtol(s, &s);
201
qh_fprintf_rbox(rbox.ferr, 6189, "rbox error: dimension, D%d, out of bounds (>=%d or <=0)", dim, MAXdim);
202
qh_errexit_rbox(qh_ERRinput);
207
gap= qh_strtod(s, &s);
214
radius= qh_strtod(s, &s);
222
meshn= qh_strtod(s, &s);
225
meshm= qh_strtod(s, &s);
230
meshr= qh_strtod(s, &s);
232
meshr= sqrt(meshn*meshn + meshm*meshm);
233
if (*s && !isspace(*s)) {
234
qh_fprintf_rbox(rbox.ferr, 7069, "rbox warning: assuming 'M3,4,5' since mesh args are not integers or reals\n");
235
meshn= 3.0, meshm=4.0, meshr=5.0;
239
rbox.out_offset= qh_strtod(s, &s);
245
while (*s && !isspace(*s)) /* read points later */
249
width= qh_strtod(s, &s);
254
radius= qh_strtod(s, &s);
260
qh_fprintf_rbox(rbox.ferr, 7070, "rbox error: unknown flag at %s.\nExecute 'rbox' without arguments for documentation.\n", s);
261
qh_errexit_rbox(qh_ERRinput);
263
if (*s && !isspace(*s)) {
264
qh_fprintf_rbox(rbox.ferr, 7071, "rbox error: missing space between flags at %s.\n", s);
265
qh_errexit_rbox(qh_ERRinput);
269
/* ============= defaults, constants, and sizes =============== */
270
if (rbox.isinteger && !isbox)
273
cubesize= (int)floor(ldexp(1.0,dim)+0.5);
286
qh_fprintf_rbox(rbox.ferr, 6190, "rbox error: can not combine 'Ln' with 'Zn'\n");
287
qh_errexit_rbox(qh_ERRinput);
290
qh_fprintf_rbox(rbox.ferr, 6191, "rbox error: lens radius %.2g should be greater than 1.0\n",
292
qh_errexit_rbox(qh_ERRinput);
294
lensangle= asin(1.0/radius);
295
lensbase= radius * cos(lensangle);
301
else if (isregular + issimplex + islens + issphere + isaxis + isspiral + iswidth + ismesh) {
302
qh_fprintf_rbox(rbox.ferr, 6192, "rbox error: missing count\n");
303
qh_errexit_rbox(qh_ERRinput);
304
}else if (adddiamond + addcube + addpoints)
307
numpoints= 50; /* ./rbox D4 is the test case */
311
if ((issimplex + islens + isspiral + ismesh > 1)
312
|| (issimplex + issphere + isspiral + ismesh > 1)) {
313
qh_fprintf_rbox(rbox.ferr, 6193, "rbox error: can only specify one of 'l', 's', 'x', 'Ln', or 'Mn,m,r' ('Ln s' is ok).\n");
314
qh_errexit_rbox(qh_ERRinput);
317
/* ============= print header with total points =============== */
318
if (issimplex || ismesh)
319
totpoints= numpoints;
321
totpoints= numpoints+dim+1;
322
else if (isregular) {
323
totpoints= numpoints;
326
totpoints += numpoints - 2;
327
}else if (dim == 3) {
329
totpoints += 2 * numpoints;
331
totpoints += 1 + numpoints;
336
totpoints= numpoints + isaxis;
337
totpoints += cubesize + diamondsize + addpoints;
339
/* ============= seed randoms =============== */
341
for (s=command; *s; s++) {
342
if (issimplex2 && *s == 'y') /* make 'y' same seed as 'x' */
348
}else if (israndom) {
349
seed= (int)time(&timedata);
350
sprintf(seedbuf, " t%d", seed); /* appends an extra t, not worth removing */
351
strncat(command, seedbuf, sizeof(command)-strlen(command)-1);
352
t= strstr(command, " t ");
354
strcpy(t+1, t+3); /* remove " t " */
355
} /* else, seed explicitly set to n */
356
qh_RANDOMseed_(seed);
358
/* ============= print header =============== */
361
qh_fprintf_rbox(rbox.fout, 9391, "%s\nbegin\n %d %d %s\n",
362
NOcommand ? "" : command,
364
rbox.isinteger ? "integer" : "real");
366
qh_fprintf_rbox(rbox.fout, 9392, "%d\n%d\n", dim, totpoints);
368
qh_fprintf_rbox(rbox.fout, 9393, "%d %s\n%d\n", dim, command, totpoints);
370
/* ============= explicit points =============== */
371
if ((s= first_point)) {
372
while (s && *s) { /* 'P' */
377
out1( qh_strtod(s, &s));
379
if (isspace(*s) || !*s)
382
qh_fprintf_rbox(rbox.ferr, 6194, "rbox error: missing comma after coordinate in %s\n\n", s);
383
qh_errexit_rbox(qh_ERRinput);
387
for (k=dim-count; k--; )
389
}else if (count > dim) {
390
qh_fprintf_rbox(rbox.ferr, 6195, "rbox error: %d coordinates instead of %d coordinates in %s\n\n",
392
qh_errexit_rbox(qh_ERRinput);
394
qh_fprintf_rbox(rbox.fout, 9394, "\n");
395
while ((s= strchr(s, 'P'))) {
402
/* ============= simplex distribution =============== */
403
if (issimplex+issimplex2) {
404
if (!(simplex= (double*)qh_malloc( dim * (dim+1) * sizeof(double)))) {
405
qh_fprintf_rbox(rbox.ferr, 6196, "rbox error: insufficient memory for simplex\n");
406
qh_errexit_rbox(qh_ERRmem); /* qh_ERRmem */
410
for (i=0; i<dim; i++) {
411
for (k=0; k<dim; k++)
412
*(simplexp++)= i==k ? 1.0 : 0.0;
414
for (k=0; k<dim; k++)
417
for (i=0; i<dim+1; i++) {
418
for (k=0; k<dim; k++) {
420
*(simplexp++)= 2.0 * randr/randmax - 1.0;
426
for (i=0; i<dim+1; i++) {
429
for (k=0; k<dim; k++)
430
out1( *(simplexp++) * box);
431
qh_fprintf_rbox(rbox.fout, 9395, "\n");
434
for (j=0; j<numpoints; j++) {
436
apex= qh_RANDOMint % (dim+1);
439
for (k=0; k<dim; k++)
442
for (i=0; i<dim+1; i++) {
444
factor= randr/randmax;
448
for (k=0; k<dim; k++) {
449
simplexp= simplex + i*dim + k;
450
coord[k] += factor * (*simplexp);
453
for (k=0; k<dim; k++)
457
for (k=0; k < dim; k++)
458
out1( coord[k] * box);
459
qh_fprintf_rbox(rbox.fout, 9396, "\n");
461
isregular= 0; /* continue with isbox */
465
/* ============= mesh distribution =============== */
467
nthroot= (int)(pow((double)numpoints, 1.0/dim) + 0.99999);
470
for (i=0; i < numpoints; i++) {
471
for (k=0; k < dim; k++) {
473
out1( mult[0] * meshn + mult[1] * (-meshm));
475
out1( mult[0] * meshm + mult[1] * meshn);
477
out1( mult[k] * meshr );
479
qh_fprintf_rbox(rbox.fout, 9397, "\n");
480
for (k=0; k < dim; k++) {
481
if (++mult[k] < nthroot)
487
/* ============= regular points for 's' =============== */
488
else if (isregular && !islens) {
489
if (dim != 2 && dim != 3) {
490
qh_fprintf_rbox(rbox.ferr, 6197, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
491
qh_errexit_rbox(qh_ERRinput);
493
if (!isaxis || radius == 0.0) {
500
out3n( 0.0, 0.0, -box);
504
out3n( 0.0, 0.0, box);
508
anglediff= 2.0 * PI/numpoints;
509
for (i=0; i < numpoints; i++) {
511
x= radius * cos(angle);
512
y= radius * sin(angle);
516
out2n( x*box, y*box);
518
norm= sqrt(1.0 + x*x + y*y);
521
out3n( box*x/norm, box*y/norm, box/norm);
525
norm= sqrt(1.0 + x*x + y*y);
528
out3n( box*x/norm, box*y/norm, box/norm);
533
/* ============= regular points for 'r Ln D2' =============== */
534
else if (isregular && islens && dim == 2) {
538
anglediff= 2 * lensangle/(numpoints - 1);
539
cos_0= cos(lensangle);
540
for (i=0; i < numpoints; i++, angle -= anglediff) {
541
x= radius * sin(angle);
542
y= radius * (cos(angle) - cos_0);
545
out2n( x*box, y*box);
546
if (i != 0 && i != numpoints - 1) {
549
out2n( x*box, -y*box);
553
/* ============= regular points for 'r Ln D3' =============== */
554
else if (isregular && islens && dim != 2) {
556
qh_fprintf_rbox(rbox.ferr, 6198, "rbox error: regular points can be used only in 2-d and 3-d\n\n");
557
qh_errexit_rbox(qh_ERRinput);
560
anglediff= 2* PI/numpoints;
565
offset= sqrt(radius * radius - (1-gap)*(1-gap)) - lensbase;
566
for (i=0; i < numpoints; i++, angle += anglediff) {
571
out3n( box*x, box*y, 0.0);
576
out3n( box*x, box*y, box * offset);
579
out3n( box*x, box*y, -box * offset);
582
/* ============= apex of 'Zn' distribution + gendim =============== */
588
for (j=0; j < gendim; j++)
591
qh_fprintf_rbox(rbox.fout, 9398, "\n");
596
/* ============= generate random point in unit cube =============== */
597
for (i=0; i < numpoints; i++) {
599
for (j=0; j < gendim; j++) {
601
coord[j]= 2.0 * randr/randmax - 1.0;
602
norm += coord[j] * coord[j];
605
/* ============= dim-1 point of 'Zn' distribution ========== */
612
rangap= 1.0 - gap * randr/randmax;
613
factor= radius * rangap / norm;
614
for (j=0; j<gendim; j++)
615
coord[j]= factor * coord[j];
616
/* ============= dim-1 point of 'Ln s' distribution =========== */
617
}else if (islens && issphere) {
623
rangap= 1.0 - gap * randr/randmax;
624
factor= rangap / norm;
625
for (j=0; j<gendim; j++)
626
coord[j]= factor * coord[j];
627
/* ============= dim-1 point of 'Ln' distribution ========== */
628
}else if (islens && !issphere) {
633
j= qh_RANDOMint % gendim;
635
coord[j]= -1.0 - coord[j] * gap;
637
coord[j]= 1.0 - coord[j] * gap;
638
/* ============= point of 'l' distribution =============== */
639
}else if (isspiral) {
641
qh_fprintf_rbox(rbox.ferr, 6199, "rbox error: spiral distribution is available only in 3d\n\n");
642
longjmp(rbox.errexit,qh_ERRinput);
644
coord[0]= cos(2*PI*i/(numpoints - 1));
645
coord[1]= sin(2*PI*i/(numpoints - 1));
646
coord[2]= 2.0*(double)i/(double)(numpoints-1) - 1.0;
647
/* ============= point of 's' distribution =============== */
648
}else if (issphere) {
652
factor *= 1.0 - width * randr/randmax;
654
for (j=0; j<dim; j++)
655
coord[j]= factor * coord[j];
657
/* ============= project 'Zn s' point in to sphere =============== */
658
if (isaxis && issphere) {
661
for (j=0; j<gendim; j++)
662
norm += coord[j] * coord[j];
664
for (j=0; j<dim; j++)
665
coord[j]= coord[j] / norm;
668
coord[dim-1] *= 1 - width * randr/randmax;
670
/* ============= project 'Zn' point onto cube =============== */
671
}else if (isaxis && !issphere) { /* not very interesting */
673
coord[dim-1]= 2.0 * randr/randmax - 1.0;
674
/* ============= project 'Ln' point out to sphere =============== */
676
coord[dim-1]= lensbase;
677
for (j=0, norm= 0; j<dim; j++)
678
norm += coord[j] * coord[j];
680
for (j=0; j<dim; j++)
681
coord[j]= coord[j] * radius/ norm;
682
coord[dim-1] -= lensbase;
685
coord[dim-1] *= 1 - width * randr/randmax;
687
if (qh_RANDOMint > randmax/2)
688
coord[dim-1]= -coord[dim-1];
689
/* ============= project 'Wn' point toward boundary =============== */
690
}else if (iswidth && !issphere) {
691
j= qh_RANDOMint % gendim;
693
coord[j]= -1.0 - coord[j] * width;
695
coord[j]= 1.0 - coord[j] * width;
697
/* ============= write point =============== */
700
for (k=0; k < dim; k++)
701
out1( coord[k] * box);
702
qh_fprintf_rbox(rbox.fout, 9399, "\n");
706
/* ============= write cube vertices =============== */
708
for (j=0; j<cubesize; j++) {
711
for (k=dim-1; k>=0; k--) {
717
qh_fprintf_rbox(rbox.fout, 9400, "\n");
721
/* ============= write diamond vertices =============== */
723
for (j=0; j<diamondsize; j++) {
726
for (k=dim-1; k>=0; k--) {
734
qh_fprintf_rbox(rbox.fout, 9401, "\n");
739
qh_fprintf_rbox(rbox.fout, 9402, "end\nhull\n");
741
/* same code for error exit and normal return */
748
/*------------------------------------------------
749
outxxx - output functions
751
int roundi( double a) {
753
if (a - 0.5 < INT_MIN) {
754
qh_fprintf_rbox(rbox.ferr, 6200, "rbox input error: negative coordinate %2.2g is too large. Reduce 'Bn'\n", a);
755
qh_errexit_rbox(qh_ERRinput);
757
return (int)(a - 0.5);
759
if (a + 0.5 > INT_MAX) {
760
qh_fprintf_rbox(rbox.ferr, 6201, "rbox input error: coordinate %2.2g is too large. Reduce 'Bn'\n", a);
761
qh_errexit_rbox(qh_ERRinput);
763
return (int)(a + 0.5);
767
void out1(double a) {
770
qh_fprintf_rbox(rbox.fout, 9403, "%d ", roundi( a+rbox.out_offset));
772
qh_fprintf_rbox(rbox.fout, 9404, qh_REAL_1, a+rbox.out_offset);
775
void out2n( double a, double b) {
778
qh_fprintf_rbox(rbox.fout, 9405, "%d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset));
780
qh_fprintf_rbox(rbox.fout, 9406, qh_REAL_2n, a+rbox.out_offset, b+rbox.out_offset);
783
void out3n( double a, double b, double c) {
786
qh_fprintf_rbox(rbox.fout, 9407, "%d %d %d\n", roundi(a+rbox.out_offset), roundi(b+rbox.out_offset), roundi(c+rbox.out_offset));
788
qh_fprintf_rbox(rbox.fout, 9408, qh_REAL_3n, a+rbox.out_offset, b+rbox.out_offset, c+rbox.out_offset);
791
void qh_errexit_rbox(int exitcode)
793
longjmp(rbox.errexit, exitcode);