| 1 | 
greg | 
1.1 | 
#ifndef lint | 
| 2 | 
greg | 
2.5 | 
static const char       RCSid[] = "$Id$"; | 
| 3 | 
greg | 
1.1 | 
#endif | 
| 4 | 
  | 
  | 
/* | 
| 5 | 
  | 
  | 
 * Replace markers in Radiance scene description with objects or instances. | 
| 6 | 
  | 
  | 
 * | 
| 7 | 
  | 
  | 
 *      Created:        17 Feb 1991     Greg Ward | 
| 8 | 
  | 
  | 
 */ | 
| 9 | 
  | 
  | 
 | 
| 10 | 
  | 
  | 
#include <stdio.h> | 
| 11 | 
greg | 
2.5 | 
#include <stdlib.h> | 
| 12 | 
greg | 
1.1 | 
#include <ctype.h> | 
| 13 | 
  | 
  | 
#include <math.h> | 
| 14 | 
  | 
  | 
 | 
| 15 | 
  | 
  | 
#include "fvect.h" | 
| 16 | 
  | 
  | 
 | 
| 17 | 
  | 
  | 
#ifdef  M_PI | 
| 18 | 
gregl | 
2.4 | 
#define  PI             ((double)M_PI) | 
| 19 | 
greg | 
1.1 | 
#else | 
| 20 | 
  | 
  | 
#define  PI             3.14159265358979323846 | 
| 21 | 
  | 
  | 
#endif | 
| 22 | 
  | 
  | 
 | 
| 23 | 
greg | 
1.2 | 
#define  FEQ(a,b)       ((a)-(b) <= 1e-7 && (b)-(a) <= 1e-7) | 
| 24 | 
  | 
  | 
 | 
| 25 | 
greg | 
1.1 | 
#define  MAXVERT        6       /* maximum number of vertices for markers */ | 
| 26 | 
greg | 
2.2 | 
#define  MAXMARK        32      /* maximum number of markers */ | 
| 27 | 
greg | 
1.1 | 
 | 
| 28 | 
  | 
  | 
typedef struct { | 
| 29 | 
  | 
  | 
        short   beg, end;               /* beginning and ending vertex */ | 
| 30 | 
  | 
  | 
        float   len2;                   /* length squared */ | 
| 31 | 
  | 
  | 
}  EDGE;                        /* a marker edge */ | 
| 32 | 
  | 
  | 
 | 
| 33 | 
greg | 
2.2 | 
struct mrkr { | 
| 34 | 
  | 
  | 
        char    *modout;                /* output modifier */ | 
| 35 | 
  | 
  | 
        double  mscale;                 /* scale by this to get unit */ | 
| 36 | 
  | 
  | 
        char    *modin;                 /* input modifier indicating marker */ | 
| 37 | 
  | 
  | 
        char    *objname;               /* output object file or octree */ | 
| 38 | 
  | 
  | 
        int     doxform;                /* true if xform, false if instance */ | 
| 39 | 
  | 
  | 
}  marker[MAXMARK];             /* array of markers */ | 
| 40 | 
  | 
  | 
int     nmarkers = 0;           /* number of markers */ | 
| 41 | 
greg | 
1.1 | 
 | 
| 42 | 
greg | 
2.2 | 
int     expand;                 /* expand commands? */ | 
| 43 | 
greg | 
1.1 | 
 | 
| 44 | 
  | 
  | 
char    *progname; | 
| 45 | 
  | 
  | 
 | 
| 46 | 
  | 
  | 
 | 
| 47 | 
  | 
  | 
main(argc, argv) | 
| 48 | 
  | 
  | 
int     argc; | 
| 49 | 
  | 
  | 
