1
2
3
4
5
6
7
8
9
10
11 package edu.uci.ics.jung.visualization.transform;
12
13 import java.awt.Shape;
14 import java.awt.geom.AffineTransform;
15 import java.awt.geom.GeneralPath;
16 import java.awt.geom.NoninvertibleTransformException;
17 import java.awt.geom.PathIterator;
18 import java.awt.geom.Point2D;
19
20 import edu.uci.ics.jung.visualization.transform.shape.ShapeTransformer;
21
22
23
24
25
26
27
28
29
30 public class AffineTransformer implements BidirectionalTransformer, ShapeTransformer {
31
32 protected AffineTransform inverse;
33
34
35
36
37
38 protected AffineTransform transform = new AffineTransform();
39
40
41
42
43 public AffineTransformer() {
44
45 }
46
47
48
49
50
51 public AffineTransformer(AffineTransform transform) {
52 if(transform != null)
53 this.transform = transform;
54 }
55
56
57
58
59 public AffineTransform getTransform() {
60 return transform;
61 }
62
63
64
65 public void setTransform(AffineTransform transform) {
66 this.transform = transform;
67 }
68
69
70
71
72
73
74 public Point2D inverseTransform(Point2D p) {
75
76 return getInverse().transform(p, null);
77 }
78
79 public AffineTransform getInverse() {
80 if(inverse == null) {
81 try {
82 inverse = transform.createInverse();
83 } catch (NoninvertibleTransformException e) {
84 e.printStackTrace();
85 }
86 }
87 return inverse;
88 }
89
90
91
92
93 public double getScaleX() {
94 return transform.getScaleX();
95 }
96
97
98
99
100 public double getScaleY() {
101 return transform.getScaleY();
102 }
103
104
105
106
107 public double getScale() {
108 return Math.sqrt(transform.getDeterminant());
109 }
110
111
112
113
114 public double getShearX() {
115 return transform.getShearX();
116 }
117
118
119
120
121 public double getShearY() {
122 return transform.getShearY();
123 }
124
125
126
127
128 public double getTranslateX() {
129 return transform.getTranslateX();
130 }
131
132
133
134
135 public double getTranslateY() {
136 return transform.getTranslateY();
137 }
138
139
140
141
142
143
144
145 public Point2D transform(Point2D p) {
146 if(p == null) return null;
147 return transform.transform(p, null);
148 }
149
150
151
152
153
154
155 public Shape transform(Shape shape) {
156 GeneralPath newPath = new GeneralPath();
157 float[] coords = new float[6];
158 for(PathIterator iterator=shape.getPathIterator(null);
159 iterator.isDone() == false;
160 iterator.next()) {
161 int type = iterator.currentSegment(coords);
162 switch(type) {
163 case PathIterator.SEG_MOVETO:
164 Point2D p = transform(new Point2D.Float(coords[0], coords[1]));
165 newPath.moveTo((float)p.getX(), (float)p.getY());
166 break;
167
168 case PathIterator.SEG_LINETO:
169 p = transform(new Point2D.Float(coords[0], coords[1]));
170 newPath.lineTo((float)p.getX(), (float) p.getY());
171 break;
172
173 case PathIterator.SEG_QUADTO:
174 p = transform(new Point2D.Float(coords[0], coords[1]));
175 Point2D q = transform(new Point2D.Float(coords[2], coords[3]));
176 newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY());
177 break;
178
179 case PathIterator.SEG_CUBICTO:
180 p = transform(new Point2D.Float(coords[0], coords[1]));
181 q = transform(new Point2D.Float(coords[2], coords[3]));
182 Point2D r = transform(new Point2D.Float(coords[4], coords[5]));
183 newPath.curveTo((float)p.getX(), (float)p.getY(),
184 (float)q.getX(), (float)q.getY(),
185 (float)r.getX(), (float)r.getY());
186 break;
187
188 case PathIterator.SEG_CLOSE:
189 newPath.closePath();
190 break;
191
192 }
193 }
194 return newPath;
195 }
196
197
198
199
200
201
202 public Shape inverseTransform(Shape shape) {
203 GeneralPath newPath = new GeneralPath();
204 float[] coords = new float[6];
205 for(PathIterator iterator=shape.getPathIterator(null);
206 iterator.isDone() == false;
207 iterator.next()) {
208 int type = iterator.currentSegment(coords);
209 switch(type) {
210 case PathIterator.SEG_MOVETO:
211 Point2D p = inverseTransform(new Point2D.Float(coords[0], coords[1]));
212 newPath.moveTo((float)p.getX(), (float)p.getY());
213 break;
214
215 case PathIterator.SEG_LINETO:
216 p = inverseTransform(new Point2D.Float(coords[0], coords[1]));
217 newPath.lineTo((float)p.getX(), (float) p.getY());
218 break;
219
220 case PathIterator.SEG_QUADTO:
221 p = inverseTransform(new Point2D.Float(coords[0], coords[1]));
222 Point2D q = inverseTransform(new Point2D.Float(coords[2], coords[3]));
223 newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY());
224 break;
225
226 case PathIterator.SEG_CUBICTO:
227 p = inverseTransform(new Point2D.Float(coords[0], coords[1]));
228 q = inverseTransform(new Point2D.Float(coords[2], coords[3]));
229 Point2D r = inverseTransform(new Point2D.Float(coords[4], coords[5]));
230 newPath.curveTo((float)p.getX(), (float)p.getY(),
231 (float)q.getX(), (float)q.getY(),
232 (float)r.getX(), (float)r.getY());
233 break;
234
235 case PathIterator.SEG_CLOSE:
236 newPath.closePath();
237 break;
238
239 }
240 }
241 return newPath;
242 }
243
244 public double getRotation() {
245 double[] unitVector = new double[]{0,0,1,0};
246 double[] result = new double[4];
247
248 transform.transform(unitVector, 0, result, 0, 2);
249
250 double dy = Math.abs(result[3] - result[1]);
251 double length = Point2D.distance(result[0], result[1], result[2], result[3]);
252 double rotation = Math.asin(dy / length);
253
254 if (result[3] - result[1] > 0) {
255 if (result[2] - result[0] < 0) {
256 rotation = Math.PI - rotation;
257 }
258 } else {
259 if (result[2] - result[0] > 0) {
260 rotation = 2 * Math.PI - rotation;
261 } else {
262 rotation = rotation + Math.PI;
263 }
264 }
265
266 return rotation;
267 }
268
269 @Override
270 public String toString() {
271 return "Transformer using "+transform;
272 }
273 }