fractal skewed web
Jim Hutchison
hutch at sdcsvax.UUCP
Fri Sep 5 21:06:16 AEST 1986
<>
Its a 3-d recursive tetrahedron generator.
Here is a program to generate the object on page 143 of B. Mandelbrot's
"Fractal Geometry of Nature". The program generates both "sun shaded"
format and "J. Blinn" format. The formats are decribed in greater detail
in the README. This compiles on atleast a sun (4.2BSD) and a vax (4.3BSD),
but it passed lint -p, so there should be no problem with 7character names
atleast.
Jim Hutchison <hutch at sdcsvax.ucsd.edu>
{ucbvax,ihnp4,seismo}!sdcsvax!hutch
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by wizard!hutch on Thu Sep 4 11:09:33 PDT 1986
# Contents: README Makefile tetra.c
echo x - README
sed 's/^@//' > "README" <<'@//E*O*F README//'
Draw a recursive tetrahedron ala Mandelbrot.
Produces sun 'shaded' format or ``Blinn'' format:
Usage: a.out [-l<len> -m<minlen> -x<xcent> -y<ycent> -z<zcent> -f<file>]
len length of an edge
minlen the length of subdivided edge at which to stop
xcent x center of object
ycent y center of object
zcent z center of object
file output file
Author: Jim Hutchison <hutch at sdcsvax.ucsd.edu>
Compiler Flags:
BLINN -- output in Jim Blinn's format, only author I could find.
FAT -- do not free any allocated memory, usually for fat machines.
free() is a relatively slow operation.
Format of output file (compiled with -DBLINN):
<TAB>Comment
PNT id, x, y, z
POLY ptnumber1, ptnumber2, ... ptnumberN
example:
THIS FILE HAS AN AARDVARK IN IT
PNT 1, 1.0, 3.5, 9.7
PNT 2, 1.0, 2.5, 9.7
PNT 3, 3.0, 3.5, 1.7
POLY 1, 2, 3
PNT 4, 5.0, 3.5, 3.7
POLY 2, 4, 1
Format of output file (compiled without -DBLINN):
points polygons
minx maxx miny maxy minz maxz
p1x py1 p1z
...
Nsides ptnumber1 ptnumber2 ... ptnumberN
...
3 1 2 3 <-- for example
@//E*O*F README//
chmod u=rw,g=r,o=r README
echo x - Makefile
sed 's/^@//' > "Makefile" <<'@//E*O*F Makefile//'
#
# Makefile for 'sun shaded format' recursive tetrahedron
#
BLINN = #-DBLINN
FAT = -DFAT
DEBUG = #-DDEBUG /usr/lib/debug/malloc.o
CFLAGS = -O $(FAT) $(BLINN) $(DEBUG)
CC = /bin/cc
tetra: tetra.c
$(CC) $(CFLAGS) tetra.c -o $@
tetra_sun: tetra.c
$(CC) $(CFLAGS) -UBLINN tetra.c -o $@
tetra_blinn: tetra.c
$(CC) $(CFLAGS) -DBLINN tetra.c -o $@
@//E*O*F Makefile//
chmod u=rw,g=r,o=r Makefile
echo x - tetra.c
sed 's/^@//' > "tetra.c" <<'@//E*O*F tetra.c//'
/*
* Draw a recursive tetrahedron ala Mandelbrot (page 142,
* "The Fractal Geometry of Nature").
*
* Produces sun 'shaded' format unless compiled with
* BLINN defined (I can find little other attribution).
*
* Usage: a.out [-l<len> -m<minlen> -x<xcent> -y<ycent> -z<zcent> -f<file>]
*
* len length of an edge
* minlen the length of subdivided edge at which to stop
* xcent x center of object
* ycent y center of object
* zcent z center of object
* file output file
*
*
* Author: Jim Hutchison <hutch at sdcsvax.ucsd.edu>
*
* Feel free to do anything with this code except remove this comment.
*
*/
/* Informational drawing
* [a,d] are the original points, and [0,5] are the
* points created for the next generation of tetrahedrons.
* '*'ed points are vertically elevated.
*
* /\c
* / \
* / \
* / *5 \
* / \
* 2----------1
* /\ /\
* ^ / \ *d / \
* | / \ / \
* | / *3 \ / *4 \
* |/ \ / \
* a----------0----------\b--->
*/
#include <stdio.h>
#define DEF_OUTFILE "./tropicalfish" /* BM says tropical fish */
#define TEMP_FILE "/tmp/tetraXXXXXX" /* temp file name, need 6 X's */
#define SQRT2 1.4142135623731 /* C.R.C. constants */
#define SQRT3 1.7320508075688
#define SQRT3over4 0.4330127018922 /* sqrt(3.0) / 4.0 */
#define SQRT3over8 0.2165063509461 /* sqrt(3.0) / 8.0 */
#define DEF_LEN 160.0 /* default start length */
#define DEF_MIN 40.0 /* default min length */
#define DEF_CX 0.0 /* default x center */
#define DEF_CY 0.0 /* default y center */
#define DEF_CZ 0.0 /* default z center */
#define OUTBUFSIZ 128
typedef struct { /* a point in space */
double x, y, z;
int id; /* its ordinal number, for vertice definition */
} POINT;
char *malloc(), *strcpy();
static double mindist; /* minimum distance between vertices */
static int pointcnt = 0; /* current point count */
static int polycnt = 0; /* current polygon count */
#ifdef BLINN
static FILE *fout; /* outfile pointer */
#else
static char *tmppoly; /* names of temporary files */
static char *tmppoint;
static FILE *fpoint,*fpoly; /* point and poylgon file pointers */
#endif
main(argc, argv)
int argc;
char **argv;
{
int ch;
char outfilename[1024];
double min, cx, cy, cz, len, half_len, projected_len;
static char options[] = "[-l<len> -m<minlen> -x<xcenter> -y<ycenter> -z<zcenter> -f<outfile>]";
extern int optind;
extern char *optarg;
/* DEFAULTS */
len = DEF_LEN; /* length of a side at start */
min = DEF_MIN; /* length of a side at which to stop */
cx = DEF_CX; /* Center of mass */
cy = DEF_CY;
cz = DEF_CZ;
strcpy(outfilename,DEF_OUTFILE); /* sun 'shaded' file */
while((ch = getopt(argc,argv,"l:m:x:y:z:f:HELP")) != EOF)
switch(ch) {
case 'l':
sscanf(optarg,"%lf",&len);
break;
case 'm':
sscanf(optarg,"%lf",&min);
if (min <= 0.0)
die("Min can not be less than or equal to 0.");
break;
case 'x':
sscanf(optarg,"%lf",&cx);
break;
case 'y':
sscanf(optarg,"%lf",&cy);
break;
case 'z':
sscanf(optarg,"%lf",&cz);
break;
case 'f':
strcpy(outfilename,optarg);
if (*outfilename == NULL)
die("Null output file name.");
break;
case 'H':
default:
fprintf(stderr,"Usage: %s %s\n",argv[0],options);
exit(-1);
}
#ifdef BLINN
if ((fout = fopen(outfilename,"w")) == NULL)
die("Could not open output file");
fprintf(fout,"\tFRACTAL SKEWED WEB, HAUSDORFF DIMENSION = 2.0\n");
fprintf(fout,"\tCX %4.7f, CY %4.7f, CZ %4.7f\n", cx, cy, cz);
fprintf(fout,"\tLEN %4.7f, MIN %4.7f\n\n", len, min);
#else
init_scratchfiles(); /* point & polygon scratch files */
#endif
half_len = len / 2.0; /* half the length of a side */
/* half a side projected onto y/z */
projected_len = (half_len / 2.0) * SQRT3;
cx = cx - half_len; /* determine a vertex from center */
cy = cy - projected_len;
cz = cz - projected_len;
#ifdef sun && DEBUG
malloc_debug(2); /* check whole heap on every call */
#endif
tetrahedrons( cx, cy, cz, min, len);
#ifdef BLINN
fclose(fout);
#else
end_files(outfilename,cx,cy,cz,len); /* sweep it all together and close */
#endif
exit(0);
}
/*
* Create a point structure containing x,y,z and return the pointer.
*/
POINT *
pcreate(x, y, z)
double x, y, z;
{
POINT *p;
extern int pointcnt;
extern FILE *fpoint, *fout;
p = (POINT *)malloc(sizeof(POINT));
if (p == NULL)
die("Out of Core in pcreate()");
p->x = x;
p->y = y;
p->z = z;
p->id = ++pointcnt;
#ifdef BLINN
fprintf(fout, "PNT %d, %4.7f, %4.7f, %4.7f\n", p->id, x, y, z);
#else
fprintf(fpoint, "%4.7f\t%4.7f\t%4.7f\n", x, y, z);
#endif
return(p);
}
/*
* Make the 'prime' points, the points of a new generation.
*
* p[0] is point 0 on the 'sketch', etc.
*/
makeprime(a, p, n)
POINT *a, *p[6];
register double n;
{
register double ax, ay, az, n1, n2, nhalf, n3fourth, nfourth;
ax = a->x;
ay = a->y;
az = a->z;
nfourth = n / 4.0;
nhalf = n / 2.0;
n3fourth = 1.5 * nhalf;
n1 = n * SQRT3over4;
n2 = n * SQRT3over8;
p[0] = pcreate(ax + nhalf, ay, az);
p[1] = pcreate(ax + n3fourth, ay, az + n1);
p[2] = pcreate(ax + nfourth, ay, az + n1);
p[3] = pcreate(ax + nfourth, ay + n1, az + n2);
p[4] = pcreate(ax + n3fourth, ay + n1, az + n2);
p[5] = pcreate(ax + nhalf, ay + n1, az + 3.0 * n2);
}
/*
* Output a tetrahedron
*/
drawtetra(a, b, c, d)
POINT *a, *b, *c, *d;
{
extern int polycnt;
extern FILE *fpoly, *fout;
polycnt += 4;
#ifdef BLINN
fprintf(fout,"POLY %5d, %5d, %5d\n", a->id, b->id, c->id);
fprintf(fout,"POLY %5d, %5d, %5d\n", a->id, b->id, d->id);
fprintf(fout,"POLY %5d, %5d, %5d\n", a->id, c->id, d->id);
fprintf(fout,"POLY %5d, %5d, %5d\n", b->id, c->id, d->id);
#else
fprintf(fpoly,"3 %5d %5d %5d\n", a->id, b->id, c->id);
fprintf(fpoly,"3 %5d %5d %5d\n", a->id, b->id, d->id);
fprintf(fpoly,"3 %5d %5d %5d\n", a->id, c->id, d->id);
fprintf(fpoly,"3 %5d %5d %5d\n", b->id, c->id, d->id);
#endif
}
/*
* Create the seed and begin the generation cycle.
*/
tetrahedrons(x, y, z, min, n)
double x, y, z, min, n;
{
POINT *a, *b, *c, *d;
extern double mindist;
mindist = min;
a = pcreate(x, y, z);
b = pcreate(x + n, y, z);
c = pcreate(x + n / 2.0, y, z + n * SQRT3 / 2.0);
d = pcreate(x + n / 2.0, y + n * SQRT3 / 2.0, z + n * SQRT3 / 4.0);
tetra(a, b, c, d, n);
}
/*
* Run the generation cycle
*/
tetra(a, b, c, d, n)
POINT *a, *b, *c, *d;
double n;
{
extern double mindist;
if (n < mindist)
drawtetra(a, b, c, d);
else {
POINT *p[6];
makeprime(a, p, n);
n /= 2.0;
/* rad! a diagonally symetric recursion matrix!!!
*/
tetra( a, p[0], p[2], p[3], n);
tetra(p[0], b, p[1], p[4], n);
tetra(p[2], p[1], c, p[5], n);
tetra(p[3], p[4], p[5], d, n);
#ifndef FAT
free(p[0]); /* if have lots of memory, can remove these for speed */
free(p[1]);
free(p[2]);
free(p[3]);
free(p[4]);
free(p[5]);
#endif
}
}
/*
* Spew a message on stderr, and die.
*/
die(message)
char *message;
{
fprintf(stderr,"Error: %s\n",message);
exit(-1);
}
#ifndef BLINN /* <----- Cut Point */
/*
* Open the scratch point and polygon files
* Set value of tmppoint and tmppoly so that
* we can unlink them later. Will not do that
* now because we are told 4.3 may break that ``technique''.
*/
init_scratchfiles()
{
extern FILE *fpoint, *fpoly;
extern char *tmppoint, *tmppoly;
char *mktemp();
tmppoint = mktemp(TEMP_FILE);
fpoint = fopen(tmppoint,"w+");
if (fpoint == NULL)
die("Could not open input file for writing");
tmppoly = mktemp(TEMP_FILE);
fpoly = fopen(tmppoly,"w+");
if (fpoly == NULL)
die("Could not open scratch polygon file for writing");
}
/*
* Open the output file, fill it from the scratch files
* and then close them all. Use the center and length
* to generate the bounding box information.
*/
end_files(outfile,cx,cy,cz,len)
char *outfile;
double cx, cy, cz, len;
{
int i;
register FILE *fout;
char buf[OUTBUFSIZ];
double projectedlen;
fout = fopen(outfile,"w");
if (fout == NULL)
die("Could not open output file");
/* Inventory */
fprintf(fout,"%d %d\n", pointcnt, polycnt);
/* Bounding box */
projectedlen = len * SQRT3 / 2.;
fprintf(fout,"%-4.7f %-4.7f ", cx, cx + len);
fprintf(fout,"%-4.7f %-4.7f ", cy, cy + projectedlen);
fprintf(fout,"%-4.7f %-4.7f\n",cz, cz + projectedlen);
/* Points */
fflush(fpoint); /* flush output and rewind */
rewind(fpoint);
for (i = pointcnt; i > 0; i--) { /* copy scratch file into output file */
fgets(buf,OUTBUFSIZ,fpoint);
fputs(buf,fout);
}
fclose(fpoint); /* close and unlink the scratch points file */
unlink(tmppoint);
/* Polygons */
fflush(fpoly); /* flush output and rewind */
rewind(fpoly);
for (i = polycnt; i > 0; i--) { /* copy scratch file into output file */
fgets(buf,OUTBUFSIZ,fpoly);
fputs(buf,fout);
}
fclose(fpoly); /* close and unlink the scratch points file */
unlink(tmppoly);
fclose(fout);
}
#endif /* <----- Cut Point */
@//E*O*F tetra.c//
chmod u=rw,g=r,o=r tetra.c
exit 0
--
Jim Hutchison UUCP: {dcdwest,ucbvax}!sdcsvax!hutch
ARPA: Hutch at sdcsvax.ucsd.edu
"The fog crept in on little cats feet" -CS
More information about the Comp.sources.unix
mailing list