char    *argv[]; | 
| 50 | 
  | 
  | 
{ | 
| 51 | 
  | 
  | 
        FILE    *fp; | 
| 52 | 
  | 
  | 
        int     i, j; | 
| 53 | 
  | 
  | 
 | 
| 54 | 
  | 
  | 
        progname = argv[0]; | 
| 55 | 
greg | 
2.2 | 
        i = 1; | 
| 56 | 
  | 
  | 
        while (i < argc && argv[i][0] == '-') { | 
| 57 | 
  | 
  | 
                do { | 
| 58 | 
  | 
  | 
                        switch (argv[i][1]) { | 
| 59 | 
  | 
  | 
                        case 'i': | 
| 60 | 
  | 
  | 
                                marker[nmarkers].doxform = 0; | 
| 61 | 
  | 
  | 
                                marker[nmarkers].objname = argv[++i]; | 
| 62 | 
  | 
  | 
                                break; | 
| 63 | 
  | 
  | 
                        case 'x': | 
| 64 | 
  | 
  | 
                                marker[nmarkers].doxform = 1; | 
| 65 | 
  | 
  | 
                                marker[nmarkers].objname = argv[++i]; | 
| 66 | 
  | 
  | 
                                break; | 
| 67 | 
  | 
  | 
                        case 'e': | 
| 68 | 
  | 
  | 
                                expand = 1; | 
| 69 | 
  | 
  | 
                                break; | 
| 70 | 
  | 
  | 
                        case 'm': | 
| 71 | 
  | 
  | 
                                marker[nmarkers].modout = argv[++i]; | 
| 72 | 
  | 
  | 
                                break; | 
| 73 | 
  | 
  | 
                        case 's': | 
| 74 | 
  | 
  | 
                                marker[nmarkers].mscale = atof(argv[++i]); | 
| 75 | 
  | 
  | 
                                break; | 
| 76 | 
  | 
  | 
                        default: | 
| 77 | 
  | 
  | 
                                goto userr; | 
| 78 | 
  | 
  | 
                        } | 
| 79 | 
  | 
  | 
                        if (++i >= argc) | 
| 80 | 
  | 
  | 
                                goto userr; | 
| 81 | 
  | 
  | 
                } while (argv[i][0] == '-'); | 
| 82 | 
  | 
  | 
                if (marker[nmarkers].objname == NULL) | 
| 83 | 
  | 
  | 
                        goto userr; | 
| 84 | 
  | 
  | 
                marker[nmarkers++].modin = argv[i++]; | 
| 85 | 
  | 
  | 
                if (nmarkers >= MAXMARK) | 
| 86 | 
greg | 
1.1 | 
                        break; | 
| 87 | 
greg | 
2.2 | 
                marker[nmarkers].mscale = marker[nmarkers-1].mscale; | 
| 88 | 
  | 
  | 
        } | 
| 89 | 
  | 
  | 
        if (nmarkers == 0) | 
| 90 | 
greg | 
1.1 | 
                goto userr; | 
| 91 | 
  | 
  | 
                                        /* simple header */ | 
| 92 | 
  | 
  | 
        putchar('#'); | 
| 93 | 
  | 
  | 
        for (j = 0; j < i; j++) { | 
| 94 | 
  | 
  | 
                putchar(' '); | 
| 95 | 
  | 
  | 
                fputs(argv[j], stdout); | 
| 96 | 
  | 
  | 
        } | 
| 97 | 
  | 
  | 
        putchar('\n'); | 
| 98 | 
  | 
  | 
        if (i == argc) | 
| 99 | 
  | 
  | 
                convert("<stdin>", stdin); | 
| 100 | 
  | 
  | 
        else | 
| 101 | 
  | 
  | 
                for ( ; i < argc; i++) { | 
| 102 | 
  | 
  | 
                        if ((fp = fopen(argv[i], "r")) == NULL) { | 
| 103 | 
  | 
  | 
                                perror(argv[i]); | 
| 104 | 
  | 
  | 
                                exit(1); | 
| 105 | 
  | 
  | 
                        } | 
| 106 | 
  | 
  | 
                        convert(argv[i], fp); | 
| 107 | 
  | 
  | 
                        fclose(fp); | 
| 108 | 
  | 
  | 
                } | 
| 109 | 
  | 
  | 
        exit(0); | 
| 110 | 
  | 
  | 
userr: | 
| 111 | 
  | 
  | 
        fprintf(stderr, | 
| 112 | 
greg | 
2.2 | 
"Usage: %s [-e][-s size][-m modout] {-x objfile|-i octree} modname .. [file ..]\n", | 
| 113 | 
greg | 
1.1 | 
                progname); | 
| 114 | 
  | 
  | 
        exit(1); | 
| 115 | 
  | 
  | 
} | 
| 116 | 
  | 
  | 
 | 
