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