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