--- ray/src/cv/mgflib/parser.c 1994/06/21 14:45:46 1.1 +++ ray/src/cv/mgflib/parser.c 1995/04/18 15:53:26 1.16 @@ -1,4 +1,4 @@ -/* Copyright (c) 1994 Regents of the University of California */ +/* Copyright (c) 1995 Regents of the University of California */ #ifndef lint static char SCCSid[] = "$SunId$ LBL"; @@ -56,11 +56,15 @@ int mg_nqcdivs = MG_NQCD; /* number of divisions per q /* alternate handler routines */ static int e_any_toss(), /* discard unneeded entity */ - e_ies(); /* IES luminaire file */ + e_ies(), /* IES luminaire file */ e_include(), /* include file */ e_sph(), /* sphere */ + e_cct(), /* color temperature */ + e_cmix(), /* color mixtures */ + e_cspec(), /* color spectra */ e_cyl(), /* cylinder */ e_cone(), /* cone */ + e_prism(), /* prism */ e_ring(), /* ring */ e_torus(); /* torus */ @@ -103,20 +107,42 @@ mg_init() /* initialize alternate entity handlers */ ineed |= 1<fid = ++nfids; ctx->lineno = 0; if (fn == NULL) { - ctx->fname = ""; + strcpy(ctx->fname, ""); ctx->fp = stdin; ctx->prev = mg_file; mg_file = ctx; return(MG_OK); } /* get name relative to this context */ - if (mg_file != NULL && - (cp = strrchr(mg_file->fname, '/')) != NULL) - olen = cp - mg_file->fname + 1; - else - olen = 0; - ctx->fname = (char *)malloc(olen+strlen(fn)+1); - if (ctx->fname == NULL) - return(MG_EMEM); - if (olen) + if (mg_file != NULL && (cp = strrchr(mg_file->fname, '/')) != NULL) { strcpy(ctx->fname, mg_file->fname); - strcpy(ctx->fname+olen, fn); + strcpy(ctx->fname+(cp-mg_file->fname+1), fn); + } else + strcpy(ctx->fname, fn); ctx->fp = fopen(ctx->fname, "r"); - if (ctx->fp == NULL) { - free((MEM_PTR)ctx->fname); + if (ctx->fp == NULL) return(MG_ENOFILE); - } ctx->prev = mg_file; /* establish new context */ mg_file = ctx; return(MG_OK); @@ -226,20 +254,34 @@ mg_close() /* close input file */ if (ctx->fp == stdin) return; /* don't close standard input */ fclose(ctx->fp); - free((MEM_PTR)ctx->fname); } +void +mg_fgetpos(pos) /* get current position in input file */ +register MG_FPOS *pos; +{ + extern long ftell(); + + pos->fid = mg_file->fid; + pos->lineno = mg_file->lineno; + pos->offset = ftell(mg_file->fp); +} + + int -mg_rewind() /* rewind input file */ +mg_fgoto(pos) /* reposition input file pointer */ +register MG_FPOS *pos; { - if (mg_file->lineno == 0) + if (pos->fid != mg_file->fid) + return(MG_ESEEK); + if (pos->lineno == mg_file->lineno) return(MG_OK); if (mg_file->fp == stdin) return(MG_ESEEK); /* cannot seek on standard input */ - if (fseek(mg_file->fp, 0L, 0) == EOF) + if (fseek(mg_file->fp, pos->offset, 0) == EOF) return(MG_ESEEK); - mg_file->lineno = 0; + mg_file->lineno = pos->lineno; return(MG_OK); } @@ -288,7 +330,7 @@ mg_parse() /* parse current input line */ return(MG_OK); /* no words in line */ *ap = NULL; /* else handle it */ - return(handle_it(-1, ap-argv, argv)); + return(mg_handle(-1, ap-argv, argv)); } @@ -300,7 +342,7 @@ char *fn; int rval; if ((rval = mg_open(&cntxt, fn)) != MG_OK) { - fprintf("%s: %s\n", fn, mg_err[rval]); + fprintf(stderr, "%s: %s\n", fn, mg_err[rval]); return(rval); } while (mg_read()) /* parse each line */ @@ -323,53 +365,6 @@ mg_clear() /* clear parser history */ } -int -mg_iterate(ac, av, f) /* iterate on statement */ -int ac; -register char **av; -int (*f)(); -{ - int niter, rval; - register int i, j; - char *argv[MG_MAXARGC]; - char cntbuf[10]; - /* build partial transformation */ - for (i = 0; i < ac; i++) { - if (av[i][0] == '-' && av[i][1] == 'a' && av[i][2] == '\0') - break; - argv[i+1] = av[i]; - } - argv[i+1] = NULL; - if (i) { /* handle transformation */ - argv[0] = mg_ename[MG_E_XF]; - if ((rval = handle_it(MG_E_XF, i+1, argv)) != MG_OK) - return(rval); - } - if (i < ac) { /* run array */ - if (i+1 >= ac || !isint(av[i+1])) - return(MG_ETYPE); - niter = atoi(av[i+1]); - argv[0] = "-i"; - argv[1] = cntbuf; - for (j = 2; j+i < ac; j++) - argv[j] = av[j+i]; - argv[j] = NULL; - for (j = 0; j < niter; j++) { - sprintf(cntbuf, "%d", j); - if ((rval = mg_iterate(ac-i, argv, f)) != MG_OK) - return(rval); - } - } else if ((rval = (*f)()) != MG_OK) /* else do this instance */ - return(rval); - if (i) { /* reset the transform */ - argv[0] = mg_ename[MG_E_XF]; - argv[1] = NULL; - (void)handle_it(MG_E_XF, 1, argv); - } - return(MG_OK); -} - - /**************************************************************************** * The following routines handle unsupported entities */ @@ -385,37 +380,42 @@ char **av; static int -reload_file() /* reload current MGF file */ -{ - register int rval; - - if ((rval = mg_rewind()) != MG_OK) - return(rval); - while (mg_read()) - if ((rval = mg_parse()) != MG_OK) - return(rval); - return(MG_OK); -} - - -static int e_include(ac, av) /* include file */ int ac; char **av; { + char *xfarg[MG_MAXARGC]; MG_FCTXT ictx; + XF_SPEC *xf_orig = xf_context; int rv; if (ac < 2) return(MG_EARGC); if ((rv = mg_open(&ictx, av[1])) != MG_OK) return(rv); - if ((rv = mg_iterate(ac-2, av+2, reload_file)) != MG_OK) { - fprintf(stderr, "%s: %d: %s:\n%s", ictx.fname, - ictx.lineno, mg_err[rv], ictx.inpline); - mg_close(); - return(MG_EINCL); + if (ac > 2) { + register int i; + + xfarg[0] = mg_ename[MG_E_XF]; + for (i = 1; i < ac-1; i++) + xfarg[i] = av[i+1]; + xfarg[ac-1] = NULL; + if ((rv = mg_handle(MG_E_XF, ac-1, xfarg)) != MG_OK) + return(rv); } + do { + while (mg_read()) + if ((rv = mg_parse()) != MG_OK) { + fprintf(stderr, "%s: %d: %s:\n%s", ictx.fname, + ictx.lineno, mg_err[rv], + ictx.inpline); + mg_close(); + return(MG_EINCL); + } + if (ac > 2) + if ((rv = mg_handle(MG_E_XF, 1, xfarg)) != MG_OK) + return(rv); + } while (xf_context != xf_orig); mg_close(); return(MG_OK); } @@ -463,26 +463,26 @@ char **av; rad = atof(av[2]); /* initialize */ warpconends = 1; - if ((rval = handle_it(MG_E_VERTEX, 3, v2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 3, v2ent)) != MG_OK) return(rval); sprintf(p2x, FLTFMT, cv->p[0]); sprintf(p2y, FLTFMT, cv->p[1]); sprintf(p2z, FLTFMT, cv->p[2]+rad); - if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK) return(rval); r2[0] = '0'; r2[1] = '\0'; for (i = 1; i <= 2*mg_nqcdivs; i++) { theta = i*(PI/2)/mg_nqcdivs; - if ((rval = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK) return(rval); sprintf(p2z, FLTFMT, cv->p[2]+rad*cos(theta)); - if ((rval = handle_it(MG_E_VERTEX, 2, v2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 2, v2ent)) != MG_OK) return(rval); - if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK) return(rval); strcpy(r1, r2); sprintf(r2, FLTFMT, rad*sin(theta)); - if ((rval = handle_it(MG_E_CONE, 5, conent)) != MG_OK) + if ((rval = mg_handle(MG_E_CONE, 5, conent)) != MG_OK) return(rval); } warpconends = 0; @@ -511,11 +511,12 @@ char **av; return(MG_EARGC); if ((cv = c_getvert(av[1])) == NULL) return(MG_EUNDEF); - if (cv->n[0]==0. && cv->n[1]==0. && cv->n[2]==0.) + if (is0vect(cv->n)) return(MG_EILL); if (!isflt(av[2]) || !isflt(av[3])) return(MG_ETYPE); minrad = atof(av[2]); + round0(minrad); maxrad = atof(av[3]); /* check orientation */ if (minrad > 0.) @@ -536,26 +537,26 @@ char **av; for (j = 0; j < 3; j++) sprintf(p2[j], FLTFMT, cv->p[j] + .5*sgn*(maxrad-minrad)*cv->n[j]); - if ((rval = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK) return(rval); - if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK) return(rval); sprintf(r2, FLTFMT, avgrad=.5*(minrad+maxrad)); /* run outer section */ for (i = 1; i <= 2*mg_nqcdivs; i++) { theta = i*(PI/2)/mg_nqcdivs; - if ((rval = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK) return(rval); for (j = 0; j < 3; j++) sprintf(p2[j], FLTFMT, cv->p[j] + .5*sgn*(maxrad-minrad)*cos(theta)*cv->n[j]); - if ((rval = handle_it(MG_E_VERTEX, 2, v2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 2, v2ent)) != MG_OK) return(rval); - if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK) return(rval); strcpy(r1, r2); sprintf(r2, FLTFMT, avgrad + .5*(maxrad-minrad)*sin(theta)); - if ((rval = handle_it(MG_E_CONE, 5, conent)) != MG_OK) + if ((rval = mg_handle(MG_E_CONE, 5, conent)) != MG_OK) return(rval); } /* run inner section */ @@ -565,15 +566,15 @@ char **av; for (j = 0; j < 3; j++) sprintf(p2[j], FLTFMT, cv->p[j] + .5*sgn*(maxrad-minrad)*cos(theta)*cv->n[j]); - if ((rval = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK) return(rval); - if ((rval = handle_it(MG_E_VERTEX, 2, v2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_VERTEX, 2, v2ent)) != MG_OK) return(rval); - if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK) + if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK) return(rval); strcpy(r1, r2); sprintf(r2, FLTFMT, -avgrad - .5*(maxrad-minrad)*sin(theta)); - if ((rval = handle_it(MG_E_CONE, 5, conent)) != MG_OK) + if ((rval = mg_handle(MG_E_CONE, 5, conent)) != MG_OK) return(rval); } warpconends = 0; @@ -594,7 +595,7 @@ char **av; avnew[2] = av[2]; avnew[3] = av[3]; avnew[4] = av[2]; - return(handle_it(MG_E_CONE, 5, avnew)); + return(mg_handle(MG_E_CONE, 5, avnew)); } @@ -623,11 +624,12 @@ char **av; return(MG_EARGC); if ((cv = c_getvert(av[1])) == NULL) return(MG_EUNDEF); - if (cv->n[0]==0. && cv->n[1]==0. && cv->n[2]==0.) + if (is0vect(cv->n)) return(MG_EILL); if (!isflt(av[2]) || !isflt(av[3])) return(MG_ETYPE); minrad = atof(av[2]); + round0(minrad); maxrad = atof(av[3]); if (minrad < 0. || maxrad <= minrad) return(MG_EILL); @@ -635,59 +637,59 @@ char **av; make_axes(u, v, cv->n); for (j = 0; j < 3; j++) sprintf(p3[j], FLTFMT, cv->p[j] + maxrad*u[j]); - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 3, v3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); if (minrad == 0.) { /* closed */ v1ent[3] = av[1]; - if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, nzent)) != MG_OK) + if ((rv = mg_handle(MG_E_NORMAL, 4, nzent)) != MG_OK) return(rv); for (i = 1; i <= 4*mg_nqcdivs; i++) { theta = i*(PI/2)/mg_nqcdivs; - if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK) return(rv); for (j = 0; j < 3; j++) sprintf(p3[j], FLTFMT, cv->p[j] + maxrad*u[j]*cos(theta) + maxrad*v[j]*sin(theta)); - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_FACE, 4, fent)) != MG_OK) + if ((rv = mg_handle(MG_E_FACE, 4, fent)) != MG_OK) return(rv); } } else { /* open */ - if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 3, v4ent)) != MG_OK) return(rv); for (j = 0; j < 3; j++) sprintf(p4[j], FLTFMT, cv->p[j] + minrad*u[j]); - if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK) return(rv); v1ent[3] = "_rv4"; for (i = 1; i <= 4*mg_nqcdivs; i++) { theta = i*(PI/2)/mg_nqcdivs; - if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK) return(rv); for (j = 0; j < 3; j++) { d = u[j]*cos(theta) + v[j]*sin(theta); sprintf(p3[j], FLTFMT, cv->p[j] + maxrad*d); sprintf(p4[j], FLTFMT, cv->p[j] + minrad*d); } - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 2, v4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_FACE, 5, fent)) != MG_OK) + if ((rv = mg_handle(MG_E_FACE, 5, fent)) != MG_OK) return(rv); } } @@ -728,7 +730,9 @@ char **av; if (!isflt(av[2]) || !isflt(av[4])) return(MG_ETYPE); rad1 = atof(av[2]); + round0(rad1); rad2 = atof(av[4]); + round0(rad2); if (rad1 == 0.) { if (rad2 == 0.) return(MG_EILL); @@ -752,89 +756,315 @@ char **av; if ((d = normalize(w)) == 0.) return(MG_EILL); n1off = n2off = (rad2 - rad1)/d; - if (warpconends) /* hack for e_sph and e_torus */ - n2off = tan(atan(n2off)-(PI/4)/mg_nqcdivs); - n2off = sgn*n2off; + if (warpconends) { /* hack for e_sph and e_torus */ + d = atan(n2off) - (PI/4)/mg_nqcdivs; + if (d <= -PI/2+FTINY) + n2off = -FHUGE; + else + n2off = tan(d); + } make_axes(u, v, w); for (j = 0; j < 3; j++) { sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*u[j]); - sprintf(n3[j], FLTFMT, u[j] + w[j]*n2off); + if (n2off <= -FHUGE) + sprintf(n3[j], FLTFMT, -w[j]); + else + sprintf(n3[j], FLTFMT, u[j] + w[j]*n2off); } - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 3, v3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_NORMAL, 4, n3ent)) != MG_OK) return(rv); if (rad1 == 0.) { /* triangles */ v1ent[3] = av[1]; - if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK) return(rv); for (j = 0; j < 3; j++) sprintf(n4[j], FLTFMT, w[j]); - if ((rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_NORMAL, 4, n4ent)) != MG_OK) return(rv); for (i = 1; i <= 4*mg_nqcdivs; i++) { theta = sgn*i*(PI/2)/mg_nqcdivs; - if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK) return(rv); for (j = 0; j < 3; j++) { d = u[j]*cos(theta) + v[j]*sin(theta); sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*d); - sprintf(n3[j], FLTFMT, d + w[j]*n2off); + if (n2off > -FHUGE) + sprintf(n3[j], FLTFMT, d + w[j]*n2off); } - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK) + if (n2off > -FHUGE && + (rv = mg_handle(MG_E_NORMAL, 4, n3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_FACE, 4, fent)) != MG_OK) + if ((rv = mg_handle(MG_E_FACE, 4, fent)) != MG_OK) return(rv); } } else { /* quads */ v1ent[3] = "_cv4"; - if (warpconends) /* hack for e_sph and e_torus */ - n1off = tan(atan(n1off)+(PI/4)/mg_nqcdivs); - n1off = sgn*n1off; + if (warpconends) { /* hack for e_sph and e_torus */ + d = atan(n1off) + (PI/4)/mg_nqcdivs; + if (d >= PI/2-FTINY) + n1off = FHUGE; + else + n1off = tan(atan(n1off)+(PI/4)/mg_nqcdivs); + } for (j = 0; j < 3; j++) { sprintf(p4[j], FLTFMT, cv1->p[j] + rad1*u[j]); - sprintf(n4[j], FLTFMT, u[j] + w[j]*n1off); + if (n1off >= FHUGE) + sprintf(n4[j], FLTFMT, w[j]); + else + sprintf(n4[j], FLTFMT, u[j] + w[j]*n1off); } - if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 3, v4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_NORMAL, 4, n4ent)) != MG_OK) return(rv); for (i = 1; i <= 4*mg_nqcdivs; i++) { theta = sgn*i*(PI/2)/mg_nqcdivs; - if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK) return(rv); for (j = 0; j < 3; j++) { d = u[j]*cos(theta) + v[j]*sin(theta); sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*d); - sprintf(n3[j], FLTFMT, d + w[j]*n2off); + if (n2off > -FHUGE) + sprintf(n3[j], FLTFMT, d + w[j]*n2off); sprintf(p4[j], FLTFMT, cv1->p[j] + rad1*d); - sprintf(n4[j], FLTFMT, d + w[j]*n1off); + if (n1off < FHUGE) + sprintf(n4[j], FLTFMT, d + w[j]*n1off); } - if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK) + if (n2off > -FHUGE && + (rv = mg_handle(MG_E_NORMAL, 4, n3ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_VERTEX, 2, v4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK) + if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK) + if (n1off < FHUGE && + (rv = mg_handle(MG_E_NORMAL, 4, n4ent)) != MG_OK) return(rv); - if ((rv = handle_it(MG_E_FACE, 5, fent)) != MG_OK) + if ((rv = mg_handle(MG_E_FACE, 5, fent)) != MG_OK) return(rv); } } + return(MG_OK); +} + + +static int +e_prism(ac, av) /* turn a prism into polygons */ +int ac; +char **av; +{ + static char p[3][24]; + static char *vent[5] = {mg_ename[MG_E_VERTEX],NULL,"="}; + static char *pent[5] = {mg_ename[MG_E_POINT],p[0],p[1],p[2]}; + static char *znorm[5] = {mg_ename[MG_E_NORMAL],"0","0","0"}; + char *newav[MG_MAXARGC], nvn[MG_MAXARGC-1][8]; + double length; + int hasnorm; + FVECT v1, v2, v3, norm; + register C_VERTEX *cv; + C_VERTEX *cv0; + int rv; + register int i, j; + /* check arguments */ + if (ac < 5) + return(MG_EARGC); + if (!isflt(av[ac-1])) + return(MG_ETYPE); + length = atof(av[ac-1]); + if (length <= FTINY && length >= -FTINY) + return(MG_EILL); + /* compute face normal */ + if ((cv0 = c_getvert(av[1])) == NULL) + return(MG_EUNDEF); + hasnorm = 0; + norm[0] = norm[1] = norm[2] = 0.; + v1[0] = v1[1] = v1[2] = 0.; + for (i = 2; i < ac-1; i++) { + if ((cv = c_getvert(av[i])) == NULL) + return(MG_EUNDEF); + hasnorm += !is0vect(cv->n); + v2[0] = cv->p[0] - cv0->p[0]; + v2[1] = cv->p[1] - cv0->p[1]; + v2[2] = cv->p[2] - cv0->p[2]; + fcross(v3, v1, v2); + norm[0] += v3[0]; + norm[1] += v3[1]; + norm[2] += v3[2]; + VCOPY(v1, v2); + } + if (normalize(norm) == 0.) + return(MG_EILL); + /* create moved vertices */ + for (i = 1; i < ac-1; i++) { + sprintf(nvn[i-1], "_pv%d", i); + vent[1] = nvn[i-1]; + vent[3] = av[i]; + if ((rv = mg_handle(MG_E_VERTEX, 4, vent)) != MG_OK) + return(rv); + cv = c_getvert(av[i]); /* checked above */ + for (j = 0; j < 3; j++) + sprintf(p[j], FLTFMT, cv->p[j] - length*norm[j]); + if ((rv = mg_handle(MG_E_POINT, 4, pent)) != MG_OK) + return(rv); + } + /* make faces */ + newav[0] = mg_ename[MG_E_FACE]; + /* do the side faces */ + newav[5] = NULL; + newav[3] = av[ac-2]; + newav[4] = nvn[ac-3]; + for (i = 1; i < ac-1; i++) { + newav[1] = nvn[i-1]; + newav[2] = av[i]; + if ((rv = mg_handle(MG_E_FACE, 5, newav)) != MG_OK) + return(rv); + newav[3] = newav[2]; + newav[4] = newav[1]; + } + /* do top face */ + for (i = 1; i < ac-1; i++) { + if (hasnorm) { /* zero normals */ + vent[1] = nvn[i-1]; + if ((rv = mg_handle(MG_E_VERTEX, 2, vent)) != MG_OK) + return(rv); + if ((rv = mg_handle(MG_E_NORMAL, 4, znorm)) != MG_OK) + return(rv); + } + newav[ac-1-i] = nvn[i-1]; /* reverse */ + } + if ((rv = mg_handle(MG_E_FACE, ac-1, newav)) != MG_OK) + return(rv); + /* do bottom face */ + if (hasnorm) + for (i = 1; i < ac-1; i++) { + vent[1] = nvn[i-1]; + vent[3] = av[i]; + if ((rv = mg_handle(MG_E_VERTEX, 4, vent)) != MG_OK) + return(rv); + if ((rv = mg_handle(MG_E_NORMAL, 4, znorm)) != MG_OK) + return(rv); + newav[i] = nvn[i-1]; + } + else + for (i = 1; i < ac-1; i++) + newav[i] = av[i]; + newav[i] = NULL; + if ((rv = mg_handle(MG_E_FACE, i, newav)) != MG_OK) + return(rv); + return(MG_OK); +} + + +static int +put_cxy() /* put out current xy chromaticities */ +{ + static char xbuf[24], ybuf[24]; + static char *ccom[4] = {mg_ename[MG_E_CXY], xbuf, ybuf}; + int rv; + + sprintf(xbuf, "%.4f", c_ccolor->cx); + sprintf(ybuf, "%.4f", c_ccolor->cy); + if ((rv = mg_handle(MG_E_CXY, 3, ccom)) != MG_OK) + return(rv); + return(MG_OK); +} + + +static int +put_cspec() /* put out current color spectrum */ +{ + char wl[2][6], vbuf[C_CNSS][24]; + char *newav[C_CNSS+4]; + double sf; + register int i; + + if (mg_ehand[MG_E_CSPEC] != c_hcolor) { + sprintf(wl[0], "%d", C_CMINWL); + sprintf(wl[1], "%d", C_CMAXWL); + newav[0] = mg_ename[MG_E_CSPEC]; + newav[1] = wl[0]; + newav[2] = wl[1]; + sf = (double)C_CNSS / c_ccolor->ssum; + for (i = 0; i < C_CNSS; i++) { + sprintf(vbuf[i], "%.4f", sf*c_ccolor->ssamp[i]); + newav[i+3] = vbuf[i]; + } + newav[C_CNSS+3] = NULL; + if ((i = mg_handle(MG_E_CSPEC, C_CNSS+3, newav)) != MG_OK) + return(i); + } + return(MG_OK); +} + + +static int +e_cspec(ac, av) /* handle spectral color */ +int ac; +char **av; +{ + /* convert to xy chromaticity */ + c_ccvt(c_ccolor, C_CSXY); + /* if it's really their handler, use it */ + if (mg_ehand[MG_E_CXY] != c_hcolor) + return(put_cxy()); + return(MG_OK); +} + + +static int +e_cmix(ac, av) /* handle mixing of colors */ +int ac; +char **av; +{ + /* + * Contorted logic works as follows: + * 1. the colors are already mixed in c_hcolor() support function + * 2. if we would handle a spectral result, make sure it's not + * 3. if c_hcolor() would handle a spectral result, don't bother + * 4. otherwise, make cspec entity and pass it to their handler + * 5. if we have only xy results, handle it as c_spec() would + */ + if (mg_ehand[MG_E_CSPEC] == e_cspec) + c_ccvt(c_ccolor, C_CSXY); + else if (c_ccolor->flags & C_CDSPEC) + return(put_cspec()); + if (mg_ehand[MG_E_CXY] != c_hcolor) + return(put_cxy()); + return(MG_OK); +} + + +static int +e_cct(ac, av) /* handle color temperature */ +int ac; +char **av; +{ + /* + * Logic is similar to e_cmix here. Support handler has already + * converted temperature to spectral color. Put it out as such + * if they support it, otherwise convert to xy chromaticity and + * put it out if they handle it. + */ + if (mg_ehand[MG_E_CSPEC] != e_cspec) + return(put_cspec()); + c_ccvt(c_ccolor, C_CSXY); + if (mg_ehand[MG_E_CXY] != c_hcolor) + return(put_cxy()); return(MG_OK); }