| 117 | 
  | 
  | 
 | 
| 118 | 
  | 
  | 
convert(name, fin)              /* replace marks in a stream */ | 
| 119 | 
  | 
  | 
char    *name; | 
| 120 | 
  | 
  | 
register FILE   *fin; | 
| 121 | 
  | 
  | 
{ | 
| 122 | 
  | 
  | 
        register int    c; | 
| 123 | 
  | 
  | 
 | 
| 124 | 
  | 
  | 
        while ((c = getc(fin)) != EOF) { | 
| 125 | 
  | 
  | 
                if (isspace(c))                         /* blank */ | 
| 126 | 
  | 
  | 
                        continue; | 
| 127 | 
  | 
  | 
                if (c == '#') {                         /* comment */ | 
| 128 | 
  | 
  | 
                        putchar(c); | 
| 129 | 
  | 
  | 
                        do { | 
| 130 | 
  | 
  | 
                                if ((c = getc(fin)) == EOF) | 
| 131 | 
  | 
  | 
                                        return; | 
| 132 | 
  | 
  | 
                                putchar(c); | 
| 133 | 
  | 
  | 
                        } while (c != '\n'); | 
| 134 | 
  | 
  | 
                } else if (c == '!') {                  /* command */ | 
| 135 | 
  | 
  | 
                        ungetc(c, fin); | 
| 136 | 
  | 
  | 
                        cvcomm(name, fin); | 
| 137 | 
  | 
  | 
                } else {                                /* object */ | 
| 138 | 
  | 
  | 
                        ungetc(c, fin); | 
| 139 | 
  | 
  | 
                        cvobject(name, fin); | 
| 140 | 
  | 
  | 
                } | 
| 141 | 
  | 
  | 
        } | 
| 142 | 
  | 
  | 
} | 
| 143 | 
  | 
  | 
 | 
| 144 | 
  | 
  | 
 | 
| 145 | 
  | 
  | 
cvcomm(fname, fin)              /* convert a command */ | 
| 146 | 
  | 
  | 
char    *fname; | 
| 147 | 
  | 
  | 
FILE    *fin; | 
| 148 | 
  | 
  | 
{ | 
| 149 | 
  | 
  | 
        FILE    *pin, *popen(); | 
| 150 | 
  | 
  | 
        char    buf[512], *fgetline(); | 
| 151 | 
  | 
  | 
 | 
| 152 | 
  | 
  | 
        fgetline(buf, sizeof(buf), fin); | 
| 153 | 
  | 
  | 
        if (expand) { | 
| 154 | 
  | 
  | 
                if ((pin = popen(buf+1, "r")) == NULL) { | 
| 155 | 
  | 
  | 
                        fprintf(stderr, | 
| 156 | 
  | 
  | 
                        "%s: (%s): cannot execute \"%s\"\n", | 
| 157 | 
  | 
  | 
                                        progname, fname, buf); | 
| 158 | 
  | 
  | 
                        exit(1); | 
| 159 | 
  | 
  | 
                } | 
| 160 | 
  | 
  | 
                convert(buf, pin); | 
| 161 | 
  | 
  | 
                pclose(pin); | 
| 162 | 
  | 
  | 
        } else | 
| 163 | 
  | 
  | 
                printf("\n%s\n", buf); | 
| 164 | 
  | 
  | 
} | 
| 165 | 
  | 
  | 
 | 
| 166 | 
  | 
  | 
 | 
| 167 | 
  | 
  | 
