1
2
3
4
5
6
7
8
9 package edu.uci.ics.jung.visualization.transform.shape;
10
11 import java.awt.Component;
12 import java.awt.Shape;
13 import java.awt.geom.GeneralPath;
14 import java.awt.geom.PathIterator;
15 import java.awt.geom.Point2D;
16
17 import edu.uci.ics.jung.algorithms.layout.PolarPoint;
18 import edu.uci.ics.jung.visualization.transform.HyperbolicTransformer;
19 import edu.uci.ics.jung.visualization.transform.MutableTransformer;
20
21
22
23
24
25
26
27
28
29
30
31
32 public class HyperbolicShapeTransformer extends HyperbolicTransformer
33 implements ShapeFlatnessTransformer {
34
35
36
37
38
39
40 public HyperbolicShapeTransformer(Component component) {
41 this(component, null);
42 }
43
44
45
46
47
48
49
50
51 public HyperbolicShapeTransformer(Component component, MutableTransformer delegate) {
52 super(component, delegate);
53 }
54
55
56
57
58
59
60
61
62 public Shape transform(Shape shape) {
63 return transform(shape, 0);
64 }
65 public Shape transform(Shape shape, float flatness) {
66 GeneralPath newPath = new GeneralPath();
67 float[] coords = new float[6];
68 PathIterator iterator = null;
69 if(flatness == 0) {
70 iterator = shape.getPathIterator(null);
71 } else {
72 iterator = shape.getPathIterator(null, flatness);
73 }
74 for( ;
75 iterator.isDone() == false;
76 iterator.next()) {
77 int type = iterator.currentSegment(coords);
78 switch(type) {
79 case PathIterator.SEG_MOVETO:
80 Point2D p = _transform(new Point2D.Float(coords[0], coords[1]));
81 newPath.moveTo((float)p.getX(), (float)p.getY());
82 break;
83
84 case PathIterator.SEG_LINETO:
85 p = _transform(new Point2D.Float(coords[0], coords[1]));
86 newPath.lineTo((float)p.getX(), (float) p.getY());
87 break;
88
89 case PathIterator.SEG_QUADTO:
90 p = _transform(new Point2D.Float(coords[0], coords[1]));
91 Point2D q = _transform(new Point2D.Float(coords[2], coords[3]));
92 newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY());
93 break;
94
95 case PathIterator.SEG_CUBICTO:
96 p = _transform(new Point2D.Float(coords[0], coords[1]));
97 q = _transform(new Point2D.Float(coords[2], coords[3]));
98 Point2D r = _transform(new Point2D.Float(coords[4], coords[5]));
99 newPath.curveTo((float)p.getX(), (float)p.getY(),
100 (float)q.getX(), (float)q.getY(),
101 (float)r.getX(), (float)r.getY());
102 break;
103
104 case PathIterator.SEG_CLOSE:
105 newPath.closePath();
106 break;
107
108 }
109 }
110 return newPath;
111 }
112
113 public Shape inverseTransform(Shape shape) {
114 GeneralPath newPath = new GeneralPath();
115 float[] coords = new float[6];
116 for(PathIterator iterator=shape.getPathIterator(null);
117 iterator.isDone() == false;
118 iterator.next()) {
119 int type = iterator.currentSegment(coords);
120 switch(type) {
121 case PathIterator.SEG_MOVETO:
122 Point2D p = _inverseTransform(new Point2D.Float(coords[0], coords[1]));
123 newPath.moveTo((float)p.getX(), (float)p.getY());
124 break;
125
126 case PathIterator.SEG_LINETO:
127 p = _inverseTransform(new Point2D.Float(coords[0], coords[1]));
128 newPath.lineTo((float)p.getX(), (float) p.getY());
129 break;
130
131 case PathIterator.SEG_QUADTO:
132 p = _inverseTransform(new Point2D.Float(coords[0], coords[1]));
133 Point2D q = _inverseTransform(new Point2D.Float(coords[2], coords[3]));
134 newPath.quadTo((float)p.getX(), (float)p.getY(), (float)q.getX(), (float)q.getY());
135 break;
136
137 case PathIterator.SEG_CUBICTO:
138 p = _inverseTransform(new Point2D.Float(coords[0], coords[1]));
139 q = _inverseTransform(new Point2D.Float(coords[2], coords[3]));
140 Point2D r = _inverseTransform(new Point2D.Float(coords[4], coords[5]));
141 newPath.curveTo((float)p.getX(), (float)p.getY(),
142 (float)q.getX(), (float)q.getY(),
143 (float)r.getX(), (float)r.getY());
144 break;
145
146 case PathIterator.SEG_CLOSE:
147 newPath.closePath();
148 break;
149
150 }
151 }
152 return newPath;
153 }
154
155
156
157 private Point2D _transform(Point2D graphPoint) {
158 if(graphPoint == null) return null;
159 Point2D viewCenter = getViewCenter();
160 double viewRadius = getViewRadius();
161 double ratio = getRatio();
162
163 Point2D viewPoint = graphPoint;
164
165 double dx = viewPoint.getX() - viewCenter.getX();
166 double dy = viewPoint.getY() - viewCenter.getY();
167
168 dx *= ratio;
169 Point2D pointFromCenter = new Point2D.Double(dx, dy);
170
171 PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter);
172 double theta = polar.getTheta();
173 double radius = polar.getRadius();
174 if(radius > viewRadius) return viewPoint;
175
176 double mag = Math.tan(Math.PI/2*magnification);
177 radius *= mag;
178
179 radius = Math.min(radius, viewRadius);
180 radius /= viewRadius;
181 radius *= Math.PI/2;
182 radius = Math.abs(Math.atan(radius));
183 radius *= viewRadius;
184 Point2D projectedPoint = PolarPoint.polarToCartesian(theta, radius);
185 projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY());
186 Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(),
187 projectedPoint.getY()+viewCenter.getY());
188 return translatedBack;
189 }
190
191
192
193
194 private Point2D _inverseTransform(Point2D viewPoint) {
195
196 viewPoint = delegate.inverseTransform(viewPoint);
197 Point2D viewCenter = getViewCenter();
198 double viewRadius = getViewRadius();
199 double ratio = getRatio();
200 double dx = viewPoint.getX() - viewCenter.getX();
201 double dy = viewPoint.getY() - viewCenter.getY();
202
203 dx *= ratio;
204
205 Point2D pointFromCenter = new Point2D.Double(dx, dy);
206
207 PolarPoint polar = PolarPoint.cartesianToPolar(pointFromCenter);
208
209 double radius = polar.getRadius();
210 if(radius > viewRadius) return viewPoint;
211
212 radius /= viewRadius;
213 radius = Math.abs(Math.tan(radius));
214 radius /= Math.PI/2;
215 radius *= viewRadius;
216 double mag = Math.tan(Math.PI/2*magnification);
217 radius /= mag;
218 polar.setRadius(radius);
219 Point2D projectedPoint = PolarPoint.polarToCartesian(polar);
220 projectedPoint.setLocation(projectedPoint.getX()/ratio, projectedPoint.getY());
221 Point2D translatedBack = new Point2D.Double(projectedPoint.getX()+viewCenter.getX(),
222 projectedPoint.getY()+viewCenter.getY());
223 return translatedBack;
224
225 }
226 }