1 /* Copyright (C) 1992-1998 The Geometry Center
2 * Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips
3 *
4 * This file is part of Geomview.
5 *
6 * Geomview is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * Geomview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with Geomview; see the file COPYING. If not, write
18 * to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
19 * USA, or visit http://www.gnu.org.
20 */
21
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #if 0
27 static char copyright[] = "Copyright (C) 1992-1998 The Geometry Center\n\
28 Copyright (C) 1998-2000 Stuart Levy, Tamara Munzner, Mark Phillips";
29 #endif
30
31
32 /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
33
34 #include <ctype.h>
35 #include "discgrpP.h"
36 #include "options.h"
37 #include "complex.h" /* in case file has elements of SL(2,C) */
38 #include <string.h>
39 #include "mgP.h"
40 #include "streampool.h"
41 #include "transobj.h"
42 #include "handleP.h"
43 #include "projective.h"
44
45 int fsaparse();
46
47 #define DG_GROUPNAME 1
48 #define DG_COMMENT 2
49 #define DG_ATTRIBUTE 3
50 #define DG_MODEL 4
51 #define DG_NGENS 5
52 #define DG_NELS 6
53 #define DG_GENS 7
54 #define DG_ELS 8
55 #define DG_DIMN 9
56 #define DG_CAMGEOM 10
57 #define DG_GEOM 11
58 #define DG_CAMGEOMFILE 12
59 #define DG_GEOMFILE 13
60 #define DG_WAFILE 14
61 #define DG_MATRIXGROUP 15
62 #define DG_CPOINT 16
63 #define DG_ENUMDEPTH 17
64 #define DG_ENUMDIST 18
65 #define DG_DSPYATTR 19
66 #define DG_SCALE 20
67 #define DG_C2M 21
68 #define DG_DRAWDIST 22
69 #define DG_NUMKEYWORDS 24 /* 2 redundant keywords */
70
71 keytokenpair keytokenlist[] = {
72 {"group", DG_GROUPNAME},
73 {"comment", DG_COMMENT},
74 {"attribute", DG_ATTRIBUTE},
75 {"model", DG_MODEL},
76 {"ngens", DG_NGENS},
77 {"nels", DG_NELS},
78 {"gens", DG_GENS},
79 {"els", DG_ELS},
80 {"dimn", DG_DIMN},
81 {"dimension", DG_DIMN},
82 {"camgeom", DG_CAMGEOM},
83 {"geom", DG_GEOM},
84 {"camgeomfile", DG_CAMGEOMFILE},
85 {"geomfile", DG_GEOMFILE},
86 {"wafile", DG_WAFILE},
87 {"matrixgroup", DG_MATRIXGROUP},
88 {"mgroup", DG_MATRIXGROUP},
89 {"cpoint", DG_CPOINT},
90 {"enumdepth", DG_ENUMDEPTH},
91 {"enumdist", DG_ENUMDIST},
92 {"drawdist", DG_DRAWDIST},
93 {"display", DG_DSPYATTR},
94 {"scale", DG_SCALE},
95 {"cam2model", DG_C2M}
96 };
97
98 keytokenpair attr_list[DG_NUM_ATTR] = {
99 {"hyperbolic", DG_HYPERBOLIC},
100 {"euclidean", DG_EUCLIDEAN},
101 {"spherical", DG_SPHERICAL},
102 {"finite", DG_FINITE},
103 {"transposed", DG_TRANSPOSED},
104 {"conformalball", DG_CONFORMALBALL},
105 {"upperhalfspace", DG_UPPERHALFSPACE},
106 {"projective", DG_PROJECTIVEMODEL}
107 };
108
109 keytokenpair dspyattr_list[DG_NUM_DSPYATTR] = {
110 {"centercam", DG_CENTERCAM},
111 {"zcull", DG_ZCULL},
112 {"drawcam", DG_DRAWCAM},
113 {"drawdirdom", DG_DRAWDIRDOM},
114 {"drawgeom", DG_DRAWGEOM}
115 };
116
117 /* Name can be {GL | SL | SO } ( {n},{k},{R | C} ) */
118 matrixgroup cgroup = { DG_GENERAL | DG_REAL, 4, 0};
119
120 static char delims[] = "%{}();";
121 static char errfmt[] = "Reading discrete group from \"%s\": %s";
122
123 static int
token_from_string(char * s,keytokenpair * kl,int n)124 token_from_string(char *s, keytokenpair *kl, int n)
125 {
126 int i;
127 for (i=0; i<n; ++i) {
128 if (strcasecmp(s, kl[i].key) == 0)
129 return (kl[i].token);
130 }
131 return (0);
132 }
133
134
135 /* following gets the next %keyword from file.
136 returns 0 if EOF, otherwise 1 */
137 static int
get_keyword(IOBFILE * fp,char keyword[],char * fname)138 get_keyword(IOBFILE *fp, char keyword[], char *fname)
139 {
140 switch(iobfnextc(fp, 0)) {
141 case EOF:
142 return 0;
143
144 case CKET:
145 return 0;
146
147 case '(':
148 iobfgetc(fp);
149 sprintf(keyword, "%.31s", iobfdelimtok(delims, fp, 0));
150 return 1;
151
152 default:
153 OOGLSyntax(fp,
154 "Reading discrete group from \"%s\": expected (", fname);
155 return(0);
156 }
157 }
158
159 static int
get_matching_parenthesis(IOBFILE * fp,char * fname)160 get_matching_parenthesis(IOBFILE *fp, char *fname)
161 {
162 int t = iobfnextc(fp, 0);
163 if (t == EOF) return(0);
164 if (t != ')') {
165 OOGLSyntax(fp,"Reading discrete group from \"%s\": expected matching )", fname);
166 return(0);
167 }
168 iobfgetc(fp);
169 return(1);
170 }
171
172 static IOBFILE *
included_file(IOBFILE * fp)173 included_file(IOBFILE *fp)
174 {
175 char *name;
176
177 if (iobfnextc(fp, 0) == '<') /* read from file */
178 {
179 name = iobfdelimtok(delims, fp, 0);
180 OOGLError(1,
181 "Discrete groups: including files "
182 "(here: \"%s\") not implemented", name);
183 return NULL;
184 }
185 return NULL;
186 }
187
188 static void
parse_group_name(char * gname)189 parse_group_name(char *gname)
190 {
191 (void)gname;
192 cgroup.attributes = DG_GENERAL | DG_REAL; /* type of entry */
193 cgroup.dimn = 4; /* dimension of matrices */
194 cgroup.sig = 0; /* signature of quadratic form */
195
196 }
197
198 static ColorA white = {1,1,1,.75};
199
200 static void
get_el_list(DiscGrp * discgrp,DiscGrpElList * dgellist,IOBFILE * fp,char * fname)201 get_el_list( DiscGrp *discgrp, DiscGrpElList *dgellist, IOBFILE *fp, char *fname)
202 {
203 int i;
204 char *name, c;
205
206 if (included_file(fp)) /* read from file */
207 {
208 }
209
210 for (i=0; i<dgellist->num_el; ++i) {
211 dgellist->el_list[i].attributes = 0;
212 dgellist->el_list[i].color = white;
213 dgellist->el_list[i].inverse = NULL;
214 c = iobfnextc(fp, 0);
215 /* get the name if it's alphabetic */
216 if ( c >= 'A' && c <= 'z' )
217 {
218 name = iobfdelimtok(delims, fp, 0);
219 if (strlen(name) > DG_WORDLENGTH) {
220 OOGLSyntax(fp,"Reading discrete group from \"%s\": Words limited to length %d", fname, DG_WORDLENGTH);
221 return;
222 }
223 strcpy(dgellist->el_list[i].word, name);
224 }
225 else { /* make up a name for this gen */
226 dgellist->el_list[i].word[0] = 'a' + i;
227 dgellist->el_list[i].word[1] = 0;
228 }
229
230
231 switch(discgrp->attributes & DG_MODEL_BITS){
232 case DG_CONFORMALBALL:
233 OOGLSyntax(fp,errfmt,fname,"Unimplemented conformal model");
234 break;
235
236 case DG_UPPERHALFSPACE:
237 {
238 sl2c_matrix mylf;
239 proj_matrix mypm;
240 int k,m;
241 for (k=0; k<2; ++k) for (m=0; m<2; ++m) {
242 iobfgetnd(fp, 1, &mylf[k][m].real, 0);
243 iobfgetnd(fp, 1, &mylf[k][m].imag, 0);
244 }
245 sl2c_to_proj(mylf, mypm);
246 for (k=0; k<4; ++k) for (m=0; m<4; ++m)
247 dgellist->el_list[i].tform[k][m] = mypm[k][m];
248 }
249 break;
250
251 default:
252 if (iobfgettransform(fp,1,(float *)dgellist->el_list[i].tform,0) != 1) {
253 OOGLSyntax(fp,errfmt,fname,"Error reading generator");
254 return;
255 }
256 if (discgrp->attributes & DG_TRANSPOSED)
257 TmTranspose(dgellist->el_list[i].tform, discgrp->big_list->el_list[i].tform);
258 break;
259 }
260 }
261 discgrp->attributes &= ~DG_UPPERHALFSPACE;
262 }
263
264 Geom *
DiscGrpImport(Pool * p)265 DiscGrpImport(Pool *p)
266 {
267 char *name, *fname;
268 char keyword[DG_KEYWORDSIZE];
269 DiscGrp *discgrp;
270 IOBFILE *fp;
271 FILE *wafp;
272 char *expect;
273
274 if(p == NULL || (fp = PoolInputFile(p)) == NULL)
275 return 0;
276
277 /* check for 'DISCGRP' at head of file */
278 if(strcmp(GeomToken(fp), "DISCGRP"))
279 return(NULL);
280
281 /* now the parentheses begin */
282 if (iobfnextc(fp, 0) != '(')
283 return(NULL);
284
285 discgrp = (DiscGrp*)GeomCreate("discgrp",CR_END);
286
287 while (get_keyword(fp, keyword,p->poolname)) {
288
289 switch ( token_from_string(keyword, keytokenlist,sizeof(keytokenlist)/sizeof(keytokenpair) )) {
290
291 case DG_WAFILE:
292 name = iobfdelimtok(delims, fp, 0);
293 fname = findfile(PoolName(p), name);
294 if(fname == NULL || (wafp = fopen(fname, "rb")) == NULL) {
295 OOGLSyntax(fp,
296 "Reading discrete group from \"%s\": can't open wafile \"%s\"",
297 p->poolname, name);
298 return(NULL);
299 }
300 discgrp->fsa = OOGLNew(wa);
301 fsaparse(wafp, discgrp->fsa);
302 fclose(wafp);
303 break;
304
305 case DG_DSPYATTR:
306 name = iobfdelimtok(delims, fp, 0);
307 discgrp->flag |= token_from_string(name, dspyattr_list,sizeof(dspyattr_list)/sizeof(keytokenpair));
308 break;
309
310 case DG_ATTRIBUTE:
311 case DG_MODEL:
312 name = iobfdelimtok(delims, fp, 0);
313 discgrp->attributes |= token_from_string(name, attr_list,sizeof(attr_list)/sizeof(keytokenpair));
314 break;
315
316 case DG_COMMENT:
317 discgrp->comment = strdup(iobfdelimtok(delims, fp, 0));
318 break;
319
320 case DG_MATRIXGROUP:
321 parse_group_name(iobfdelimtok(delims, fp, 0));
322 break;
323
324 case DG_SCALE:
325 if(iobfgetnf(fp, 1, &discgrp->scale, 0) <= 0) {
326 OOGLSyntax(fp,errfmt, p->poolname, "Invalid scale");
327 return(NULL);
328 }
329 break;
330
331
332 case DG_C2M:
333 discgrp->c2m = (float (*)[4])OOGLNewNE(float, 16, "Transform");
334 if (iobfgettransform(fp,1,(float *)discgrp->c2m,0) != 1) {
335 OOGLSyntax(fp,errfmt,p->poolname,"Error reading cam2model");
336 return(NULL);
337 }
338 break;
339
340 case DG_ENUMDEPTH:
341 if(iobfgetni(fp, 1, &discgrp->enumdepth, 0) <= 0) {
342 OOGLSyntax(fp,errfmt, p->poolname, "Invalid enumdepth");
343 return(NULL);
344 }
345 break;
346
347 case DG_ENUMDIST:
348 if(iobfgetnf(fp, 1, &discgrp->enumdist, 0) <= 0) {
349 OOGLSyntax(fp,errfmt, p->poolname, "Invalid enumdist");
350 return(NULL);
351 }
352 break;
353
354 case DG_DRAWDIST:
355 if(iobfgetnf(fp, 1, &discgrp->drawdist, 0) <= 0) {
356 OOGLSyntax(fp,errfmt, p->poolname, "Invalid drawdist");
357 return(NULL);
358 }
359 break;
360
361 case DG_CPOINT:
362 if(iobfgetnf(fp, 4, (float *)&discgrp->cpoint, 0) <= 0) {
363 OOGLSyntax(fp,errfmt, p->poolname, "Invalid Cpoint");
364 return(NULL);
365 }
366 break;
367
368 case DG_CAMGEOM:
369 expect = "camgeometry";
370 if(!GeomStreamIn(p, &discgrp->camgeomhandle, &discgrp->camgeom))
371 goto failed;
372 if(discgrp->camgeomhandle)
373 HandleRegister(&discgrp->camgeomhandle, (Ref *)discgrp,
374 &discgrp->camgeom, HandleUpdRef);
375
376 break;
377
378 case DG_ELS:
379 discgrp->big_list->mgroup = cgroup;
380 get_el_list(discgrp, discgrp->big_list, fp, p->poolname);
381 discgrp->flag |= DG_SAVEBIGLIST;
382 break;
383
384 case DG_GROUPNAME:
385 discgrp->name = strdup(iobfdelimtok(delims, fp, 0));
386 break;
387
388 case DG_GENS:
389 {
390 int i;
391 static char name[2] = "a";
392 discgrp->gens->mgroup = cgroup;
393 get_el_list(discgrp, discgrp->gens, fp, p->poolname);
394 /* make up names for the generators if not given */
395 if (strcmp(discgrp->gens->el_list[0].word, "") == 0) {
396 for (i=0; i<discgrp->gens->num_el; ++i) {
397 strcpy(discgrp->gens->el_list[i].word,name);
398 name[0]++;
399 }
400 }
401 }
402
403 break;
404
405 case DG_GEOM:
406 expect = "geometry";
407 if(!GeomStreamIn(p, &discgrp->geomhandle, &discgrp->geom))
408 goto failed;
409 if(discgrp->geomhandle)
410 HandleRegister(&discgrp->geomhandle, (Ref *)discgrp,
411 &discgrp->geom, HandleUpdRef);
412
413 break;
414
415 case DG_DIMN:
416 if(iobfgetni(fp, 1, &discgrp->dimn, 0) <= 0 ||
417 discgrp->dimn > 4) {
418 OOGLSyntax(fp,errfmt, p->poolname, "Invalid Dimension");
419 return(NULL);
420 }
421 cgroup.dimn = discgrp->dimn+1; /* default matrix group */
422 break;
423
424 case DG_NGENS:
425 {
426 int ngens;
427 if(iobfgetni(fp, 1, &ngens, 0) <= 0 || ngens <= 0) {
428 OOGLSyntax(fp,errfmt,p->poolname, "Invalid generator count");
429 return(NULL);
430 }
431 discgrp->gens = OOGLNewE(DiscGrpElList, "DiscGrp gens");
432 discgrp->gens->num_el = ngens;
433 discgrp->gens->el_list = OOGLNewNE(DiscGrpEl,
434 discgrp->gens->num_el, "DiscGrp gens elem list");
435 }
436 break;
437
438 case DG_NELS:
439 {
440 int nels;
441 if(iobfgetni(fp, 1, &nels, 0) <= 0 || nels <= 0) {
442 OOGLSyntax(fp,errfmt,p->poolname, "Invalid generator count");
443 return(NULL);
444 }
445 discgrp->big_list = OOGLNewE(DiscGrpElList, "DiscGrp el_list");
446 discgrp->big_list->num_el = nels;
447 discgrp->big_list->el_list = OOGLNewNE(DiscGrpEl,
448 discgrp->big_list->num_el, "DiscGrp elem list");
449 }
450 break;
451 failed:
452 OOGLSyntax(fp, "Couldn't read DISCGRP in \"%s\": expected %s",
453 PoolName(p), expect);
454 break;
455
456 default:
457 OOGLError(1,"Bad keyword DiscGrpFLoad %s",keyword);
458 break;
459 }
460 if ( !(get_matching_parenthesis(fp,p->poolname))) break;
461 }
462
463 /* make sure the generator list includes all inverses */
464 DiscGrpAddInverses(discgrp);
465
466 /*
467 if (discgrp->geom == NULL)
468 {
469 discgrp->flag |= DG_DRAWDIRDOM;
470 DiscGrpSetupDirdom(discgrp);
471 discgrp->ddgeom = DiscGrpDirDom(discgrp);
472 }
473 */
474
475 if (discgrp->big_list == NULL)
476 {
477 DiscGrpInitStandardConstraint(discgrp->enumdepth, discgrp->enumdist, discgrp->enumdist);
478 discgrp->big_list = DiscGrpEnum(discgrp, DiscGrpStandardConstraint);
479 }
480
481 return(( Geom *) discgrp);
482 }
483
484 /*
485 * Local Variables: ***
486 * mode: c ***
487 * c-basic-offset: 2 ***
488 * End: ***
489 */
490