cvobject(fname, fin)            /* convert an object */ | 
| 168 | 
  | 
  | 
char    *fname; | 
| 169 | 
  | 
  | 
FILE    *fin; | 
| 170 | 
  | 
  | 
{ | 
| 171 | 
  | 
  | 
        char    buf[128], typ[16], nam[128]; | 
| 172 | 
greg | 
2.2 | 
        int     i, n; | 
| 173 | 
  | 
  | 
        register int    j; | 
| 174 | 
greg | 
1.1 | 
 | 
| 175 | 
  | 
  | 
        if (fscanf(fin, "%s %s %s", buf, typ, nam) != 3) | 
| 176 | 
  | 
  | 
                goto readerr; | 
| 177 | 
greg | 
2.2 | 
        if (!strcmp(typ, "polygon")) | 
| 178 | 
  | 
  | 
                for (j = 0; j < nmarkers; j++) | 
| 179 | 
  | 
  | 
                        if (!strcmp(buf, marker[j].modin)) { | 
| 180 | 
  | 
  | 
                                replace(fname, &marker[j], nam, fin); | 
| 181 | 
  | 
  | 
                                return; | 
| 182 | 
  | 
  | 
                        } | 
| 183 | 
greg | 
1.1 | 
        printf("\n%s %s %s\n", buf, typ, nam); | 
| 184 | 
  | 
  | 
        if (!strcmp(typ, "alias")) {            /* alias special case */ | 
| 185 | 
  | 
  | 
                if (fscanf(fin, "%s", buf) != 1) | 
| 186 | 
  | 
  | 
                        goto readerr; | 
| 187 | 
  | 
  | 
                printf("\t%s\n", buf); | 
| 188 | 
  | 
  | 
                return; | 
| 189 | 
  | 
  | 
        } | 
| 190 | 
  | 
  | 
        for (i = 0; i < 3; i++) {               /* pass along arguments */ | 
| 191 | 
  | 
  | 
                if (fscanf(fin, "%d", &n) != 1) | 
| 192 | 
  | 
  | 
                        goto readerr; | 
| 193 | 
  | 
  | 
                printf("%d", n); | 
| 194 | 
  | 
  | 
                for (j = 0; j < n; j++) { | 
| 195 | 
greg | 
2.5 | 
                        if (fgetword(buf, sizeof(buf), fin) == NULL) | 
| 196 | 
greg | 
1.1 | 
                                goto readerr; | 
| 197 | 
  | 
  | 
                        if (j%3 == 0) | 
| 198 | 
  | 
  | 
                                putchar('\n'); | 
| 199 | 
greg | 
2.5 | 
                        putchar('\t'); | 
| 200 | 
  | 
  | 
                        fputword(buf, stdout); | 
| 201 | 
greg | 
1.1 | 
                } | 
| 202 | 
  | 
  | 
                putchar('\n'); | 
| 203 | 
  | 
  | 
        } | 
| 204 | 
  | 
  | 
        return; | 
| 205 | 
  | 
  | 
readerr: | 
| 206 | 
  | 
  | 
        fprintf(stderr, "%s: (%s): read error for %s \"%s\"\n", | 
| 207 | 
  | 
  | 
                        progname, fname, typ, nam); | 
| 208 | 
  | 
  | 
} | 
| 209 | 
  | 
  | 
 | 
| 210 | 
  | 
  | 
 | 
| 211 | 
greg | 
2.2 | 
replace(fname, m, mark, fin)            /* replace marker */ | 
| 212 | 
  | 
  | 
char    *fname; | 
| 213 | 
  | 
  | 
register struct mrkr    *m; | 
| 214 | 
  | 
  | 
