--- ray/src/rt/data.c 1990/04/03 17:48:46 1.5 +++ ray/src/rt/data.c 1992/11/22 10:47:51 2.6 @@ -1,4 +1,4 @@ -/* Copyright (c) 1986 Regents of the University of California */ +/* Copyright (c) 1992 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -14,33 +14,43 @@ static char SCCSid[] = "$SunId$ LBL"; #include "color.h" +#include "resolu.h" + #include "data.h" +#define TABSIZ 97 /* table size (prime) */ + +#define hash(s) (shash(s)%TABSIZ) + + +extern char *fgetword(); + extern char *libpath; /* library search path */ -static DATARRAY *dlist = NULL; /* data array list */ +static DATARRAY *dtab[TABSIZ]; /* data array list */ -static DATARRAY *plist = NULL; /* picture list */ +static DATARRAY *ptab[TABSIZ]; /* picture list */ DATARRAY * getdata(dname) /* get data array dname */ char *dname; { + char word[64]; char *dfname; FILE *fp; int asize; register int i, j; register DATARRAY *dp; /* look for array in list */ - for (dp = dlist; dp != NULL; dp = dp->next) + for (dp = dtab[hash(dname)]; dp != NULL; dp = dp->next) if (!strcmp(dname, dp->name)) return(dp); /* found! */ /* * If we haven't loaded the data already, we will look - * for it in the directorys specified by the library path. + * for it in the directories specified by the library path. * * The file has the following format: * @@ -55,7 +65,7 @@ char *dname; * For irregularly spaced points, the following can be * substituted for begi endi ni: * - * @ ni p0i p1i .. pni + * 0 0 ni p0i p1i .. pni */ if ((dfname = getpath(dname, libpath, R_OK)) == NULL) { @@ -72,26 +82,37 @@ char *dname; error(SYSTEM, errmsg); } /* get dimensions */ - if (fscanf(fp, "%d", &dp->nd) != 1) + if (fgetword(word, sizeof(word), fp) == NULL || !isint(word)) goto scanerr; - if (dp->nd <= 0 || dp->nd > MAXDIM) { + dp->nd = atoi(word); + if (dp->nd <= 0 || dp->nd > MAXDDIM) { sprintf(errmsg, "bad number of dimensions for \"%s\"", dname); error(USER, errmsg); } asize = 1; for (i = 0; i < dp->nd; i++) { - if (fscanf(fp, "%lf %lf %d", - &dp->dim[i].org, &dp->dim[i].siz, - &dp->dim[i].ne) == 3) { - dp->dim[i].siz -= dp->dim[i].org; - dp->dim[i].p = NULL; - } else if (fscanf(fp, "@ %d", &dp->dim[i].ne) == 1) { + if (fgetword(word, sizeof(word), fp) == NULL || !isflt(word)) + goto scanerr; + dp->dim[i].org = atof(word); + if (fgetword(word, sizeof(word), fp) == NULL || !isflt(word)) + goto scanerr; + dp->dim[i].siz = atof(word); + if (fgetword(word, sizeof(word), fp) == NULL || !isint(word)) + goto scanerr; + dp->dim[i].ne = atoi(word); + if (dp->dim[i].ne < 2) + goto scanerr; + asize *= dp->dim[i].ne; + if ((dp->dim[i].siz -= dp->dim[i].org) == 0) { dp->dim[i].p = (double *)malloc(dp->dim[i].ne*sizeof(double)); if (dp->dim[i].p == NULL) goto memerr; - for (j = 0; j < dp->dim[i].ne; j++) - if (fscanf(fp, "%lf", &dp->dim[i].p[j]) != 1) + for (j = 0; j < dp->dim[i].ne; j++) { + if (fgetword(word, sizeof(word), fp) == NULL || + !isflt(word)) goto scanerr; + dp->dim[i].p[j] = atof(word); + } for (j = 1; j < dp->dim[i].ne-1; j++) if ((dp->dim[i].p[j-1] < dp->dim[i].p[j]) != (dp->dim[i].p[j] < dp->dim[i].p[j+1])) @@ -100,21 +121,20 @@ char *dname; dp->dim[i].siz = dp->dim[i].p[dp->dim[i].ne-1] - dp->dim[i].p[0]; } else - goto scanerr; - if (dp->dim[i].siz == 0.0 || dp->dim[i].ne < 2) - goto scanerr; - asize *= dp->dim[i].ne; + dp->dim[i].p = NULL; } if ((dp->arr = (DATATYPE *)malloc(asize*sizeof(DATATYPE))) == NULL) goto memerr; - for (i = 0; i < asize; i++) - if (fscanf(fp, DSCANF, &dp->arr[i]) != 1) + for (i = 0; i < asize; i++) { + if (fgetword(word, sizeof(word), fp) == NULL || !isflt(word)) goto scanerr; - + dp->arr[i] = atof(word); + } fclose(fp); - dp->next = dlist; - return(dlist = dp); + i = hash(dname); + dp->next = dtab[i]; + return(dtab[i] = dp); memerr: error(SYSTEM, "out of memory in getdata"); @@ -125,14 +145,13 @@ scanerr: } -static double inpaspect; /* aspect ratio of input picture */ - static -headaspect(s) /* check string for aspect ratio */ +headaspect(s, iap) /* check string for aspect ratio */ char *s; +double *iap; { if (isaspect(s)) - inpaspect *= aspectval(s); + *iap *= aspectval(s); } @@ -141,15 +160,18 @@ getpict(pname) /* get picture pname */ char *pname; { extern char *libpath; + double inpaspect; char *pfname; FILE *fp; COLOR *scanin; - int width, height; - int x, y; - register int i; + int sl, ns; + RESOLU inpres; + FLOAT loc[2]; + int y; + register int x, i; register DATARRAY *pp; /* look for array in list */ - for (pp = plist; pp != NULL; pp = pp->next) + for (pp = ptab[hash(pname)]; pp != NULL; pp = pp->next) if (!strcmp(pname, pp->name)) return(pp); /* found! */ @@ -168,44 +190,59 @@ char *pname; sprintf(errmsg, "cannot open picture file \"%s\"", pfname); error(SYSTEM, errmsg); } +#ifdef MSDOS + setmode(fileno(fp), O_BINARY); +#endif /* get dimensions */ inpaspect = 1.0; - getheader(fp, headaspect); - if (fgetresolu(&width, &height, fp) != (YMAJOR|YDECR)) + getheader(fp, headaspect, &inpaspect); + if (!fgetsresolu(&inpres, fp)) goto readerr; for (i = 0; i < 3; i++) { pp[i].nd = 2; - pp[i].dim[0].ne = width; - pp[i].dim[1].ne = height; + pp[i].dim[0].ne = inpres.yr; + pp[i].dim[1].ne = inpres.xr; pp[i].dim[0].org = pp[i].dim[1].org = 0.0; - if (width <= height*inpaspect) { - pp[i].dim[0].siz = 1.0; - pp[i].dim[1].siz = inpaspect*(double)height/width; - } else { - pp[i].dim[0].siz = (double)width/height/inpaspect; + if (inpres.xr <= inpres.yr*inpaspect) { + pp[i].dim[0].siz = inpaspect * + (double)inpres.yr/inpres.xr; pp[i].dim[1].siz = 1.0; + } else { + pp[i].dim[0].siz = 1.0; + pp[i].dim[1].siz = (double)inpres.xr/inpres.yr / + inpaspect; } - pp[i].arr = (DATATYPE *)malloc(width*height*sizeof(DATATYPE)); + pp[i].dim[0].p = pp[i].dim[1].p = NULL; + pp[i].arr = (DATATYPE *) + malloc(inpres.xr*inpres.yr*sizeof(DATATYPE)); if (pp[i].arr == NULL) goto memerr; } /* load picture */ - if ((scanin = (COLOR *)malloc(width*sizeof(COLOR))) == NULL) + sl = scanlen(&inpres); + ns = numscans(&inpres); + if ((scanin = (COLOR *)malloc(sl*sizeof(COLOR))) == NULL) goto memerr; - for (y = height-1; y >= 0; y--) { - if (freadscan(scanin, width, fp) < 0) + for (y = 0; y < ns; y++) { + if (freadscan(scanin, sl, fp) < 0) goto readerr; - for (x = 0; x < width; x++) - for (i = 0; i < 3; i++) - pp[i].arr[x*height+y] = colval(scanin[x],i); + for (x = 0; x < sl; x++) { + pix2loc(loc, &inpres, x, y); + i = (int)(loc[1]*inpres.yr)*inpres.xr + + (int)(loc[0]*inpres.xr); + pp[0].arr[i] = colval(scanin[x],RED); + pp[1].arr[i] = colval(scanin[x],GRN); + pp[2].arr[i] = colval(scanin[x],BLU); + } } free((char *)scanin); fclose(fp); + i = hash(pname); pp[0].next = pp[1].next = - pp[2].next = plist; - return(plist = pp); + pp[2].next = ptab[i]; + return(ptab[i] = pp); memerr: error(SYSTEM, "out of memory in getpict"); @@ -218,56 +255,75 @@ readerr: freedata(dname) /* free memory associated with dname */ char *dname; { + DATARRAY head; + int hval, nents; register DATARRAY *dp, *dpl; register int i; - for (dpl = NULL, dp = dlist; dp != NULL; dpl = dp, dp = dp->next) - if (!strcmp(dname, dp->name)) { - if (dpl == NULL) - dlist = dp->next; - else + if (dname == NULL) { /* free all if NULL */ + hval = 0; nents = TABSIZ; + } else { + hval = hash(dname); nents = 1; + } + while (nents--) { + head.next = dtab[hval]; + dpl = &head; + while ((dp = dpl->next) != NULL) + if (dname == NULL || !strcmp(dname, dp->name)) { dpl->next = dp->next; - free((char *)dp->arr); - for (i = 0; i < dp->nd; i++) - if (dp->dim[i].p != NULL) - free((char *)dp->dim[i].p); - freestr(dp->name); - free((char *)dp); - return; - } + free((char *)dp->arr); + for (i = 0; i < dp->nd; i++) + if (dp->dim[i].p != NULL) + free((char *)dp->dim[i].p); + freestr(dp->name); + free((char *)dp); + } else + dpl = dp; + dtab[hval++] = head.next; + } } freepict(pname) /* free memory associated with pname */ char *pname; { + DATARRAY head; + int hval, nents; register DATARRAY *pp, *ppl; - for (ppl = NULL, pp = plist; pp != NULL; ppl = pp, pp = pp->next) - if (!strcmp(pname, pp->name)) { - if (ppl == NULL) - plist = pp->next; - else + if (pname == NULL) { /* free all if NULL */ + hval = 0; nents = TABSIZ; + } else { + hval = hash(pname); nents = 1; + } + while (nents--) { + head.next = ptab[hval]; + ppl = &head; + while ((pp = ppl->next) != NULL) + if (pname == NULL || !strcmp(pname, pp->name)) { ppl->next = pp->next; - free((char *)pp[0].arr); - free((char *)pp[1].arr); - free((char *)pp[2].arr); - freestr(pp[0].name); - free((char *)pp); - return; - } + free((char *)pp[0].arr); + free((char *)pp[1].arr); + free((char *)pp[2].arr); + freestr(pp[0].name); + free((char *)pp); + } else + ppl = pp; + ptab[hval++] = head.next; + } } double datavalue(dp, pt) /* interpolate data value at a point */ register DATARRAY *dp; -double *pt; +double *pt; { DATARRAY sd; int asize; + int lower, upper; register int i; - double x, y, y0, y1; + double x, y, y0, y1; /* set up dimensions for recursion */ sd.nd = dp->nd - 1; asize = 1; @@ -287,20 +343,22 @@ double *pt; else if (i > dp->dim[0].ne - 2) i = dp->dim[0].ne - 2; } else { /* unevenly spaced points */ - if (dp->dim[0].siz > 0.0) - for (i = 0; i < dp->dim[0].ne; i++) - if (pt[0] < dp->dim[0].p[i]) - break; - else - for (i = 0; i < dp->dim[0].ne; i++) - if (pt[0] >= dp->dim[0].p[i]) - break; - if (i <= 0) - i = 0; - else if (i >= dp->dim[0].ne) + if (dp->dim[0].siz > 0.0) { + lower = 0; + upper = dp->dim[0].ne; + } else { + lower = dp->dim[0].ne; + upper = 0; + } + do { + i = (lower + upper) >> 1; + if (pt[0] >= dp->dim[0].p[i]) + lower = i; + else + upper = i; + } while (i != (lower + upper) >> 1); + if (i > dp->dim[0].ne - 2) i = dp->dim[0].ne - 2; - else - i--; x = i + (pt[0] - dp->dim[0].p[i]) / (dp->dim[0].p[i+1] - dp->dim[0].p[i]); }