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 <strings.h>
22 #include <math.h>
23
24 #include <GDSstructs.h>
25 #include <GDSconsts.h>
26 #include <GDSaux.h>
27 #include <GDStransf.h>
28 #include <GDSboundary.h>
29
30 static double
getAngle(coord x1,coord y1,coord x2,coord y2)31 getAngle(coord x1, coord y1, coord x2, coord y2)
32 {
33 double angle;
34
35 if(x1 == x2)
36 angle = M_PI_2 * ((y2 > y1) ? 1 : -1);
37 else
38 {
39 angle = atan(fabs(y2 - y1)/fabs(x2 - x1));
40 if(y2 >= y1)
41 {
42 if(x2 >= x1)
43 angle += 0;
44 else
45 angle = M_PI - angle;
46 }
47 else
48 {
49 if(x2 >= x1)
50 angle = 2 * M_PI - angle;
51 else
52 angle += M_PI;
53 }
54 }
55
56 return angle;
57 }
58
59 #define EPS 1e-8
60
61 static point
getDeltaXY(coord hw,point p1,point p2,point p3)62 getDeltaXY(coord hw, point p1, point p2, point p3)
63 {
64 double alpha, beta, theta, r;
65 point pnt;
66
67 alpha = getAngle(p1.x, p1.y, p2.x, p2.y);
68 beta = getAngle(p2.x, p2.y, p3.x, p3.y);
69
70 theta = (alpha + beta + M_PI)/2.0;
71
72 if(fabs(cos((alpha - beta)/2.0)) < EPS)
73 {
74 fprintf(stderr, "Internal algorithm error: cos((alpha - beta)/2) = 0\n");
75 exit(1);
76 }
77 r = ((double) hw) / cos((alpha - beta)/2.0);
78
79 pnt.x = (coord) (r * cos(theta));
80 pnt.y = (coord) (r * sin(theta));
81
82 return pnt;
83 }
84
85 static point
getEndDeltaXY(coord hw,point p1,point p2)86 getEndDeltaXY(coord hw, point p1, point p2)
87 {
88 double alpha, theta, r;
89 point pnt;
90
91 alpha = getAngle(p1.x, p1.y, p2.x, p2.y);
92
93 theta = alpha;
94 r= hw;
95 pnt.x = (coord)(-r * sin(theta));
96 pnt.y = (coord)(r * cos(theta));
97
98 return pnt;
99 }
100
101
102 boundaryEl *
PathToBoundary(pathEl * path)103 PathToBoundary(pathEl *path)
104 {
105 boundaryEl *boundary;
106 coord hw = path->width / 2;
107 int i, numpoints = path->numpoints;
108 point *points, deltaxy;
109
110 if (numpoints < 2)
111 {
112 fprintf(stderr,
113 "PathToBoundary(): don't know to handle wires < 2 pts yet\n");
114 return NULL;
115 }
116
117 points = (point *)MALLOC(sizeof(point) * (2 * numpoints + 1));
118
119 deltaxy = getEndDeltaXY(hw, path->points[0], path->points[1]);
120
121 if(path->pathtype == BUTT_END)
122 {
123 points[0].x = path->points[0].x + deltaxy.x;
124 points[0].y = path->points[0].y + deltaxy.y;
125 points[2 * numpoints].x = path->points[0].x + deltaxy.x;
126 points[2 * numpoints].y = path->points[0].y + deltaxy.y;
127 points[2 * numpoints - 1].x = path->points[0].x - deltaxy.x;
128 points[2 * numpoints - 1].y = path->points[0].y - deltaxy.y;
129 }
130 else /* Extended end */
131 {
132 points[0].x = path->points[0].x + deltaxy.x - deltaxy.y;
133 points[0].y = path->points[0].y + deltaxy.y - deltaxy.x;
134 points[2 * numpoints].x = path->points[0].x + deltaxy.x - deltaxy.y;
135 points[2 * numpoints].y = path->points[0].y + deltaxy.y - deltaxy.x;
136 points[2 * numpoints - 1].x = path->points[0].x - deltaxy.x - deltaxy.y;
137 points[2 * numpoints - 1].y = path->points[0].y - deltaxy.y - deltaxy.x;
138 }
139
140
141 for(i = 1; i < numpoints - 1; i++)
142 {
143 deltaxy = getDeltaXY(hw, path->points[i - 1],
144 path->points[i], path->points[i + 1]);
145 points[i].x = path->points[i].x + deltaxy.x;
146 points[i].y = path->points[i].y + deltaxy.y;
147 points[2 * numpoints - i - 1].x = path->points[i].x - deltaxy.x;
148 points[2 * numpoints - i - 1].y = path->points[i].y - deltaxy.y;
149 }
150
151 deltaxy = getEndDeltaXY(hw, path->points[numpoints - 2],
152 path->points[numpoints - 1]);
153 if(path->pathtype == BUTT_END)
154 {
155 points[numpoints - 1].x = path->points[numpoints - 1].x + deltaxy.x;
156 points[numpoints - 1].y = path->points[numpoints - 1].y + deltaxy.y;
157 points[numpoints].x = path->points[numpoints - 1].x - deltaxy.x;
158 points[numpoints].y = path->points[numpoints - 1].y - deltaxy.y;
159 }
160 else /* Extended end */
161 {
162 points[numpoints - 1].x = path->points[numpoints - 1].x + deltaxy.x + deltaxy.y;
163 points[numpoints - 1].y = path->points[numpoints - 1].y + deltaxy.y + deltaxy.x;
164 points[numpoints].x = path->points[numpoints - 1].x - deltaxy.x + deltaxy.y;
165 points[numpoints].y = path->points[numpoints - 1].y - deltaxy.y + deltaxy.x;
166 }
167
168 boundary = (boundaryEl *)MALLOC(sizeof(boundaryEl));
169 boundary->layerptr = path->layerptr;
170 boundary->numpoints = numpoints * 2 + 1;
171 boundary->points = points;
172
173 return boundary;
174 }
175
176 bbox
GDSgetPathBBox(pathEl * path)177 GDSgetPathBBox(pathEl *path)
178 {
179 bbox bbx;
180 boundaryEl *boundary;
181
182 boundary = PathToBoundary(path);
183 if(boundary == NULL)
184 {
185 bbx.ll.x = BIGVAL;
186 bbx.ll.y = BIGVAL;
187 bbx.ur.x = -BIGVAL;
188 bbx.ur.y = -BIGVAL;
189 return bbx;
190 }
191 bbx = GDSgetBoundaryBBox(boundary);
192 FREE(boundary->points);
193 FREE(boundary);
194
195 return bbx;
196 }
197
198 void
PathToPS(FILE * psfile,pathEl * path,PSStyle psStyle)199 PathToPS(FILE *psfile, pathEl *path, PSStyle psStyle)
200 {
201 boundaryEl *boundary;
202
203 if(path->layerptr->layerno != psStyle.gdsno)
204 return;
205 boundary = PathToBoundary(path);
206 if(boundary == NULL)
207 return;
208 BoundaryToPS(psfile, boundary, psStyle);
209 FREE(boundary->points);
210 FREE(boundary);
211 }
212
213 void
PathToPOV(FILE * povfile,pathEl * path,PSStyle psStyle)214 PathToPOV(FILE *povfile, pathEl *path, PSStyle psStyle)
215 {
216 boundaryEl *boundary;
217 boundary = PathToBoundary(path);
218 if(boundary == NULL)
219 return;
220 BoundaryToPOV(povfile, boundary, psStyle);
221 FREE(boundary->points);
222 FREE(boundary);
223 }
224
225 void
PathToHPGL(FILE * hpglfile,pathEl * path,PSStyle psStyle)226 PathToHPGL(FILE *hpglfile, pathEl *path, PSStyle psStyle)
227 {
228 boundaryEl *boundary;
229
230 if(path->layerptr->layerno != psStyle.gdsno)
231 return;
232 boundary = PathToBoundary(path);
233 if(boundary == NULL)
234 return;
235 BoundaryToHPGL(hpglfile, boundary, psStyle);
236 FREE(boundary->points);
237 FREE(boundary);
238 }
239
240 /*
241 * Frees the cell contents and removes the layer list reference.
242 * The structure list reference has to be removed at the upper level.
243 */
244 void
GDSfreePath(GDScell * cell)245 GDSfreePath(GDScell *cell)
246 {
247 GDScell *cellptr;
248
249 if(cell == NULL)
250 return;
251 if(cell->type != PATH)
252 return;
253
254 if(cell == cell->detail.path->layerptr->cells)
255 cell->detail.path->layerptr->cells = cell->next;
256 else
257 {
258 for(cellptr = cell->detail.path->layerptr->cells;
259 cellptr->next != NULL; cellptr = cellptr->next)
260 {
261 if(cellptr->next == cell)
262 {
263 cellptr->next = cellptr->next->next;
264 break;
265 }
266 }
267 if(cellptr == NULL)
268 fprintf(stderr, "Oops! GDSfreePath(): Missing cell in layerptr\n");
269 }
270 FREE(cell->detail.path->points);
271 FREE(cell->detail.path);
272 return;
273 }
274
275 GDScell *
GDSdupPath(pathEl * path)276 GDSdupPath(pathEl *path)
277 {
278 int i;
279 GDScell *newcell;
280 pathEl *pathptr;
281
282 if(path == NULL)
283 return NULL;
284
285 pathptr = (pathEl *)MALLOC(sizeof(pathEl));
286 newcell = (GDScell *)MALLOC(sizeof(GDScell));
287 newcell->type = PATH;
288 newcell->detail.path = pathptr;
289
290 newcell->next = path->layerptr->cells;
291 path->layerptr->cells = newcell;
292
293 pathptr->layerptr = path->layerptr;
294 pathptr->pathtype = path->pathtype;
295 pathptr->width= path->width;
296 pathptr->numpoints = path->numpoints;
297 pathptr->points = (point *)MALLOC(pathptr->numpoints * sizeof(point));
298 for(i = 0; i < pathptr->numpoints; i ++)
299 {
300 (pathptr->points[i]).x = (path->points[i]).x;
301 (pathptr->points[i]).y = (path->points[i]).y;
302 }
303
304 return newcell;
305 }
306
307 /*
308 * Apply the transform transf to all points in path.
309 */
310 void
GDStransfPath(pathEl * path,transform * transf)311 GDStransfPath(pathEl *path, transform *transf)
312 {
313 int i;
314 double mag;
315 for(i = 0; i < path->numpoints; i++)
316 path->points[i] = GDStransfPoint(&(path->points[i]), transf);
317 /* Check to see if width needs to be changed. */
318 GDSGetTransfValues(transf,&i,&mag);
319 if (mag!=1.0) { path->width= (coord)((double)path->width*mag); }
320 return;
321 }
322
323 GDScell *
GDSreadPath(int gdsfildes,GDSstruct * structptr)324 GDSreadPath(int gdsfildes, GDSstruct *structptr)
325 {
326 unsigned char *record;
327 int i, nbytes, layerno,datatype;
328 layer *layerptr;
329 GDScell *newcell;
330 pathEl *pathptr;
331
332 pathptr = (pathEl *)MALLOC(sizeof(pathEl));
333 newcell = (GDScell *)MALLOC(sizeof(GDScell));
334 newcell->type = PATH;
335 newcell->detail.path = pathptr;
336
337 if(GDSreadRecord(gdsfildes, &record, &nbytes) != LAYER)
338 {
339 fprintf(stderr, "Missing LAYER field in PATH element. Abort!\n");
340 exit(1);
341 }
342 layerno = GDSreadInt2(record + 2);
343 FREE(record);
344
345 if(GDSreadRecord(gdsfildes, &record, &nbytes) != DATATYPE)
346 {
347 fprintf(stderr, "Missing DATATYPE field in PATH element. Abort!\n");
348 exit(1);
349 }
350 datatype = GDSreadInt2(record + 2);
351 FREE(record);
352
353 for(layerptr = structptr->layers;
354 layerptr != NULL; layerptr = layerptr->next)
355 if(layerptr->layerno == layerno && layerptr->datatype==datatype)
356 break;
357 if(layerptr == NULL)
358 {
359 layerptr = (layer *)MALLOC(sizeof(layer));
360 layerptr->layerno = layerno;
361 layerptr->datatype = datatype;
362 layerptr->name = NULL; /* to be added later */
363 layerptr->cells = newcell;
364 layerptr->next = structptr->layers;
365 structptr->layers = layerptr;
366 }
367 else
368 {
369 newcell->next = layerptr->cells;
370 layerptr->cells = newcell;
371 }
372 pathptr->layerptr = layerptr;
373
374 if(GDSreadRecord(gdsfildes, &record, &nbytes) != PATHTYPE)
375 {
376 fprintf(stderr, "Missing PATHTYPE field in PATH element. Abort!\n");
377 exit(1);
378 }
379 pathptr->pathtype = GDSreadInt2(record + 2);
380 FREE(record);
381
382 switch(pathptr->pathtype)
383 {
384 case ROUND_END:
385 fprintf(stderr,
386 "Round ended path not supported. Used extended instead\n");
387 case CUSTOMPLUS_END:
388 fprintf(stderr,
389 "Custom ended path not supported. Used extended instead\n");
390 pathptr->pathtype = EXTENDED_END;
391 case EXTENDED_END:
392 case BUTT_END:
393 break;
394 default:
395 fprintf(stderr, "Unknown pathtype %d. Used butt end instead\n",
396 pathptr->pathtype);
397 pathptr->pathtype = BUTT_END;
398 break;
399 }
400 if(GDSreadRecord(gdsfildes, &record, &nbytes) != WIDTH)
401 {
402 fprintf(stderr, "Missing WIDTH field in PATH element. Abort!\n");
403 exit(1);
404 }
405 pathptr->width = GDSreadInt4(record + 2);
406 FREE(record);
407
408 if(GDSreadRecord(gdsfildes, &record, &nbytes) != XY)
409 {
410 fprintf(stderr, "Missing XY field in PATH element. Abort!\n");
411 exit(1);
412 }
413 pathptr->numpoints = (nbytes - 2) / 8;
414 pathptr->points = (point *)MALLOC(pathptr->numpoints * sizeof(point));
415
416 for(i = 0; i < pathptr->numpoints; i ++)
417 {
418 (pathptr->points[i]).x = GDSreadInt4(record + 8 * i + 2);
419 (pathptr->points[i]).y = GDSreadInt4(record + 8 * i + 6);
420 }
421 FREE(record);
422
423 if(GDSreadRecord(gdsfildes, &record, &nbytes) != ENDEL)
424 {
425 fprintf(stderr, "Missing ENDEL field in PATH element. Abort!\n");
426 exit(1);
427 }
428 FREE(record);
429
430 fprintf(stdout, "Path on layer %d, datatype %d, of type %d with width = %d:\n",
431 layerno, layerptr->datatype,pathptr->pathtype, pathptr->width);
432 for(i = 0; i < pathptr->numpoints; i++)
433 fprintf(stdout, "point[%d] = %d %d\n",
434 i, (pathptr->points[i]).x, (pathptr->points[i]).y);
435 return newcell;
436 }
437
438