char    *mark; | 
| 215 | 
greg | 
1.1 | 
FILE    *fin; | 
| 216 | 
  | 
  | 
{ | 
| 217 | 
  | 
  | 
        int     n; | 
| 218 | 
  | 
  | 
        char    buf[256]; | 
| 219 | 
  | 
  | 
 | 
| 220 | 
greg | 
2.5 | 
        buf[0] = '\0';                  /* bug fix thanks to schorsch */ | 
| 221 | 
greg | 
2.2 | 
        if (m->doxform) { | 
| 222 | 
greg | 
1.1 | 
                sprintf(buf, "xform -e -n %s", mark); | 
| 223 | 
greg | 
2.2 | 
                if (m->modout != NULL) | 
| 224 | 
  | 
  | 
                        sprintf(buf+strlen(buf), " -m %s", m->modout); | 
| 225 | 
  | 
  | 
                if (buildxf(buf+strlen(buf), m->mscale, fin) < 0) | 
| 226 | 
greg | 
1.1 | 
                        goto badxf; | 
| 227 | 
greg | 
2.2 | 
                sprintf(buf+strlen(buf), " %s", m->objname); | 
| 228 | 
greg | 
1.1 | 
                if (expand) { | 
| 229 | 
  | 
  | 
                        fflush(stdout); | 
| 230 | 
  | 
  | 
                        system(buf); | 
| 231 | 
  | 
  | 
                } else | 
| 232 | 
  | 
  | 
                        printf("\n!%s\n", buf); | 
| 233 | 
  | 
  | 
        } else { | 
| 234 | 
greg | 
2.2 | 
                if ((n = buildxf(buf, m->mscale, fin)) < 0) | 
| 235 | 
greg | 
1.1 | 
                        goto badxf; | 
| 236 | 
greg | 
2.2 | 
                printf("\n%s instance %s\n", | 
| 237 | 
  | 
  | 
                                m->modout==NULL?"void":m->modout, mark); | 
| 238 | 
  | 
  | 
                printf("%d %s%s\n0\n0\n", n+1, m->objname, buf); | 
| 239 | 
greg | 
1.1 | 
        } | 
| 240 | 
  | 
  | 
        return; | 
| 241 | 
  | 
  | 
badxf: | 
| 242 | 
  | 
  | 
        fprintf(stderr, "%s: (%s): bad arguments for marker \"%s\"\n", | 
| 243 | 
  | 
  | 
                        progname, fname, mark); | 
| 244 | 
  | 
  | 
        exit(1); | 
| 245 | 
  | 
  | 
} | 
| 246 | 
  | 
  | 
 | 
| 247 | 
  | 
  | 
 | 
| 248 | 
  | 
  | 
edgecmp(e1, e2)                 /* compare two edges, descending order */ | 
| 249 | 
  | 
  | 
EDGE    *e1, *e2; | 
| 250 | 
  | 
  | 
{ | 
| 251 | 
  | 
  | 
        if (e1->len2 > e2->len2) | 
| 252 | 
  | 
  | 
                return(-1); | 
| 253 | 
  | 
  | 
        if (e1->len2 < e2->len2) | 
| 254 | 
  | 
  | 
                return(1); | 
| 255 | 
  | 
  | 
        return(0); | 
| 256 | 
  | 
  | 
} | 
| 257 | 
  | 
  | 
 | 
| 258 | 
  | 
  | 
 | 
| 259 | 
  | 
  | 
