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