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