int | 
| 260 | 
greg | 
2.2 | 
buildxf(xf, markscale, fin)             /* build transform for marker */ | 
| 261 | 
greg | 
2.5 | 
register char   *xf; | 
| 262 | 
greg | 
2.2 | 
double  markscale; | 
| 263 | 
greg | 
1.1 | 
FILE    *fin; | 
| 264 | 
  | 
  | 
{ | 
| 265 | 
  | 
  | 
        static FVECT    vlist[MAXVERT]; | 
| 266 | 
  | 
  | 
        static EDGE     elist[MAXVERT]; | 
| 267 | 
  | 
  | 
        FVECT   xvec, yvec, zvec; | 
| 268 | 
  | 
  | 
        double  xlen; | 
| 269 | 
  | 
  | 
        int     n; | 
| 270 | 
  | 
  | 
        register int    i; | 
| 271 | 
  | 
  | 
        /* | 
| 272 | 
  | 
  | 
         * Read and sort vectors:  longest is hypotenuse, | 
| 273 | 
  | 
  | 
         *      second longest is x' axis, | 
| 274 | 
  | 
  | 
         *      third longest is y' axis (approximate), | 
| 275 | 
  | 
  | 
         *      other vectors are ignored. | 
| 276 | 
  | 
  | 
         * It is an error if the x' and y' axes do | 
| 277 | 
  | 
  | 
         *      not share a common vertex (their origin). | 
| 278 | 
  | 
  | 
         */ | 
| 279 | 
  | 
  | 
        if (fscanf(fin, "%*d %*d %d", &n) != 1) | 
| 280 | 
  | 
  | 
                return(-1); | 
| 281 | 
  | 
  | 
        if (n%3 != 0) | 
| 282 | 
  | 
  | 
                return(-1); | 
| 283 | 
  | 
  | 
        n /= 3; | 
| 284 | 
  | 
  | 
        if (n < 3 || n > MAXVERT) | 
| 285 | 
  | 
  | 
                return(-1); | 
| 286 | 
  | 
  | 
                                        /* sort edges in descending order */ | 
| 287 | 
  | 
  | 
        for (i = 0; i < n; i++) { | 
| 288 | 
  | 
  | 
                if (fscanf(fin, "%lf %lf %lf", &vlist[i][0], | 
| 289 | 
  | 
  | 
                                &vlist[i][1], &vlist[i][2]) != 3) | 
| 290 | 
  | 
  | 
                        return(-1); | 
| 291 | 
  | 
  | 
                if (i) { | 
| 292 | 
  | 
  | 
                        elist[i].beg = i-1; | 
| 293 | 
  | 
  | 
                        elist[i].end = i; | 
| 294 | 
  | 
  | 
                        elist[i].len2 = dist2(vlist[i-1],vlist[i]); | 
| 295 | 
  | 
  | 
                } | 
| 296 | 
  | 
  | 
        } | 
| 297 | 
  | 
  | 
        elist[0].beg = n-1; | 
| 298 | 
  | 
  | 
        elist[0].end = 0; | 
| 299 | 
  | 
  | 
        elist[0].len2 = dist2(vlist[n-1],vlist[0]); | 
| 300 | 
  | 
  | 
        qsort(elist, n, sizeof(EDGE), edgecmp); | 
| 301 | 
  | 
  | 
                                        /* find x' and y' */ | 
| 302 | 
  | 
  | 
        if (elist[1].end == elist[2].beg || elist[1].end == elist[2].end) { | 
| 303 | 
  | 
  | 
                i = elist[1].beg; | 
| 304 | 
  | 
  | 
                elist[1].beg = elist[1].end; | 
| 305 | 
  | 
  | 
                elist[1].end = i; | 
| 306 | 
  | 
  | 
        } | 
| 307 | 
  | 
  | 
        if (elist[2].end == elist[1].beg) { | 
| 308 | 
  | 
  | 
                i = elist[2].beg; | 
| 309 | 
  | 
  | 
                elist[2].beg = elist[2].end; | 
| 310 | 
  | 
  | 
                elist[2].end = i; | 
| 311 | 
  | 
  | 
        } | 
| 312 | 
  | 
  | 
        if (elist[1].beg != elist[2].beg) | 
| 313 | 
  | 
  | 
                return(-1);             /* x' and y' not connected! */ | 
| 314 | 
  | 
  | 
        for (i = 0; i < 3; i++) { | 
| 315 | 
  | 
  | 
                xvec[i] = vlist[elist[1].end][i] - vlist[elist[1].beg][i]; | 
| 316 | 
  | 
  | 
                yvec[i] = vlist[elist[2].end][i] - vlist[elist[2].beg][i]; | 
| 317 | 
  | 
  | 
        } | 
| 318 | 
  | 
  | 
        if ((xlen = normalize(xvec)) == 0.0) | 
| 319 | 
  | 
  | 
                return(-1); | 
| 320 | 
  | 
  | 
        fcross(zvec, xvec, yvec); | 
| 321 | 
  | 
  | 
        if (normalize(zvec) == 0.0) | 
| 322 | 
  | 
  | 
                return(-1); | 
| 323 | 
  | 
  | 
        fcross(yvec, zvec, xvec); | 
| 324 | 
  | 
  | 
        n = 0;                          /* start transformation... */ | 
| 325 | 
  | 
  | 
        if (markscale > 0.0) {          /* add scale factor */ | 
| 326 | 
  | 
  | 
                sprintf(xf, " -s %f", xlen*markscale); | 
| 327 | 
  | 
  | 
                n += 2; | 
| 328 | 
greg | 
2.5 | 
                while (*xf) ++xf; | 
| 329 | 
greg | 
1.1 | 
        } | 
| 330 | 
  | 
  | 
                                        /* add rotation */ | 
| 331 | 
  | 
  | 
        n += addrot(xf, xvec, yvec, zvec); | 
| 332 | 
greg | 
2.5 | 
        while (*xf) ++xf; | 
| 333 | 
greg | 
1.1 | 
                                        /* add translation */ | 
| 334 | 
  | 
  | 
        n += 4; | 
| 335 | 
  | 
  | 
        sprintf(xf, " -t %f %f %f", vlist[elist[1].beg][0], | 
| 336 | 
  | 
  | 
                        vlist[elist[1].beg][1], vlist[elist[1].beg][2]); | 
| 337 | 
  | 
  | 
        return(n);                      /* all done */ | 
| 338 | 
  | 
  | 
} | 
| 339 | 
  | 
  | 
 | 
