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 <math.h>
22 #include <strings.h>
23 #include <unistd.h>
24 #include <GDSstructs.h>
25 #include <GDSconsts.h>
26
27 #include <GDSaux.h>
28
29 /*
30 * Most of the code has been adapted from the beautiful piece of sw. named Magic
31 * Thank you, guys!
32 */
33
34 transform Ident = { 1.0, 0.0, 0, 0.0, 1.0, 0 };
35
36
37 double
GDSgetDeterminant(transform * transf)38 GDSgetDeterminant(transform *transf)
39 {
40 return (transf->a * transf->e - transf->b * transf->d);
41 }
42
43 coord
myRound(double value)44 myRound(double value)
45 {
46 if(value < 0.0)
47 return (coord)(value - 0.5);
48 else
49 return (coord)(value + 0.5);
50 }
51
52 transform *
GDSinvertTransf(transform * transf)53 GDSinvertTransf(transform *transf)
54 {
55 transform *invtransf;
56 double det;
57
58 det = GDSgetDeterminant(transf);
59 if(det == 0.0)
60 {
61 fprintf(stderr, "Error in GDSinvertTransf(): matrix cannot be inverted\n");
62 exit(1);
63 }
64
65 invtransf = (transform *)MALLOC(sizeof(transform));
66 invtransf->a = transf->e / det;
67 invtransf->b = - transf->b / det;
68 invtransf->c = (transf->b * transf->f - transf->c * transf->e) / det;
69 invtransf->d = - transf->d / det;
70 invtransf->e = transf->a / det;
71 invtransf->f = (transf->d * transf->c - transf->a * transf->f) / det;
72
73 return invtransf;
74 }
75
76
77 /* We put a point in, and do the backwards transform on it. */
78 point
GDSinvtransfPoint(point * pointptr,transform * transfptr)79 GDSinvtransfPoint(point *pointptr, transform *transfptr)
80 {
81 point newpoint;
82 double det;
83 double a, b;
84
85 det = GDSgetDeterminant(transfptr);
86 if(det == 0.0)
87 {
88 fprintf(stderr,
89 "Error in GDSinvtransfPoint(): matrix cannot be inverted\n");
90 exit(1);
91 }
92
93 a = (pointptr->x - transfptr->c) / det;
94 b = (pointptr->y - transfptr->f) / det;
95 newpoint.x = myRound(a * transfptr->e - b * transfptr->b);
96 newpoint.y = myRound(b * transfptr->a - a * transfptr->d);
97
98 return newpoint;
99 }
100
101 /*
102 * Creates a transform based on the GDSII transformation hints.
103 * For now, mag is not used. (Actually, I added this. (Pete)
104 */
105 transform *
GDSgetTransf(point ref,double angle,double mag,int mirror)106 GDSgetTransf(point ref, double angle, double mag, int mirror)
107 {
108 transform *newtransf;
109
110 newtransf = (transform *)MALLOC(sizeof(transform));
111 newtransf->a = mag*cos(angle * M_PI / 180.0);
112 newtransf->b = -mag*sin(angle * M_PI / 180.0);
113 newtransf->c = ref.x;
114 newtransf->d = mag*sin(angle * M_PI / 180.0);
115 newtransf->e = mag*cos(angle * M_PI / 180.0);
116 newtransf->f = ref.y;
117
118 /* GDSII understands only the Y mirroring */
119
120 /* Reflecting about X means changing *Y* */
121 if (mirror) {
122 newtransf->b = -newtransf->b;
123 newtransf->e = -newtransf->e;
124 }
125 return newtransf;
126 }
127
128
129
130 /* Returns angle in degrees implied by the
131 transform matrix. */
GDSGetTransfValues(transform * t,int * mirror,double * mag)132 double GDSGetTransfValues(transform *t, int *mirror, double *mag)
133 {
134 double retval;
135
136 /*
137 |nx| | mx*cos(R) -my*sin(R)||x| |ox|
138 |ny| = | mx*sin(R) my*cos(R)||y| + |oy|
139
140 Generally, mx=my=1. However, if my=-mx, we are flipped.
141
142
143 Not flipped:
144
145 ab
146 de
147
148 --|+-
149 +-|++
150 -------
151 -+|++
152 --|-+
153
154 flipped:
155
156 -+|++
157 ++|+-
158 -------
159 --|+-
160 -+|--
161
162 if b*d is POSITIVE, or a*e is NEGATIVE we are flipped.
163
164 */
165
166 *mag=(double)sqrt((t->d) * (t->d) + (t->e)*(t->e));
167 /* If b and d have different signs *or* a and e have different signs,
168 then we are mirrored. one might be zero, but not both. */
169 if ((t->b)*(t->d)>0.0 || (t->a)*(t->e)<0.0) *mirror=1; else *mirror=0;
170
171 /* If mirrored, d and e are wrong in sign. */
172 /* We can get angle from a and -b d*/
173
174 /* if a==0, do not take atan. */
175 if (fabs(t->a)<1.0e-14) {
176 if (t->d<=0) return(-90.0); /* Remember b=-sin(R) */
177 return(90.0);
178 }
179 if (t->a<0.0)
180 retval=atan((t->d)/t->a)+asin(1.0)*2.0;
181 else
182 retval=atan((t->d)/t->a);
183 return(retval*90.0/asin(1.0));
184 }
185
186
187
188 point
GDStransfPoint(point * pointptr,transform * transfptr)189 GDStransfPoint(point *pointptr, transform *transfptr)
190 {
191 point newpoint;
192
193 newpoint.x = myRound(pointptr->x * transfptr->a + pointptr->y * transfptr->b +
194 transfptr->c);
195 newpoint.y = myRound(pointptr->x * transfptr->d + pointptr->y * transfptr->e +
196 transfptr->f);
197
198 return newpoint;
199 }
200
201 transform *
GDSdupTransf(transform * transf)202 GDSdupTransf(transform *transf)
203 {
204 transform *newtransf;
205
206 newtransf = (transform *)MALLOC(sizeof(transform));
207
208 newtransf->a = transf->a;
209 newtransf->b = transf->b;
210 newtransf->c = transf->c;
211 newtransf->d = transf->d;
212 newtransf->e = transf->e;
213 newtransf->f = transf->f;
214
215 return newtransf;
216 }
217
218 void
GDSfreeTransf(transform * transf)219 GDSfreeTransf(transform *transf)
220 {
221 FREE(transf);
222 }
223
224 /*
225 * newtransf, if applied, is equivalent to the application of transf1,
226 * followed by the application of transf2.
227 */
228 transform *
GDStransfTransf(transform * transf1,transform * transf2)229 GDStransfTransf(transform *transf1, transform *transf2)
230 {
231 transform *newtransf;
232
233 newtransf = (transform *)MALLOC(sizeof(transform));
234 newtransf->a = transf1->a * transf2->a + transf1->d * transf2->b;
235 newtransf->b = transf1->b * transf2->a + transf1->e * transf2->b;
236 newtransf->c = transf1->c * transf2->a + transf1->f * transf2->b + transf2->c;
237 newtransf->d = transf1->a * transf2->d + transf1->d * transf2->e;
238 newtransf->e = transf1->b * transf2->d + transf1->e * transf2->e;
239 newtransf->f = transf1->c * transf2->d + transf1->f * transf2->e + transf2->f;
240
241 return newtransf;
242 }
243
244
245 transform *
GDStranslateTransf(transform * transf,point refpoint)246 GDStranslateTransf(transform *transf, point refpoint)
247 {
248 transform *newtransf;
249
250 newtransf = (transform *)MALLOC(sizeof(transform));
251 newtransf->a = transf->a;
252 newtransf->b = transf->b;
253 newtransf->d = transf->d;
254 newtransf->e = transf->e;
255 newtransf->c = transf->c + refpoint.x;
256 newtransf->f = transf->f + refpoint.y;
257
258 return newtransf;
259 }
260