| 1 |
#ifndef lint
|
| 2 |
static const char RCSid[] = "$Id: mgf2meta.c,v 2.11 2003/11/17 13:20:10 schorsch Exp $";
|
| 3 |
#endif
|
| 4 |
/*
|
| 5 |
* Convert MGF (Materials and Geometry Format) to Metafile 2-d graphics
|
| 6 |
*/
|
| 7 |
|
| 8 |
#include <stdio.h>
|
| 9 |
#include <stdlib.h>
|
| 10 |
#include <string.h>
|
| 11 |
#include <math.h>
|
| 12 |
|
| 13 |
#include "meta.h"
|
| 14 |
#include "random.h"
|
| 15 |
#include "mgf_parser.h"
|
| 16 |
#include "plocate.h" /* XXX shouldn't this rather be in rtmath.h? */
|
| 17 |
|
| 18 |
#define MSIZE ((1<<14)-1)
|
| 19 |
#define MX(v) (int)(MSIZE*(v)[(proj_axis+1)%3])
|
| 20 |
#define MY(v) (int)(MSIZE*(v)[(proj_axis+2)%3])
|
| 21 |
|
| 22 |
int proj_axis;
|
| 23 |
double limit[3][2];
|
| 24 |
int layer;
|
| 25 |
long rthresh = 1;
|
| 26 |
|
| 27 |
extern int mg_nqcdivs;
|
| 28 |
|
| 29 |
static int r_face(int ac, char **av);
|
| 30 |
static void newlayer(void);
|
| 31 |
static int doline(int v1x, int v1y, int v2x, int v2y);
|
| 32 |
|
| 33 |
|
| 34 |
int
|
| 35 |
main( /* convert files to stdout */
|
| 36 |
int argc,
|
| 37 |
char *argv[]
|
| 38 |
)
|
| 39 |
{
|
| 40 |
int i;
|
| 41 |
/* initialize dispatch table */
|
| 42 |
mg_ehand[MG_E_FACE] = r_face;
|
| 43 |
mg_ehand[MG_E_POINT] = c_hvertex;
|
| 44 |
mg_ehand[MG_E_VERTEX] = c_hvertex;
|
| 45 |
mg_ehand[MG_E_XF] = xf_handler;
|
| 46 |
mg_nqcdivs = 3; /* reduce object subdivision */
|
| 47 |
mg_init(); /* initialize the parser */
|
| 48 |
/* get arguments */
|
| 49 |
if (argc > 9 && !strcmp(argv[1], "-t")) {
|
| 50 |
rthresh = atof(argv[2])*MSIZE + 0.5;
|
| 51 |
rthresh *= rthresh;
|
| 52 |
argv += 2;
|
| 53 |
argc -= 2;
|
| 54 |
}
|
| 55 |
if (argc < 8 || (proj_axis = argv[1][0]-'x') < 0 || proj_axis > 2)
|
| 56 |
goto userr;
|
| 57 |
limit[0][0] = atof(argv[2]); limit[0][1] = atof(argv[3]);
|
| 58 |
limit[1][0] = atof(argv[4]); limit[1][1] = atof(argv[5]);
|
| 59 |
limit[2][0] = atof(argv[6]); limit[2][1] = atof(argv[7]);
|
| 60 |
|
| 61 |
if (argc == 8) { /* convert stdin */
|
| 62 |
if (mg_load(NULL) != MG_OK)
|
| 63 |
exit(1);
|
| 64 |
} else /* convert each file */
|
| 65 |
for (i = 8; i < argc; i++) {
|
| 66 |
if (mg_load(argv[i]) != MG_OK)
|
| 67 |
exit(1);
|
| 68 |
newlayer();
|
| 69 |
}
|
| 70 |
mendpage(); /* print page */
|
| 71 |
mdone(); /* close output */
|
| 72 |
exit(0);
|
| 73 |
userr:
|
| 74 |
fputs("Usage: mgf2meta [-t thresh] {x|y|z} xmin xmax ymin ymax zmin zmax [file.mgf] ..\n",
|
| 75 |
stderr);
|
| 76 |
exit(1);
|
| 77 |
}
|
| 78 |
|
| 79 |
|
| 80 |
int
|
| 81 |
r_face( /* convert a face */
|
| 82 |
int ac,
|
| 83 |
char **av
|
| 84 |
)
|
| 85 |
{
|
| 86 |
static FVECT bbmin = {0,0,0}, bbmax = {1,1,1};
|
| 87 |
register int i, j;
|
| 88 |
register C_VERTEX *cv;
|
| 89 |
FVECT v1, v2, vo;
|
| 90 |
|
| 91 |
if (ac < 4)
|
| 92 |
return(MG_EARGC);
|
| 93 |
/* connect to last point */
|
| 94 |
if ((cv = c_getvert(av[ac-1])) == NULL)
|
| 95 |
return(MG_EUNDEF);
|
| 96 |
xf_xfmpoint(vo, cv->p);
|
| 97 |
for (j = 0; j < 3; j++)
|
| 98 |
vo[j] = (vo[j] - limit[j][0])/(limit[j][1]-limit[j][0]);
|
| 99 |
for (i = 1; i < ac; i++) { /* go around face */
|
| 100 |
if ((cv = c_getvert(av[i])) == NULL)
|
| 101 |
return(MG_EUNDEF);
|
| 102 |
xf_xfmpoint(v2, cv->p);
|
| 103 |
for (j = 0; j < 3; j++)
|
| 104 |
v2[j] = (v2[j] - limit[j][0])/(limit[j][1]-limit[j][0]);
|
| 105 |
VCOPY(v1, vo);
|
| 106 |
VCOPY(vo, v2);
|
| 107 |
if (clip(v1, v2, bbmin, bbmax))
|
| 108 |
doline(MX(v1), MY(v1), MX(v2), MY(v2));
|
| 109 |
}
|
| 110 |
return(MG_OK);
|
| 111 |
}
|
| 112 |
|
| 113 |
|
| 114 |
#define HTBLSIZ 16381 /* prime hash table size */
|
| 115 |
|
| 116 |
short hshtab[HTBLSIZ][4]; /* done line segments */
|
| 117 |
|
| 118 |
#define hash(mx1,my1,mx2,my2) ((long)(mx1)<<15 ^ (long)(my1)<<10 ^ \
|
| 119 |
(long)(mx2)<<5 ^ (long)(my2))
|
| 120 |
|
| 121 |
|
| 122 |
void
|
| 123 |
newlayer(void) /* start a new layer */
|
| 124 |
{
|
| 125 |
(void)memset((char *)hshtab, '\0', sizeof(hshtab));
|
| 126 |
if (++layer >= 16) {
|
| 127 |
mendpage();
|
| 128 |
layer = 0;
|
| 129 |
}
|
| 130 |
}
|
| 131 |
|
| 132 |
|
| 133 |
int
|
| 134 |
doline( /* draw line conditionally */
|
| 135 |
int v1x,
|
| 136 |
int v1y,
|
| 137 |
int v2x,
|
| 138 |
int v2y
|
| 139 |
)
|
| 140 |
{
|
| 141 |
register int h;
|
| 142 |
|
| 143 |
if (v1x > v2x || (v1x == v2x && v1y > v2y)) { /* sort endpoints */
|
| 144 |
h=v1x; v1x=v2x; v2x=h;
|
| 145 |
h=v1y; v1y=v2y; v2y=h;
|
| 146 |
}
|
| 147 |
h = hash(v1x, v1y, v2x, v2y) % HTBLSIZ;
|
| 148 |
if (hshtab[h][0] == v1x && hshtab[h][1] == v1y &&
|
| 149 |
hshtab[h][2] == v2x && hshtab[h][3] == v2y)
|
| 150 |
return(0);
|
| 151 |
hshtab[h][0] = v1x; hshtab[h][1] = v1y;
|
| 152 |
hshtab[h][2] = v2x; hshtab[h][3] = v2y;
|
| 153 |
if ((long)(v2x-v1x)*(v2x-v1x) + (long)(v2y-v1y)*(v2y-v1y)
|
| 154 |
<= random() % rthresh)
|
| 155 |
return(0);
|
| 156 |
mline(v1x, v1y, layer/4, 0, layer%4);
|
| 157 |
mdraw(v2x, v2y);
|
| 158 |
return(1);
|
| 159 |
}
|