1 /*
2  * gdsreader - simple Calma parser/printer tool
3  * Copyright (C) 1999 Serban-Mihai Popescu, serbanp@ix.netcom.com
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <math.h>
23 
24 #include <GDSstructs.h>
25 #include <GDSconsts.h>
26 #include <GDSaux.h>
27 #include <GDSreader.h>
28 #include <GDSboundary.h>
29 #include <GDSpath.h>
30 #include <GDSsref.h>
31 #include <GDSaref.h>
32 #include <GDStext.h>
33 #include <GDStext.h>
34 #include <GDSnode.h>
35 #include <GDSbox.h>
36 #include <GDSstruct.h>
37 #include <GDStransf.h>
38 #include <GDSparser.h>
39 /*
40 static char
41 *PSInit[] =
42 {
43 
44 };
45 */
46 
47 
48 extern PSStyle psStyles[];
49 extern int howmanylayers; /* set by GDSinitPSStyles(cfgfileptr); in GDStoPS.c */
50 
51 
52 /*
53    Layer to style...  Map layer to style number using best find.
54    all layers have gdsno and datatype, not all styles have datatype
55    Ugh...  What about layers that have no entry in config file?  Damn.
56    We need to return a number for a style that is hidden.  I will make
57    a dummy [0] style with a neg gds number which will always be present.
58 
59    Ugh.  That also means I have to modify the GDStoPS and GDStoHPGL
60    converters to ignore entry zero.  Damn, this code sucks.
61 
62 */
layer_to_style_no(layer * layerptr)63 int layer_to_style_no(layer *layerptr)
64 {
65  int i,generic=-1;
66  for(i=0;i<howmanylayers;i++) {
67    if (psStyles[i].gdsno==layerptr->layerno && psStyles[i].dataspec
68            && psStyles[i].datatype==layerptr->datatype)
69               {
70                 return(i); /* Perfect Match */
71               }
72    if (psStyles[i].gdsno==layerptr->layerno && !(psStyles[i].dataspec)) generic=i;
73   }
74  if (generic!=-1) {
75    return(generic);
76   }
77  fprintf(stderr,"Warning: Layer %d, datatype %d found with no corresponding\n"
78                 " layer entry in configuration file.\n",
79           layerptr->layerno,layerptr->datatype);
80  /* exit(1); */
81  return(0);  /* Dummy hidden layer */
82 }
83 
84 
85 
86 
87 /* Returns true if any part of structure is visible, actually
88  returns number of items visible.  Subitems count as one. */
is_visible(GDSstruct * structptr)89 int is_visible(GDSstruct *structptr)
90 {
91  layer *lp;
92  GDScell *cellptr;
93  int vis=0;
94   lp=structptr->layers;
95   while (lp!=NULL) {
96    if (!psStyles[layer_to_style_no(lp)].hidden) {
97      vis++;
98     }
99    lp=lp->next;
100   }
101  /* Now we must check srefs and arefs if they are present. */
102  cellptr=structptr->cells;
103  while (cellptr!=NULL) {
104   switch(cellptr->type)
105       {
106         case SREF:
107            if (is_visible(cellptr->detail.aref->strptr)) vis++;
108           break;
109         case AREF:
110            if (is_visible(cellptr->detail.sref->strptr)) vis++;
111           break;
112         default:
113           break;
114       }
115    cellptr=cellptr->next;
116   }
117  return(vis);
118 }
119 
120 /* Dump a particular cell declaration to the file.
121    We need to see if any of the layers are visible first, also
122    check if only a single subcell VISIBLE, no union or braces....
123    note this is not topcellname here really...  */
124 void
GDStoPOVCell(GDSlibrary * libptr,FILE * povfileptr,char * topcellname)125 GDStoPOVCell(GDSlibrary *libptr, FILE *povfileptr, char *topcellname)
126 {
127   GDSstruct *structptr;
128   GDScell *cellptr;
129   bbox bbx;
130   char *esctopcell=NULL;
131 
132   double scalex, scaley, scale;
133   int i=0,subcells=0;
134 
135 
136   structptr = GDSgetStructByName(libptr, topcellname);
137   if(structptr == NULL)
138   {
139     fprintf(stderr, "Couldn't find the structure named \"%s\"\n",
140             topcellname);
141     return;
142   }
143   /* We should check to see if any of the layers in this cell are visible.  If
144      not, then we should draw no structure(s)? */
145   /* Visibility check */
146 
147   if (!(subcells=is_visible(structptr))) return;
148 
149   bbx = GDSgetStructBBox(structptr);
150 
151   scalex = 8.5 * InternalScaleFactor * 72.0 * 0.85 / (bbx.ur.x - bbx.ll.x);
152   scaley = 11.0 * InternalScaleFactor * 72.0 * 0.85 / (bbx.ur.y - bbx.ll.y);
153   fprintf(stderr, "scalex = %f, scaley = %f\n", scalex, scaley);
154   scale = (scalex < scaley) ? scalex : scaley;
155 
156   /* Loop through any layers not invisible. */
157   esctopcell=GDSEscPovString(topcellname);
158   if (subcells>1) {
159     fprintf(povfileptr,"#declare %s = union {\n",esctopcell);
160   } else {
161     fprintf(povfileptr,"#declare %s = \n",esctopcell);
162   }
163 
164     /* Loop through cells */
165     for(cellptr = structptr->cells; cellptr != NULL;
166         cellptr = cellptr->next)
167     {
168       switch(cellptr->type)
169       {
170         case BOUNDARY: /* All drawing is actually done here. */
171           if (!(psStyles[i=layer_to_style_no(cellptr->detail.boundary->layerptr)].hidden))
172           BoundaryToPOV(povfileptr, cellptr->detail.boundary,
173                        psStyles[i]);
174           break;
175         case PATH:
176           if (!(psStyles[i=layer_to_style_no(cellptr->detail.path->layerptr)].hidden))
177           PathToPOV(povfileptr, cellptr->detail.path, psStyles[i]);
178           break;
179         case SREF:
180            if (is_visible(cellptr->detail.sref->strptr))
181               SrefToPOV(povfileptr, cellptr->detail.sref, &Ident, psStyles[i]);
182           break;
183         case AREF: /* calls sref for each element in the array */
184           fprintf(povfileptr,"//Aref:\n");
185            if (is_visible(cellptr->detail.aref->strptr))
186               ArefToPOV(povfileptr, cellptr->detail.aref, &Ident, psStyles[i]);
187           break;
188         case TEXT: /* does nothing in POV yet */
189           if (!psStyles[i=layer_to_style_no(cellptr->detail.text->layerptr)].hidden)
190             TextToPOV(povfileptr, cellptr->detail.text, &Ident, psStyles[i]);
191           break;
192         case NODE: /* does nothing? */
193           if (!psStyles[i=layer_to_style_no(cellptr->detail.node->layerptr)].hidden)
194             NodeToPOV(povfileptr, cellptr->detail.node, psStyles[i]);
195           break;
196         case BOX: /* does nothing? */
197           if (!psStyles[i=layer_to_style_no(cellptr->detail.box->layerptr)].hidden)
198             BoxToPOV(povfileptr, cellptr->detail.box, psStyles[i]);
199           break;
200         default:
201           break;
202       } /* switch */
203     } /* cell loop */
204   if (subcells>1) {
205     fprintf(povfileptr,"}\n");
206   } else {
207     fprintf(povfileptr,"\n");
208   }
209 
210   FREE(esctopcell);
211 }
212 
213 
214 
215 struct callorder {
216  char *name;
217  struct callorder *next;
218 } *callorderfirst=NULL;
219 
220 
221 
222 /* Call with topcell, will descend heirarchy and create a call order */
223 
POVStructsInOrder(GDSlibrary * libptr,char * cellname)224 void POVStructsInOrder(GDSlibrary *libptr,char *cellname)
225 {
226  GDSstruct *structptr;
227  GDScell *fcell;
228  struct callorder *cur,*pre;
229  structptr = GDSgetStructByName(libptr, cellname);
230  fcell=structptr->cells;
231  while (fcell!=NULL) {
232   if (fcell->type==SREF) {
233    POVStructsInOrder(libptr,fcell->detail.sref->refname);
234   }
235   if (fcell->type==AREF) {
236    POVStructsInOrder(libptr,fcell->detail.aref->refname);
237   }
238   fcell=fcell->next;
239  }
240  cur=callorderfirst;
241  pre=NULL;
242  while (cur!=NULL && strcmp(cellname,cur->name)!=0) {
243   pre=cur;
244   cur=cur->next;
245  }
246  if (cur==NULL) { /* Must add */
247   cur=(struct callorder *)MALLOC(sizeof(struct callorder));
248   cur->next=NULL;
249   cur->name=(char *)MALLOC(sizeof(char)*(strlen(cellname)+1));
250   strcpy(cur->name,cellname);
251   if (pre==NULL) callorderfirst=cur; else pre->next=cur;
252  }
253 }
254 
255 
256 void
GDStoPOV(GDSlibrary * libptr,char * povfile,char * topcellname)257 GDStoPOV(GDSlibrary *libptr, char *povfile, char *topcellname)
258 {
259  FILE *povfileptr;
260  GDSstruct *structptr;
261  struct callorder *cur;
262  bbox bbx;
263  char *esctopcell,*ts;
264  int i;
265 
266  povfileptr = fopen(povfile, "w");
267 
268  if(povfileptr == NULL)
269   {
270     fprintf(stderr, "Couldn't open %s for writing. Aborting...\n", povfile);
271     exit(1);
272   }
273 
274   structptr = GDSgetStructByName(libptr, topcellname);
275   if(structptr == NULL)
276   {
277     fprintf(stderr, "Couldn't find the structure named \"%s\"\n",
278             topcellname);
279     fclose(povfileptr);
280     return;
281   }
282   bbx = GDSgetStructBBox(structptr);
283   esctopcell=GDSEscPovString(topcellname);
284   fprintf(povfileptr,
285     "// POVRAY file generated from gdsreader-0.3.1\n"
286     "// Top level cell is %s (or %s if escaping is needed.)\n"
287     "// Bounding box is (%d,%d)-(%d,%d)\n"
288     "// UserUnit: %e MeterUnit: %e \n"
289     "// Since thickness in the config is specified in microns,\n"
290     "//   the instance of the final object will be vertically scaled\n"
291     "//   by %e at the end of the file.\n\n"
292  //   "#include \"colors.inc\"\n"
293  //   "#include \"shapes.inc\"\n"
294  //   "#include \"finish.inc\"\n"
295  //   "#include \"glass.inc\"\n"
296     "camera {\n"
297     " location <%f,%f,%f>\n"
298     " look_at <%f,0,%f>\n"
299     "}\n"
300     "global_settings { ambient_light rgb <4.5,4.5,4.5> }\n"
301     "light_source { <%f,%f,%f> color rgb <1.0, 1.0, 1.0> }\n\n",
302      topcellname,esctopcell,
303      /* bbox of whole thing. */ bbx.ur.x,bbx.ur.y,bbx.ll.x,bbx.ll.y,
304      /* This is the units specified in the file: */ libptr->userunit,libptr->meterunit,
305      /* Scale vertically by: ----> */ 1.0e-6/libptr->meterunit,
306      /* Camera at a corner, height is x+y */
307      (double)bbx.ll.x, (double)abs(bbx.ur.x-bbx.ll.x)+abs(bbx.ur.y-bbx.ll.y)   ,(double)bbx.ll.y,
308      /* Look at center of bounding box */
309      (bbx.ur.x+bbx.ll.x)/2.0,(bbx.ur.y+bbx.ll.y)/2.0,
310      /* Light source diagonally from camera, height same as camera */
311      (double)bbx.ur.x, (double) abs(bbx.ur.x-bbx.ll.x)+abs(bbx.ur.y-bbx.ll.y)   ,(double)bbx.ll.y
312     );
313 /*  fprintf(stderr,"Wrote POV Header.\n");
314   fflush(stderr); */
315   /* Time to go through the "how many layers" PSStyles and dump them */
316   for(i=0;i<howmanylayers;i++) if (!(psStyles[i].hidden)) {
317      /* Print out a layer description. */
318      fprintf(povfileptr,
319        "#declare %s = texture { // Layer name: %s \n"
320        "     pigment {\n"
321        "        color rgb <%f,%f,%f>\n"
322        "     }\n"
323        "  }\n",
324        ts=GDSpsStyleNoToTEXName(i),
325        psStyles[i].layername,
326        psStyles[i].edgecolor.r,
327        psStyles[i].edgecolor.g,
328        psStyles[i].edgecolor.b );
329       FREE(ts);
330      }
331   /* I need to find the cells, in the right order, and then dump them. */
332   POVStructsInOrder(libptr,topcellname);
333   cur=callorderfirst;
334   while (cur!=NULL) {
335    GDStoPOVCell(libptr, povfileptr, cur->name);
336    cur=cur->next;
337   }
338   fprintf(povfileptr, "object { %s scale <1.0,%f,1.0> }\n// end of povray file\n",esctopcell,1.0e-6/libptr->meterunit);
339   FREE(esctopcell);
340 
341   /* x,z x,z */
342 
343 
344 
345  fclose(povfileptr);
346 }
347