| 340 | 
  | 
  | 
 | 
| 341 | 
  | 
  | 
addrot(xf, xp, yp, zp)          /* compute rotation (x,y,z) => (xp,yp,zp) */ | 
| 342 | 
greg | 
2.5 | 
register char   *xf; | 
| 343 | 
greg | 
1.1 | 
FVECT   xp, yp, zp; | 
| 344 | 
  | 
  | 
{ | 
| 345 | 
greg | 
1.2 | 
        int     n; | 
| 346 | 
  | 
  | 
        double  theta; | 
| 347 | 
greg | 
1.1 | 
 | 
| 348 | 
greg | 
1.2 | 
        n = 0; | 
| 349 | 
  | 
  | 
        theta = atan2(yp[2], zp[2]); | 
| 350 | 
  | 
  | 
        if (!FEQ(theta,0.0)) { | 
| 351 | 
  | 
  | 
                sprintf(xf, " -rx %f", theta*(180./PI)); | 
| 352 | 
greg | 
2.5 | 
                while (*xf) ++xf; | 
| 353 | 
greg | 
1.2 | 
                n += 2; | 
| 354 | 
  | 
  | 
        } | 
| 355 | 
  | 
  | 
        theta = asin(-xp[2]); | 
| 356 | 
  | 
  | 
        if (!FEQ(theta,0.0)) { | 
| 357 | 
  | 
  | 
                sprintf(xf, " -ry %f", theta*(180./PI)); | 
| 358 | 
greg | 
2.5 | 
                while (*xf) ++xf; | 
| 359 | 
greg | 
1.2 | 
                n += 2; | 
| 360 | 
  | 
  | 
        } | 
| 361 | 
  | 
  | 
        theta = atan2(xp[1], xp[0]); | 
| 362 | 
  | 
  | 
        if (!FEQ(theta,0.0)) { | 
| 363 | 
  | 
  | 
                sprintf(xf, " -rz %f", theta*(180./PI)); | 
| 364 | 
greg | 
2.5 | 
                /* while (*xf) ++xf; */ | 
| 365 | 
greg | 
1.2 | 
                n += 2; | 
| 366 | 
  | 
  | 
        } | 
| 367 | 
  | 
  | 
        return(n); | 
| 368 | 
greg | 
1.1 | 
} |