ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cv/mgflib/parser.c
(Generate patch)

Comparing ray/src/cv/mgflib/parser.c (file contents):
Revision 1.1 by greg, Tue Jun 21 14:45:46 1994 UTC vs.
Revision 1.23 by greg, Wed Jun 19 22:34:59 1996 UTC

# Line 1 | Line 1
1 < /* Copyright (c) 1994 Regents of the University of California */
1 > /* Copyright (c) 1996 Regents of the University of California */
2  
3   #ifndef lint
4   static char SCCSid[] = "$SunId$ LBL";
# Line 27 | Line 27 | char   mg_ename[MG_NENTITIES][MG_MAXELEN] = MG_NAMELIST;
27  
28   int     (*mg_ehand[MG_NENTITIES])();
29  
30 +                        /* Handler routine for unknown entities */
31 +
32 + int     (*mg_uhand)() = mg_defuhand;
33 +
34 + unsigned        mg_nunknown;    /* count of unknown entities */
35 +
36                          /* error messages */
37  
38   char    *mg_err[MG_NERRS] = MG_ERRLIST;
# Line 56 | Line 62 | int    mg_nqcdivs = MG_NQCD;   /* number of divisions per q
62                                  /* alternate handler routines */
63  
64   static int      e_any_toss(),           /* discard unneeded entity */
65 <                e_ies();                /* IES luminaire file */
66 <                e_include(),            /* include file */
65 >                e_ies(),                /* IES luminaire file */
66 >                e_cct(),                /* color temperature */
67 >                e_cmix(),               /* color mixtures */
68 >                e_cspec();              /* color spectra */
69 >
70 > int             e_include(),            /* include file */
71                  e_sph(),                /* sphere */
72                  e_cyl(),                /* cylinder */
73                  e_cone(),               /* cone */
74 +                e_prism(),              /* prism */
75                  e_ring(),               /* ring */
76                  e_torus();              /* torus */
77  
# Line 85 | Line 96 | mg_init()                      /* initialize alternate entity handlers */
96                  mg_ehand[MG_E_INCLUDE] = e_include;
97          if (mg_ehand[MG_E_SPH] == NULL) {
98                  mg_ehand[MG_E_SPH] = e_sph;
99 <                ineed |= 1<<MG_E_POINT|1<<MG_E_VERTEX;
99 >                ineed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX;
100          } else
101 <                uneed |= 1<<MG_E_POINT|1<<MG_E_VERTEX|1<<MG_E_XF;
101 >                uneed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX|1L<<MG_E_XF;
102          if (mg_ehand[MG_E_CYL] == NULL) {
103                  mg_ehand[MG_E_CYL] = e_cyl;
104 <                ineed |= 1<<MG_E_POINT|1<<MG_E_VERTEX;
104 >                ineed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX;
105          } else
106 <                uneed |= 1<<MG_E_POINT|1<<MG_E_VERTEX|1<<MG_E_XF;
106 >                uneed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX|1L<<MG_E_XF;
107          if (mg_ehand[MG_E_CONE] == NULL) {
108                  mg_ehand[MG_E_CONE] = e_cone;
109 <                ineed |= 1<<MG_E_POINT|1<<MG_E_VERTEX;
109 >                ineed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX;
110          } else
111 <                uneed |= 1<<MG_E_POINT|1<<MG_E_VERTEX|1<<MG_E_XF;
111 >                uneed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX|1L<<MG_E_XF;
112          if (mg_ehand[MG_E_RING] == NULL) {
113                  mg_ehand[MG_E_RING] = e_ring;
114 <                ineed |= 1<<MG_E_POINT|1<<MG_E_NORMAL|1<<MG_E_VERTEX;
114 >                ineed |= 1L<<MG_E_POINT|1L<<MG_E_NORMAL|1L<<MG_E_VERTEX;
115          } else
116 <                uneed |= 1<<MG_E_POINT|1<<MG_E_NORMAL|1<<MG_E_VERTEX|1<<MG_E_XF;
116 >                uneed |= 1L<<MG_E_POINT|1L<<MG_E_NORMAL|1L<<MG_E_VERTEX|1L<<MG_E_XF;
117 >        if (mg_ehand[MG_E_PRISM] == NULL) {
118 >                mg_ehand[MG_E_PRISM] = e_prism;
119 >                ineed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX;
120 >        } else
121 >                uneed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX|1L<<MG_E_XF;
122          if (mg_ehand[MG_E_TORUS] == NULL) {
123                  mg_ehand[MG_E_TORUS] = e_torus;
124 <                ineed |= 1<<MG_E_POINT|1<<MG_E_NORMAL|1<<MG_E_VERTEX;
124 >                ineed |= 1L<<MG_E_POINT|1L<<MG_E_NORMAL|1L<<MG_E_VERTEX;
125          } else
126 <                uneed |= 1<<MG_E_POINT|1<<MG_E_NORMAL|1<<MG_E_VERTEX|1<<MG_E_XF;
126 >                uneed |= 1L<<MG_E_POINT|1L<<MG_E_NORMAL|1L<<MG_E_VERTEX|1L<<MG_E_XF;
127 >        if (mg_ehand[MG_E_COLOR] != NULL) {
128 >                if (mg_ehand[MG_E_CMIX] == NULL) {
129 >                        mg_ehand[MG_E_CMIX] = e_cmix;
130 >                        ineed |= 1L<<MG_E_COLOR|1L<<MG_E_CXY|1L<<MG_E_CSPEC|1L<<MG_E_CMIX|1L<<MG_E_CCT;
131 >                }
132 >                if (mg_ehand[MG_E_CSPEC] == NULL) {
133 >                        mg_ehand[MG_E_CSPEC] = e_cspec;
134 >                        ineed |= 1L<<MG_E_COLOR|1L<<MG_E_CXY|1L<<MG_E_CSPEC|1L<<MG_E_CMIX|1L<<MG_E_CCT;
135 >                }
136 >                if (mg_ehand[MG_E_CCT] == NULL) {
137 >                        mg_ehand[MG_E_CCT] = e_cct;
138 >                        ineed |= 1L<<MG_E_COLOR|1L<<MG_E_CXY|1L<<MG_E_CSPEC|1L<<MG_E_CMIX|1L<<MG_E_CCT;
139 >                }
140 >        }
141                                          /* check for consistency */
142          if (mg_ehand[MG_E_FACE] != NULL)
143 <                uneed |= 1<<MG_E_POINT|1<<MG_E_VERTEX|1<<MG_E_XF;
144 <        if (mg_ehand[MG_E_CXY] != NULL)
145 <                uneed |= 1<<MG_E_COLOR;
143 >                uneed |= 1L<<MG_E_POINT|1L<<MG_E_VERTEX|1L<<MG_E_XF;
144 >        if (mg_ehand[MG_E_CXY] != NULL || mg_ehand[MG_E_CSPEC] != NULL ||
145 >                        mg_ehand[MG_E_CMIX] != NULL)
146 >                uneed |= 1L<<MG_E_COLOR;
147          if (mg_ehand[MG_E_RD] != NULL || mg_ehand[MG_E_TD] != NULL ||
148 +                        mg_ehand[MG_E_IR] != NULL ||
149                          mg_ehand[MG_E_ED] != NULL ||
150                          mg_ehand[MG_E_RS] != NULL ||
151 <                        mg_ehand[MG_E_TS] != NULL)
152 <                uneed |= 1<<MG_E_MATERIAL;
151 >                        mg_ehand[MG_E_TS] != NULL ||
152 >                        mg_ehand[MG_E_SIDES] != NULL)
153 >                uneed |= 1L<<MG_E_MATERIAL;
154          for (i = 0; i < MG_NENTITIES; i++)
155 <                if (uneed & 1<<i && mg_ehand[i] == NULL) {
155 >                if (uneed & 1L<<i && mg_ehand[i] == NULL) {
156                          fprintf(stderr, "Missing support for \"%s\" entity\n",
157                                          mg_ename[i]);
158                          exit(1);
159                  }
160                                          /* add support as needed */
161 <        if (ineed & 1<<MG_E_VERTEX && mg_ehand[MG_E_VERTEX] != c_hvertex)
161 >        if (ineed & 1L<<MG_E_VERTEX && mg_ehand[MG_E_VERTEX] != c_hvertex)
162                  e_supp[MG_E_VERTEX] = c_hvertex;
163 <        if (ineed & 1<<MG_E_POINT && mg_ehand[MG_E_POINT] != c_hvertex)
163 >        if (ineed & 1L<<MG_E_POINT && mg_ehand[MG_E_POINT] != c_hvertex)
164                  e_supp[MG_E_POINT] = c_hvertex;
165 <        if (ineed & 1<<MG_E_NORMAL && mg_ehand[MG_E_NORMAL] != c_hvertex)
165 >        if (ineed & 1L<<MG_E_NORMAL && mg_ehand[MG_E_NORMAL] != c_hvertex)
166                  e_supp[MG_E_NORMAL] = c_hvertex;
167 +        if (ineed & 1L<<MG_E_COLOR && mg_ehand[MG_E_COLOR] != c_hcolor)
168 +                e_supp[MG_E_COLOR] = c_hcolor;
169 +        if (ineed & 1L<<MG_E_CXY && mg_ehand[MG_E_CXY] != c_hcolor)
170 +                e_supp[MG_E_CXY] = c_hcolor;
171 +        if (ineed & 1L<<MG_E_CSPEC && mg_ehand[MG_E_CSPEC] != c_hcolor)
172 +                e_supp[MG_E_CSPEC] = c_hcolor;
173 +        if (ineed & 1L<<MG_E_CMIX && mg_ehand[MG_E_CMIX] != c_hcolor)
174 +                e_supp[MG_E_CMIX] = c_hcolor;
175 +        if (ineed & 1L<<MG_E_CCT && mg_ehand[MG_E_CCT] != c_hcolor)
176 +                e_supp[MG_E_CCT] = c_hcolor;
177                                          /* discard remaining entities */
178          for (i = 0; i < MG_NENTITIES; i++)
179                  if (mg_ehand[i] == NULL)
# Line 138 | Line 181 | mg_init()                      /* initialize alternate entity handlers */
181   }
182  
183  
141
184   int
185   mg_entity(name)                 /* get entity number from its name */
186   char    *name;
187   {
188 <        static LUTAB    ent_tab;        /* entity lookup table */
188 >        static LUTAB    ent_tab = LU_SINIT(NULL,NULL);  /* lookup table */
189          register char   *cp;
190  
191          if (!ent_tab.tsiz) {            /* initialize hash table */
# Line 160 | Line 202 | char   *name;
202   }
203  
204  
205 < static int
206 < handle_it(en, ac, av)           /* pass entity to appropriate handler */
205 > int
206 > mg_handle(en, ac, av)           /* pass entity to appropriate handler */
207   register int    en;
208   int     ac;
209   char    **av;
210   {
211          int     rv;
212  
213 <        if (en < 0 && (en = mg_entity(av[0])) < 0)
213 >        if (en < 0 && (en = mg_entity(av[0])) < 0) {    /* unknown entity */
214 >                if (mg_uhand != NULL)
215 >                        return((*mg_uhand)(ac, av));
216                  return(MG_EUNK);
217 <        if (e_supp[en] != NULL) {
217 >        }
218 >        if (e_supp[en] != NULL) {                       /* support handler */
219                  if ((rv = (*e_supp[en])(ac, av)) != MG_OK)
220                          return(rv);
221          }
222 <        return((*mg_ehand[en])(ac, av));
222 >        return((*mg_ehand[en])(ac, av));                /* assigned handler */
223   }
224  
225  
# Line 183 | Line 228 | mg_open(ctx, fn)                       /* open new input file */
228   register MG_FCTXT       *ctx;
229   char    *fn;
230   {
231 <        int     olen;
231 >        static int      nfids;
232          register char   *cp;
233  
234 +        ctx->fid = ++nfids;
235          ctx->lineno = 0;
236          if (fn == NULL) {
237 <                ctx->fname = "<stdin>";
237 >                strcpy(ctx->fname, "<stdin>");
238                  ctx->fp = stdin;
239                  ctx->prev = mg_file;
240                  mg_file = ctx;
241                  return(MG_OK);
242          }
243                                          /* get name relative to this context */
244 <        if (mg_file != NULL &&
199 <                        (cp = strrchr(mg_file->fname, '/')) != NULL)
200 <                olen = cp - mg_file->fname + 1;
201 <        else
202 <                olen = 0;
203 <        ctx->fname = (char *)malloc(olen+strlen(fn)+1);
204 <        if (ctx->fname == NULL)
205 <                return(MG_EMEM);
206 <        if (olen)
244 >        if (mg_file != NULL && (cp = strrchr(mg_file->fname, '/')) != NULL) {
245                  strcpy(ctx->fname, mg_file->fname);
246 <        strcpy(ctx->fname+olen, fn);
246 >                strcpy(ctx->fname+(cp-mg_file->fname+1), fn);
247 >        } else
248 >                strcpy(ctx->fname, fn);
249          ctx->fp = fopen(ctx->fname, "r");
250 <        if (ctx->fp == NULL) {
211 <                free((MEM_PTR)ctx->fname);
250 >        if (ctx->fp == NULL)
251                  return(MG_ENOFILE);
213        }
252          ctx->prev = mg_file;            /* establish new context */
253          mg_file = ctx;
254          return(MG_OK);
# Line 223 | Line 261 | mg_close()                     /* close input file */
261          register MG_FCTXT       *ctx = mg_file;
262  
263          mg_file = ctx->prev;            /* restore enclosing context */
264 <        if (ctx->fp == stdin)
265 <                return;                 /* don't close standard input */
228 <        fclose(ctx->fp);
229 <        free((MEM_PTR)ctx->fname);
264 >        if (ctx->fp != stdin)           /* close file if it's a file */
265 >                fclose(ctx->fp);
266   }
267  
268  
269 + void
270 + mg_fgetpos(pos)                 /* get current position in input file */
271 + register MG_FPOS        *pos;
272 + {
273 +        extern long     ftell();
274 +
275 +        pos->fid = mg_file->fid;
276 +        pos->lineno = mg_file->lineno;
277 +        pos->offset = ftell(mg_file->fp);
278 + }
279 +
280 +
281   int
282 < mg_rewind()                     /* rewind input file */
282 > mg_fgoto(pos)                   /* reposition input file pointer */
283 > register MG_FPOS        *pos;
284   {
285 <        if (mg_file->lineno == 0)
285 >        if (pos->fid != mg_file->fid)
286 >                return(MG_ESEEK);
287 >        if (pos->lineno == mg_file->lineno)
288                  return(MG_OK);
289          if (mg_file->fp == stdin)
290                  return(MG_ESEEK);       /* cannot seek on standard input */
291 <        if (fseek(mg_file->fp, 0L, 0) == EOF)
291 >        if (fseek(mg_file->fp, pos->offset, 0) == EOF)
292                  return(MG_ESEEK);
293 <        mg_file->lineno = 0;
293 >        mg_file->lineno = pos->lineno;
294          return(MG_OK);
295   }
296  
# Line 253 | Line 304 | mg_read()                      /* read next line from file */
304                  if (fgets(mg_file->inpline+len,
305                                  MG_MAXLINE-len, mg_file->fp) == NULL)
306                          return(len);
256                mg_file->lineno++;
307                  len += strlen(mg_file->inpline+len);
308 <                if (len > 1 && mg_file->inpline[len-2] == '\\')
309 <                        mg_file->inpline[--len-1] = ' ';
310 <        } while (mg_file->inpline[len]);
308 >                if (len >= MG_MAXLINE-1)
309 >                        return(len);
310 >                mg_file->lineno++;
311 >        } while (len > 1 && mg_file->inpline[len-2] == '\\');
312  
313          return(len);
314   }
# Line 269 | Line 320 | mg_parse()                     /* parse current input line */
320          char    abuf[MG_MAXLINE];
321          char    *argv[MG_MAXARGC];
322          int     en;
323 <        register char   *cp, **ap;
324 <
325 <        strcpy(cp=abuf, mg_file->inpline);
326 <        ap = argv;                      /* break into words */
323 >        register char   *cp, *cp2, **ap;
324 >                                        /* copy line, removing escape chars */
325 >        cp = abuf; cp2 = mg_file->inpline;
326 >        while ((*cp++ = *cp2++))
327 >                if (cp2[0] == '\n' && cp2[-1] == '\\')
328 >                        cp--;
329 >        cp = abuf; ap = argv;           /* break into words */
330          for ( ; ; ) {
331                  while (isspace(*cp))
332                          *cp++ = '\0';
# Line 288 | Line 342 | mg_parse()                     /* parse current input line */
342                  return(MG_OK);          /* no words in line */
343          *ap = NULL;
344                                          /* else handle it */
345 <        return(handle_it(-1, ap-argv, argv));
345 >        return(mg_handle(-1, ap-argv, argv));
346   }
347  
348  
# Line 298 | Line 352 | char   *fn;
352   {
353          MG_FCTXT        cntxt;
354          int     rval;
355 +        register int    nbr;
356  
357          if ((rval = mg_open(&cntxt, fn)) != MG_OK) {
358 <                fprintf("%s: %s\n", fn, mg_err[rval]);
358 >                fprintf(stderr, "%s: %s\n", fn, mg_err[rval]);
359                  return(rval);
360          }
361 <        while (mg_read())               /* parse each line */
361 >        while ((nbr = mg_read()) > 0) { /* parse each line */
362 >                if (nbr >= MG_MAXLINE-1) {
363 >                        fprintf(stderr, "%s: %d: %s\n", cntxt.fname,
364 >                                        cntxt.lineno, mg_err[rval=MG_ELINE]);
365 >                        break;
366 >                }
367                  if ((rval = mg_parse()) != MG_OK) {
368                          fprintf(stderr, "%s: %d: %s:\n%s", cntxt.fname,
369                                          cntxt.lineno, mg_err[rval],
370                                          cntxt.inpline);
371                          break;
372                  }
373 +        }
374          mg_close();
375          return(rval);
376   }
377  
378  
379 < void
380 < mg_clear()                      /* clear parser history */
379 > int
380 > mg_defuhand(ac, av)             /* default handler for unknown entities */
381 > int     ac;
382 > char    **av;
383   {
384 <        c_clearall();                   /* clear context tables */
385 <        mg_file = NULL;                 /* reset our context */
384 >        if (mg_nunknown++ == 0)         /* report first incident */
385 >                fprintf(stderr, "%s: %d: %s: %s\n", mg_file->fname,
386 >                                mg_file->lineno, mg_err[MG_EUNK], av[0]);
387 >        return(MG_OK);
388   }
389  
390  
391 < int
392 < mg_iterate(ac, av, f)           /* iterate on statement */
328 < int     ac;
329 < register char   **av;
330 < int     (*f)();
391 > void
392 > mg_clear()                      /* clear parser history */
393   {
394 <        int     niter, rval;
395 <        register int    i, j;
396 <        char    *argv[MG_MAXARGC];
335 <        char    cntbuf[10];
336 <                                        /* build partial transformation */
337 <        for (i = 0; i < ac; i++) {
338 <                if (av[i][0] == '-' && av[i][1] == 'a' && av[i][2] == '\0')
339 <                        break;
340 <                argv[i+1] = av[i];
341 <        }
342 <        argv[i+1] = NULL;
343 <        if (i) {                        /* handle transformation */
344 <                argv[0] = mg_ename[MG_E_XF];
345 <                if ((rval = handle_it(MG_E_XF, i+1, argv)) != MG_OK)
346 <                        return(rval);
347 <        }
348 <        if (i < ac) {                   /* run array */
349 <                if (i+1 >= ac || !isint(av[i+1]))
350 <                        return(MG_ETYPE);
351 <                niter = atoi(av[i+1]);
352 <                argv[0] = "-i";
353 <                argv[1] = cntbuf;
354 <                for (j = 2; j+i < ac; j++)
355 <                        argv[j] = av[j+i];
356 <                argv[j] = NULL;
357 <                for (j = 0; j < niter; j++) {
358 <                        sprintf(cntbuf, "%d", j);
359 <                        if ((rval = mg_iterate(ac-i, argv, f)) != MG_OK)
360 <                                return(rval);
361 <                }
362 <        } else if ((rval = (*f)()) != MG_OK)    /* else do this instance */
363 <                        return(rval);
364 <        if (i) {                        /* reset the transform */
365 <                argv[0] = mg_ename[MG_E_XF];
366 <                argv[1] = NULL;
367 <                (void)handle_it(MG_E_XF, 1, argv);
368 <        }
369 <        return(MG_OK);
394 >        c_clearall();                   /* clear context tables */
395 >        while (mg_file != NULL)         /* reset our file context */
396 >                mg_close();
397   }
398  
399  
# Line 384 | Line 411 | char   **av;
411   }
412  
413  
414 < static int
388 < reload_file()                   /* reload current MGF file */
389 < {
390 <        register int    rval;
391 <
392 <        if ((rval = mg_rewind()) != MG_OK)
393 <                return(rval);
394 <        while (mg_read())
395 <                if ((rval = mg_parse()) != MG_OK)
396 <                        return(rval);
397 <        return(MG_OK);
398 < }
399 <
400 <
401 < static int
414 > int
415   e_include(ac, av)               /* include file */
416   int     ac;
417   char    **av;
418   {
419 +        char    *xfarg[MG_MAXARGC];
420          MG_FCTXT        ictx;
421 <        int     rv;
421 >        XF_SPEC *xf_orig = xf_context;
422 >        register int    rv;
423  
424          if (ac < 2)
425                  return(MG_EARGC);
426          if ((rv = mg_open(&ictx, av[1])) != MG_OK)
427                  return(rv);
428 <        if ((rv = mg_iterate(ac-2, av+2, reload_file)) != MG_OK) {
429 <                fprintf(stderr, "%s: %d: %s:\n%s", ictx.fname,
430 <                                ictx.lineno, mg_err[rv], ictx.inpline);
431 <                mg_close();
432 <                return(MG_EINCL);
428 >        if (ac > 2) {
429 >                register int    i;
430 >
431 >                xfarg[0] = mg_ename[MG_E_XF];
432 >                for (i = 1; i < ac-1; i++)
433 >                        xfarg[i] = av[i+1];
434 >                xfarg[ac-1] = NULL;
435 >                if ((rv = mg_handle(MG_E_XF, ac-1, xfarg)) != MG_OK) {
436 >                        mg_close();
437 >                        return(rv);
438 >                }
439          }
440 +        do {
441 +                while ((rv = mg_read()) > 0) {
442 +                        if (rv >= MG_MAXLINE-1) {
443 +                                fprintf(stderr, "%s: %d: %s\n", ictx.fname,
444 +                                                ictx.lineno, mg_err[MG_ELINE]);
445 +                                mg_close();
446 +                                return(MG_EINCL);
447 +                        }
448 +                        if ((rv = mg_parse()) != MG_OK) {
449 +                                fprintf(stderr, "%s: %d: %s:\n%s", ictx.fname,
450 +                                                ictx.lineno, mg_err[rv],
451 +                                                ictx.inpline);
452 +                                mg_close();
453 +                                return(MG_EINCL);
454 +                        }
455 +                }
456 +                if (ac > 2)
457 +                        if ((rv = mg_handle(MG_E_XF, 1, xfarg)) != MG_OK) {
458 +                                mg_close();
459 +                                return(rv);
460 +                        }
461 +        } while (xf_context != xf_orig);
462          mg_close();
463          return(MG_OK);
464   }
# Line 438 | Line 481 | FVECT  u, v, w;
481   }
482  
483  
484 < static int
484 > int
485   e_sph(ac, av)                   /* expand a sphere into cones */
486   int     ac;
487   char    **av;
# Line 463 | Line 506 | char   **av;
506          rad = atof(av[2]);
507                                          /* initialize */
508          warpconends = 1;
509 <        if ((rval = handle_it(MG_E_VERTEX, 3, v2ent)) != MG_OK)
509 >        if ((rval = mg_handle(MG_E_VERTEX, 3, v2ent)) != MG_OK)
510                  return(rval);
511          sprintf(p2x, FLTFMT, cv->p[0]);
512          sprintf(p2y, FLTFMT, cv->p[1]);
513          sprintf(p2z, FLTFMT, cv->p[2]+rad);
514 <        if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK)
514 >        if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK)
515                  return(rval);
516          r2[0] = '0'; r2[1] = '\0';
517          for (i = 1; i <= 2*mg_nqcdivs; i++) {
518                  theta = i*(PI/2)/mg_nqcdivs;
519 <                if ((rval = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK)
519 >                if ((rval = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK)
520                          return(rval);
521                  sprintf(p2z, FLTFMT, cv->p[2]+rad*cos(theta));
522 <                if ((rval = handle_it(MG_E_VERTEX, 2, v2ent)) != MG_OK)
522 >                if ((rval = mg_handle(MG_E_VERTEX, 2, v2ent)) != MG_OK)
523                          return(rval);
524 <                if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK)
524 >                if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK)
525                          return(rval);
526                  strcpy(r1, r2);
527                  sprintf(r2, FLTFMT, rad*sin(theta));
528 <                if ((rval = handle_it(MG_E_CONE, 5, conent)) != MG_OK)
528 >                if ((rval = mg_handle(MG_E_CONE, 5, conent)) != MG_OK)
529                          return(rval);
530          }
531          warpconends = 0;
# Line 490 | Line 533 | char   **av;
533   }
534  
535  
536 < static int
536 > int
537   e_torus(ac, av)                 /* expand a torus into cones */
538   int     ac;
539   char    **av;
# Line 511 | Line 554 | char   **av;
554                  return(MG_EARGC);
555          if ((cv = c_getvert(av[1])) == NULL)
556                  return(MG_EUNDEF);
557 <        if (cv->n[0]==0. && cv->n[1]==0. && cv->n[2]==0.)
557 >        if (is0vect(cv->n))
558                  return(MG_EILL);
559          if (!isflt(av[2]) || !isflt(av[3]))
560                  return(MG_ETYPE);
561          minrad = atof(av[2]);
562 +        round0(minrad);
563          maxrad = atof(av[3]);
564                                          /* check orientation */
565          if (minrad > 0.)
# Line 536 | Line 580 | char   **av;
580          for (j = 0; j < 3; j++)
581                  sprintf(p2[j], FLTFMT, cv->p[j] +
582                                  .5*sgn*(maxrad-minrad)*cv->n[j]);
583 <        if ((rval = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK)
583 >        if ((rval = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK)
584                  return(rval);
585 <        if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK)
585 >        if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK)
586                  return(rval);
587          sprintf(r2, FLTFMT, avgrad=.5*(minrad+maxrad));
588                                          /* run outer section */
589          for (i = 1; i <= 2*mg_nqcdivs; i++) {
590                  theta = i*(PI/2)/mg_nqcdivs;
591 <                if ((rval = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK)
591 >                if ((rval = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK)
592                          return(rval);
593                  for (j = 0; j < 3; j++)
594                          sprintf(p2[j], FLTFMT, cv->p[j] +
595                                  .5*sgn*(maxrad-minrad)*cos(theta)*cv->n[j]);
596 <                if ((rval = handle_it(MG_E_VERTEX, 2, v2ent)) != MG_OK)
596 >                if ((rval = mg_handle(MG_E_VERTEX, 2, v2ent)) != MG_OK)
597                          return(rval);
598 <                if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK)
598 >                if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK)
599                          return(rval);
600                  strcpy(r1, r2);
601                  sprintf(r2, FLTFMT, avgrad + .5*(maxrad-minrad)*sin(theta));
602 <                if ((rval = handle_it(MG_E_CONE, 5, conent)) != MG_OK)
602 >                if ((rval = mg_handle(MG_E_CONE, 5, conent)) != MG_OK)
603                          return(rval);
604          }
605                                          /* run inner section */
# Line 565 | Line 609 | char   **av;
609                  for (j = 0; j < 3; j++)
610                          sprintf(p2[j], FLTFMT, cv->p[j] +
611                                  .5*sgn*(maxrad-minrad)*cos(theta)*cv->n[j]);
612 <                if ((rval = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK)
612 >                if ((rval = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK)
613                          return(rval);
614 <                if ((rval = handle_it(MG_E_VERTEX, 2, v2ent)) != MG_OK)
614 >                if ((rval = mg_handle(MG_E_VERTEX, 2, v2ent)) != MG_OK)
615                          return(rval);
616 <                if ((rval = handle_it(MG_E_POINT, 4, p2ent)) != MG_OK)
616 >                if ((rval = mg_handle(MG_E_POINT, 4, p2ent)) != MG_OK)
617                          return(rval);
618                  strcpy(r1, r2);
619                  sprintf(r2, FLTFMT, -avgrad - .5*(maxrad-minrad)*sin(theta));
620 <                if ((rval = handle_it(MG_E_CONE, 5, conent)) != MG_OK)
620 >                if ((rval = mg_handle(MG_E_CONE, 5, conent)) != MG_OK)
621                          return(rval);
622          }
623          warpconends = 0;
# Line 581 | Line 625 | char   **av;
625   }
626  
627  
628 < static int
628 > int
629   e_cyl(ac, av)                   /* replace a cylinder with equivalent cone */
630   int     ac;
631   char    **av;
# Line 594 | Line 638 | char   **av;
638          avnew[2] = av[2];
639          avnew[3] = av[3];
640          avnew[4] = av[2];
641 <        return(handle_it(MG_E_CONE, 5, avnew));
641 >        return(mg_handle(MG_E_CONE, 5, avnew));
642   }
643  
644  
645 < static int
645 > int
646   e_ring(ac, av)                  /* turn a ring into polygons */
647   int     ac;
648   char    **av;
# Line 623 | Line 667 | char   **av;
667                  return(MG_EARGC);
668          if ((cv = c_getvert(av[1])) == NULL)
669                  return(MG_EUNDEF);
670 <        if (cv->n[0]==0. && cv->n[1]==0. && cv->n[2]==0.)
670 >        if (is0vect(cv->n))
671                  return(MG_EILL);
672          if (!isflt(av[2]) || !isflt(av[3]))
673                  return(MG_ETYPE);
674          minrad = atof(av[2]);
675 +        round0(minrad);
676          maxrad = atof(av[3]);
677          if (minrad < 0. || maxrad <= minrad)
678                  return(MG_EILL);
# Line 635 | Line 680 | char   **av;
680          make_axes(u, v, cv->n);
681          for (j = 0; j < 3; j++)
682                  sprintf(p3[j], FLTFMT, cv->p[j] + maxrad*u[j]);
683 <        if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK)
683 >        if ((rv = mg_handle(MG_E_VERTEX, 3, v3ent)) != MG_OK)
684                  return(rv);
685 <        if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK)
685 >        if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK)
686                  return(rv);
687          if (minrad == 0.) {             /* closed */
688                  v1ent[3] = av[1];
689 <                if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK)
689 >                if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK)
690                          return(rv);
691 <                if ((rv = handle_it(MG_E_NORMAL, 4, nzent)) != MG_OK)
691 >                if ((rv = mg_handle(MG_E_NORMAL, 4, nzent)) != MG_OK)
692                          return(rv);
693                  for (i = 1; i <= 4*mg_nqcdivs; i++) {
694                          theta = i*(PI/2)/mg_nqcdivs;
695 <                        if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK)
695 >                        if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK)
696                                  return(rv);
697                          for (j = 0; j < 3; j++)
698                                  sprintf(p3[j], FLTFMT, cv->p[j] +
699                                                  maxrad*u[j]*cos(theta) +
700                                                  maxrad*v[j]*sin(theta));
701 <                        if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK)
701 >                        if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK)
702                                  return(rv);
703 <                        if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK)
703 >                        if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK)
704                                  return(rv);
705 <                        if ((rv = handle_it(MG_E_FACE, 4, fent)) != MG_OK)
705 >                        if ((rv = mg_handle(MG_E_FACE, 4, fent)) != MG_OK)
706                                  return(rv);
707                  }
708          } else {                        /* open */
709 <                if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK)
709 >                if ((rv = mg_handle(MG_E_VERTEX, 3, v4ent)) != MG_OK)
710                          return(rv);
711                  for (j = 0; j < 3; j++)
712                          sprintf(p4[j], FLTFMT, cv->p[j] + minrad*u[j]);
713 <                if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK)
713 >                if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK)
714                          return(rv);
715                  v1ent[3] = "_rv4";
716                  for (i = 1; i <= 4*mg_nqcdivs; i++) {
717                          theta = i*(PI/2)/mg_nqcdivs;
718 <                        if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK)
718 >                        if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK)
719                                  return(rv);
720 <                        if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK)
720 >                        if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK)
721                                  return(rv);
722                          for (j = 0; j < 3; j++) {
723                                  d = u[j]*cos(theta) + v[j]*sin(theta);
724                                  sprintf(p3[j], FLTFMT, cv->p[j] + maxrad*d);
725                                  sprintf(p4[j], FLTFMT, cv->p[j] + minrad*d);
726                          }
727 <                        if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK)
727 >                        if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK)
728                                  return(rv);
729 <                        if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK)
729 >                        if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK)
730                                  return(rv);
731 <                        if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK)
731 >                        if ((rv = mg_handle(MG_E_VERTEX, 2, v4ent)) != MG_OK)
732                                  return(rv);
733 <                        if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK)
733 >                        if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK)
734                                  return(rv);
735 <                        if ((rv = handle_it(MG_E_FACE, 5, fent)) != MG_OK)
735 >                        if ((rv = mg_handle(MG_E_FACE, 5, fent)) != MG_OK)
736                                  return(rv);
737                  }
738          }
# Line 695 | Line 740 | char   **av;
740   }
741  
742  
743 < static int
743 > int
744   e_cone(ac, av)                  /* turn a cone into polygons */
745   int     ac;
746   char    **av;
# Line 710 | Line 755 | char   **av;
755          static char     *p4ent[5] = {mg_ename[MG_E_POINT],p4[0],p4[1],p4[2]};
756          static char     *n4ent[5] = {mg_ename[MG_E_NORMAL],n4[0],n4[1],n4[2]};
757          static char     *fent[6] = {mg_ename[MG_E_FACE],"_cv1","_cv2","_cv3","_cv4"};
758 +        char    *v1n;
759          register C_VERTEX       *cv1, *cv2;
760          register int    i, j;
761          FVECT   u, v, w;
# Line 725 | Line 771 | char   **av;
771          if ((cv1 = c_getvert(av[1])) == NULL ||
772                          (cv2 = c_getvert(av[3])) == NULL)
773                  return(MG_EUNDEF);
774 +        v1n = av[1];
775          if (!isflt(av[2]) || !isflt(av[4]))
776                  return(MG_ETYPE);
777          rad1 = atof(av[2]);
778 +        round0(rad1);
779          rad2 = atof(av[4]);
780 +        round0(rad2);
781          if (rad1 == 0.) {
782                  if (rad2 == 0.)
783                          return(MG_EILL);
# Line 741 | Line 790 | char   **av;
790                  cv = cv1;
791                  cv1 = cv2;
792                  cv2 = cv;
793 +                v1n = av[3];
794                  d = rad1;
795                  rad1 = rad2;
796                  rad2 = d;
# Line 752 | Line 802 | char   **av;
802          if ((d = normalize(w)) == 0.)
803                  return(MG_EILL);
804          n1off = n2off = (rad2 - rad1)/d;
805 <        if (warpconends)                /* hack for e_sph and e_torus */
806 <                n2off = tan(atan(n2off)-(PI/4)/mg_nqcdivs);
807 <        n2off = sgn*n2off;
805 >        if (warpconends) {              /* hack for e_sph and e_torus */
806 >                d = atan(n2off) - (PI/4)/mg_nqcdivs;
807 >                if (d <= -PI/2+FTINY)
808 >                        n2off = -FHUGE;
809 >                else
810 >                        n2off = tan(d);
811 >        }
812          make_axes(u, v, w);
813          for (j = 0; j < 3; j++) {
814                  sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*u[j]);
815 <                sprintf(n3[j], FLTFMT, u[j] + w[j]*n2off);
815 >                if (n2off <= -FHUGE)
816 >                        sprintf(n3[j], FLTFMT, -w[j]);
817 >                else
818 >                        sprintf(n3[j], FLTFMT, u[j] + w[j]*n2off);
819          }
820 <        if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK)
820 >        if ((rv = mg_handle(MG_E_VERTEX, 3, v3ent)) != MG_OK)
821                  return(rv);
822 <        if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK)
822 >        if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK)
823                  return(rv);
824 <        if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK)
824 >        if ((rv = mg_handle(MG_E_NORMAL, 4, n3ent)) != MG_OK)
825                  return(rv);
826          if (rad1 == 0.) {               /* triangles */
827 <                v1ent[3] = av[1];
828 <                if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK)
827 >                v1ent[3] = v1n;
828 >                if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK)
829                          return(rv);
830                  for (j = 0; j < 3; j++)
831                          sprintf(n4[j], FLTFMT, w[j]);
832 <                if ((rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK)
832 >                if ((rv = mg_handle(MG_E_NORMAL, 4, n4ent)) != MG_OK)
833                          return(rv);
834                  for (i = 1; i <= 4*mg_nqcdivs; i++) {
835                          theta = sgn*i*(PI/2)/mg_nqcdivs;
836 <                        if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK)
836 >                        if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK)
837                                  return(rv);
838                          for (j = 0; j < 3; j++) {
839                                  d = u[j]*cos(theta) + v[j]*sin(theta);
840                                  sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*d);
841 <                                sprintf(n3[j], FLTFMT, d + w[j]*n2off);
841 >                                if (n2off > -FHUGE)
842 >                                        sprintf(n3[j], FLTFMT, d + w[j]*n2off);
843                          }
844 <                        if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK)
844 >                        if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK)
845                                  return(rv);
846 <                        if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK)
846 >                        if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK)
847                                  return(rv);
848 <                        if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK)
848 >                        if (n2off > -FHUGE &&
849 >                        (rv = mg_handle(MG_E_NORMAL, 4, n3ent)) != MG_OK)
850                                  return(rv);
851 <                        if ((rv = handle_it(MG_E_FACE, 4, fent)) != MG_OK)
851 >                        if ((rv = mg_handle(MG_E_FACE, 4, fent)) != MG_OK)
852                                  return(rv);
853                  }
854          } else {                        /* quads */
855                  v1ent[3] = "_cv4";
856 <                if (warpconends)                /* hack for e_sph and e_torus */
857 <                        n1off = tan(atan(n1off)+(PI/4)/mg_nqcdivs);
858 <                n1off = sgn*n1off;
856 >                if (warpconends) {              /* hack for e_sph and e_torus */
857 >                        d = atan(n1off) + (PI/4)/mg_nqcdivs;
858 >                        if (d >= PI/2-FTINY)
859 >                                n1off = FHUGE;
860 >                        else
861 >                                n1off = tan(atan(n1off)+(PI/4)/mg_nqcdivs);
862 >                }
863                  for (j = 0; j < 3; j++) {
864                          sprintf(p4[j], FLTFMT, cv1->p[j] + rad1*u[j]);
865 <                        sprintf(n4[j], FLTFMT, u[j] + w[j]*n1off);
865 >                        if (n1off >= FHUGE)
866 >                                sprintf(n4[j], FLTFMT, w[j]);
867 >                        else
868 >                                sprintf(n4[j], FLTFMT, u[j] + w[j]*n1off);
869                  }
870 <                if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK)
870 >                if ((rv = mg_handle(MG_E_VERTEX, 3, v4ent)) != MG_OK)
871                          return(rv);
872 <                if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK)
872 >                if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK)
873                          return(rv);
874 <                if ((rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK)
874 >                if ((rv = mg_handle(MG_E_NORMAL, 4, n4ent)) != MG_OK)
875                          return(rv);
876                  for (i = 1; i <= 4*mg_nqcdivs; i++) {
877                          theta = sgn*i*(PI/2)/mg_nqcdivs;
878 <                        if ((rv = handle_it(MG_E_VERTEX, 4, v1ent)) != MG_OK)
878 >                        if ((rv = mg_handle(MG_E_VERTEX, 4, v1ent)) != MG_OK)
879                                  return(rv);
880 <                        if ((rv = handle_it(MG_E_VERTEX, 4, v2ent)) != MG_OK)
880 >                        if ((rv = mg_handle(MG_E_VERTEX, 4, v2ent)) != MG_OK)
881                                  return(rv);
882                          for (j = 0; j < 3; j++) {
883                                  d = u[j]*cos(theta) + v[j]*sin(theta);
884                                  sprintf(p3[j], FLTFMT, cv2->p[j] + rad2*d);
885 <                                sprintf(n3[j], FLTFMT, d + w[j]*n2off);
885 >                                if (n2off > -FHUGE)
886 >                                        sprintf(n3[j], FLTFMT, d + w[j]*n2off);
887                                  sprintf(p4[j], FLTFMT, cv1->p[j] + rad1*d);
888 <                                sprintf(n4[j], FLTFMT, d + w[j]*n1off);
888 >                                if (n1off < FHUGE)
889 >                                        sprintf(n4[j], FLTFMT, d + w[j]*n1off);
890                          }
891 <                        if ((rv = handle_it(MG_E_VERTEX, 3, v3ent)) != MG_OK)
891 >                        if ((rv = mg_handle(MG_E_VERTEX, 2, v3ent)) != MG_OK)
892                                  return(rv);
893 <                        if ((rv = handle_it(MG_E_POINT, 4, p3ent)) != MG_OK)
893 >                        if ((rv = mg_handle(MG_E_POINT, 4, p3ent)) != MG_OK)
894                                  return(rv);
895 <                        if ((rv = handle_it(MG_E_NORMAL, 4, n3ent)) != MG_OK)
895 >                        if (n2off > -FHUGE &&
896 >                        (rv = mg_handle(MG_E_NORMAL, 4, n3ent)) != MG_OK)
897                                  return(rv);
898 <                        if ((rv = handle_it(MG_E_VERTEX, 3, v4ent)) != MG_OK)
898 >                        if ((rv = mg_handle(MG_E_VERTEX, 2, v4ent)) != MG_OK)
899                                  return(rv);
900 <                        if ((rv = handle_it(MG_E_POINT, 4, p4ent)) != MG_OK)
900 >                        if ((rv = mg_handle(MG_E_POINT, 4, p4ent)) != MG_OK)
901                                  return(rv);
902 <                        if ((rv = handle_it(MG_E_NORMAL, 4, n4ent)) != MG_OK)
902 >                        if (n1off < FHUGE &&
903 >                        (rv = mg_handle(MG_E_NORMAL, 4, n4ent)) != MG_OK)
904                                  return(rv);
905 <                        if ((rv = handle_it(MG_E_FACE, 5, fent)) != MG_OK)
905 >                        if ((rv = mg_handle(MG_E_FACE, 5, fent)) != MG_OK)
906                                  return(rv);
907                  }
908          }
909 +        return(MG_OK);
910 + }
911 +
912 +
913 + int
914 + e_prism(ac, av)                 /* turn a prism into polygons */
915 + int     ac;
916 + char    **av;
917 + {
918 +        static char     p[3][24];
919 +        static char     *vent[5] = {mg_ename[MG_E_VERTEX],NULL,"="};
920 +        static char     *pent[5] = {mg_ename[MG_E_POINT],p[0],p[1],p[2]};
921 +        static char     *znorm[5] = {mg_ename[MG_E_NORMAL],"0","0","0"};
922 +        char    *newav[MG_MAXARGC], nvn[MG_MAXARGC-1][8];
923 +        double  length;
924 +        int     hasnorm;
925 +        FVECT   v1, v2, v3, norm;
926 +        register C_VERTEX       *cv;
927 +        C_VERTEX        *cv0;
928 +        int     rv;
929 +        register int    i, j;
930 +                                                /* check arguments */
931 +        if (ac < 5)
932 +                return(MG_EARGC);
933 +        if (!isflt(av[ac-1]))
934 +                return(MG_ETYPE);
935 +        length = atof(av[ac-1]);
936 +        if (length <= FTINY && length >= -FTINY)
937 +                return(MG_EILL);
938 +                                                /* compute face normal */
939 +        if ((cv0 = c_getvert(av[1])) == NULL)
940 +                return(MG_EUNDEF);
941 +        hasnorm = 0;
942 +        norm[0] = norm[1] = norm[2] = 0.;
943 +        v1[0] = v1[1] = v1[2] = 0.;
944 +        for (i = 2; i < ac-1; i++) {
945 +                if ((cv = c_getvert(av[i])) == NULL)
946 +                        return(MG_EUNDEF);
947 +                hasnorm += !is0vect(cv->n);
948 +                v2[0] = cv->p[0] - cv0->p[0];
949 +                v2[1] = cv->p[1] - cv0->p[1];
950 +                v2[2] = cv->p[2] - cv0->p[2];
951 +                fcross(v3, v1, v2);
952 +                norm[0] += v3[0];
953 +                norm[1] += v3[1];
954 +                norm[2] += v3[2];
955 +                VCOPY(v1, v2);
956 +        }
957 +        if (normalize(norm) == 0.)
958 +                return(MG_EILL);
959 +                                                /* create moved vertices */
960 +        for (i = 1; i < ac-1; i++) {
961 +                sprintf(nvn[i-1], "_pv%d", i);
962 +                vent[1] = nvn[i-1];
963 +                vent[3] = av[i];
964 +                if ((rv = mg_handle(MG_E_VERTEX, 4, vent)) != MG_OK)
965 +                        return(rv);
966 +                cv = c_getvert(av[i]);          /* checked above */
967 +                for (j = 0; j < 3; j++)
968 +                        sprintf(p[j], FLTFMT, cv->p[j] - length*norm[j]);
969 +                if ((rv = mg_handle(MG_E_POINT, 4, pent)) != MG_OK)
970 +                        return(rv);
971 +        }
972 +                                                /* make faces */
973 +        newav[0] = mg_ename[MG_E_FACE];
974 +                                                /* do the side faces */
975 +        newav[5] = NULL;
976 +        newav[3] = av[ac-2];
977 +        newav[4] = nvn[ac-3];
978 +        for (i = 1; i < ac-1; i++) {
979 +                newav[1] = nvn[i-1];
980 +                newav[2] = av[i];
981 +                if ((rv = mg_handle(MG_E_FACE, 5, newav)) != MG_OK)
982 +                        return(rv);
983 +                newav[3] = newav[2];
984 +                newav[4] = newav[1];
985 +        }
986 +                                                /* do top face */
987 +        for (i = 1; i < ac-1; i++) {
988 +                if (hasnorm) {                  /* zero normals */
989 +                        vent[1] = nvn[i-1];
990 +                        if ((rv = mg_handle(MG_E_VERTEX, 2, vent)) != MG_OK)
991 +                                return(rv);
992 +                        if ((rv = mg_handle(MG_E_NORMAL, 4, znorm)) != MG_OK)
993 +                                return(rv);
994 +                }
995 +                newav[ac-1-i] = nvn[i-1];       /* reverse */
996 +        }
997 +        if ((rv = mg_handle(MG_E_FACE, ac-1, newav)) != MG_OK)
998 +                return(rv);
999 +                                                /* do bottom face */
1000 +        if (hasnorm)
1001 +                for (i = 1; i < ac-1; i++) {
1002 +                        vent[1] = nvn[i-1];
1003 +                        vent[3] = av[i];
1004 +                        if ((rv = mg_handle(MG_E_VERTEX, 4, vent)) != MG_OK)
1005 +                                return(rv);
1006 +                        if ((rv = mg_handle(MG_E_NORMAL, 4, znorm)) != MG_OK)
1007 +                                return(rv);
1008 +                        newav[i] = nvn[i-1];
1009 +                }
1010 +        else
1011 +                for (i = 1; i < ac-1; i++)
1012 +                        newav[i] = av[i];
1013 +        newav[i] = NULL;
1014 +        if ((rv = mg_handle(MG_E_FACE, i, newav)) != MG_OK)
1015 +                return(rv);
1016 +        return(MG_OK);
1017 + }
1018 +
1019 +
1020 + static int
1021 + put_cxy()                       /* put out current xy chromaticities */
1022 + {
1023 +        static char     xbuf[24], ybuf[24];
1024 +        static char     *ccom[4] = {mg_ename[MG_E_CXY], xbuf, ybuf};
1025 +
1026 +        sprintf(xbuf, "%.4f", c_ccolor->cx);
1027 +        sprintf(ybuf, "%.4f", c_ccolor->cy);
1028 +        return(mg_handle(MG_E_CXY, 3, ccom));
1029 + }
1030 +
1031 +
1032 + static int
1033 + put_cspec()                     /* put out current color spectrum */
1034 + {
1035 +        char    wl[2][6], vbuf[C_CNSS][24];
1036 +        char    *newav[C_CNSS+4];
1037 +        double  sf;
1038 +        register int    i;
1039 +
1040 +        if (mg_ehand[MG_E_CSPEC] != c_hcolor) {
1041 +                sprintf(wl[0], "%d", C_CMINWL);
1042 +                sprintf(wl[1], "%d", C_CMAXWL);
1043 +                newav[0] = mg_ename[MG_E_CSPEC];
1044 +                newav[1] = wl[0];
1045 +                newav[2] = wl[1];
1046 +                sf = (double)C_CNSS / c_ccolor->ssum;
1047 +                for (i = 0; i < C_CNSS; i++) {
1048 +                        sprintf(vbuf[i], "%.4f", sf*c_ccolor->ssamp[i]);
1049 +                        newav[i+3] = vbuf[i];
1050 +                }
1051 +                newav[C_CNSS+3] = NULL;
1052 +                if ((i = mg_handle(MG_E_CSPEC, C_CNSS+3, newav)) != MG_OK)
1053 +                        return(i);
1054 +        }
1055 +        return(MG_OK);
1056 + }
1057 +
1058 +
1059 + static int
1060 + e_cspec(ac, av)                 /* handle spectral color */
1061 + int     ac;
1062 + char    **av;
1063 + {
1064 +                                /* convert to xy chromaticity */
1065 +        c_ccvt(c_ccolor, C_CSXY);
1066 +                                /* if it's really their handler, use it */
1067 +        if (mg_ehand[MG_E_CXY] != c_hcolor)
1068 +                return(put_cxy());
1069 +        return(MG_OK);
1070 + }
1071 +
1072 +
1073 + static int
1074 + e_cmix(ac, av)                  /* handle mixing of colors */
1075 + int     ac;
1076 + char    **av;
1077 + {
1078 +        /*
1079 +         * Contorted logic works as follows:
1080 +         *      1. the colors are already mixed in c_hcolor() support function
1081 +         *      2. if we would handle a spectral result, make sure it's not
1082 +         *      3. if c_hcolor() would handle a spectral result, don't bother
1083 +         *      4. otherwise, make cspec entity and pass it to their handler
1084 +         *      5. if we have only xy results, handle it as c_spec() would
1085 +         */
1086 +        if (mg_ehand[MG_E_CSPEC] == e_cspec)
1087 +                c_ccvt(c_ccolor, C_CSXY);
1088 +        else if (c_ccolor->flags & C_CDSPEC)
1089 +                return(put_cspec());
1090 +        if (mg_ehand[MG_E_CXY] != c_hcolor)
1091 +                return(put_cxy());
1092 +        return(MG_OK);
1093 + }
1094 +
1095 +
1096 + static int
1097 + e_cct(ac, av)                   /* handle color temperature */
1098 + int     ac;
1099 + char    **av;
1100 + {
1101 +        /*
1102 +         * Logic is similar to e_cmix here.  Support handler has already
1103 +         * converted temperature to spectral color.  Put it out as such
1104 +         * if they support it, otherwise convert to xy chromaticity and
1105 +         * put it out if they handle it.
1106 +         */
1107 +        if (mg_ehand[MG_E_CSPEC] != e_cspec)
1108 +                return(put_cspec());
1109 +        c_ccvt(c_ccolor, C_CSXY);
1110 +        if (mg_ehand[MG_E_CXY] != c_hcolor)
1111 +                return(put_cxy());
1112          return(MG_OK);
1113   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines