1
2
3
4
5
6
7
8
9
10
11
12 package edu.uci.ics.jung.visualization.picking;
13
14 import java.awt.Shape;
15 import java.awt.geom.AffineTransform;
16 import java.awt.geom.GeneralPath;
17 import java.awt.geom.PathIterator;
18 import java.awt.geom.Point2D;
19 import java.awt.geom.Rectangle2D;
20 import java.util.Collection;
21 import java.util.ConcurrentModificationException;
22 import java.util.HashSet;
23 import java.util.Set;
24
25 import edu.uci.ics.jung.algorithms.layout.GraphElementAccessor;
26 import edu.uci.ics.jung.algorithms.layout.Layout;
27 import edu.uci.ics.jung.graph.Graph;
28 import edu.uci.ics.jung.graph.util.Context;
29 import edu.uci.ics.jung.graph.util.Pair;
30 import edu.uci.ics.jung.visualization.Layer;
31 import edu.uci.ics.jung.visualization.VisualizationServer;
32 import edu.uci.ics.jung.visualization.transform.MutableTransformerDecorator;
33
34
35
36
37
38
39
40
41 public class ViewLensShapePickSupport<V, E> extends ShapePickSupport<V,E>
42 implements GraphElementAccessor<V,E> {
43
44
45
46
47
48
49
50
51
52
53 public ViewLensShapePickSupport(VisualizationServer<V,E> vv, float pickSize) {
54 super(vv, pickSize);
55 }
56
57
58
59
60
61 public ViewLensShapePickSupport(VisualizationServer<V,E> vv) {
62 this(vv, 2);
63 }
64
65
66
67
68
69
70
71 public V getVertex(Layout<V, E> layout, double x, double y) {
72
73 V closest = null;
74 double minDistance = Double.MAX_VALUE;
75 Point2D ip = ((MutableTransformerDecorator)vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)).getDelegate().inverseTransform(new Point2D.Double(x,y));
76 x = ip.getX();
77 y = ip.getY();
78
79 while(true) {
80 try {
81 for(V v : getFilteredVertices(layout)) {
82
83 Shape shape = vv.getRenderContext().getVertexShapeTransformer().transform(v);
84
85 Point2D p = layout.transform(v);
86 if(p == null) continue;
87 AffineTransform xform =
88 AffineTransform.getTranslateInstance(p.getX(), p.getY());
89 shape = xform.createTransformedShape(shape);
90
91
92
93 Point2D lp = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.LAYOUT, p);
94 AffineTransform xlate = AffineTransform.getTranslateInstance(
95 lp.getX()-p.getX(),lp.getY()-p.getY());
96 shape = xlate.createTransformedShape(shape);
97
98
99 shape = vv.getRenderContext().getMultiLayerTransformer().transform(Layer.VIEW, shape);
100
101
102
103
104 if(shape.contains(x, y)) {
105
106 if(style == Style.LOWEST) {
107
108 return v;
109 } else if(style == Style.HIGHEST) {
110
111 closest = v;
112 } else {
113 Rectangle2D bounds = shape.getBounds2D();
114 double dx = bounds.getCenterX() - x;
115 double dy = bounds.getCenterY() - y;
116 double dist = dx * dx + dy * dy;
117 if (dist < minDistance) {
118 minDistance = dist;
119 closest = v;
120 }
121 }
122 }
123 }
124 break;
125 } catch(ConcurrentModificationException cme) {}
126 }
127 return closest;
128 }
129
130
131
132
133
134
135
136 public Collection<V> getVertices(Layout<V, E> layout, Shape rectangle) {
137 Set<V> pickedVertices = new HashSet<V>();
138
139
140 rectangle = ((MutableTransformerDecorator)vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)).getDelegate().inverseTransform(rectangle);
141
142 while(true) {
143 try {
144 for(V v : getFilteredVertices(layout)) {
145 Point2D p = layout.transform(v);
146 if(p == null) continue;
147
148 Shape shape = vv.getRenderContext().getVertexShapeTransformer().transform(v);
149
150 AffineTransform xform =
151 AffineTransform.getTranslateInstance(p.getX(), p.getY());
152 shape = xform.createTransformedShape(shape);
153
154 shape = vv.getRenderContext().getMultiLayerTransformer().transform(shape);
155 Rectangle2D bounds = shape.getBounds2D();
156 p.setLocation(bounds.getCenterX(),bounds.getCenterY());
157
158 if(rectangle.contains(p)) {
159 pickedVertices.add(v);
160 }
161 }
162 break;
163 } catch(ConcurrentModificationException cme) {}
164 }
165 return pickedVertices;
166 }
167
168
169
170
171 public E getEdge(Layout<V, E> layout, double x, double y) {
172
173 Point2D ip = ((MutableTransformerDecorator)vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)).getDelegate().inverseTransform(new Point2D.Double(x,y));
174 x = ip.getX();
175 y = ip.getY();
176
177
178
179
180 Rectangle2D pickArea =
181 new Rectangle2D.Float((float)x-pickSize/2,(float)y-pickSize/2,pickSize,pickSize);
182 E closest = null;
183 double minDistance = Double.MAX_VALUE;
184 while(true) {
185 try {
186 for(E e : getFilteredEdges(layout)) {
187
188 Pair<V> pair = layout.getGraph().getEndpoints(e);
189 V v1 = pair.getFirst();
190 V v2 = pair.getSecond();
191 boolean isLoop = v1.equals(v2);
192 Point2D p1 = layout.transform(v1);
193
194 Point2D p2 = layout.transform(v2);
195
196 if(p1 == null || p2 == null) continue;
197 float x1 = (float) p1.getX();
198 float y1 = (float) p1.getY();
199 float x2 = (float) p2.getX();
200 float y2 = (float) p2.getY();
201
202
203 AffineTransform xform = AffineTransform.getTranslateInstance(x1, y1);
204
205 Shape edgeShape =
206 vv.getRenderContext().getEdgeShapeTransformer().transform(Context.<Graph<V,E>,E>getInstance(vv.getGraphLayout().getGraph(),e));
207 if(isLoop) {
208
209 Shape s2 = vv.getRenderContext().getVertexShapeTransformer().transform(v2);
210 Rectangle2D s2Bounds = s2.getBounds2D();
211 xform.scale(s2Bounds.getWidth(),s2Bounds.getHeight());
212
213 xform.translate(0, -edgeShape.getBounds2D().getHeight()/2);
214 } else {
215 float dx = x2 - x1;
216 float dy = y2 - y1;
217
218 double theta = Math.atan2(dy,dx);
219 xform.rotate(theta);
220
221 float dist = (float) Math.sqrt(dx*dx + dy*dy);
222 xform.scale(dist, 1.0f);
223 }
224
225
226 edgeShape = xform.createTransformedShape(edgeShape);
227
228 edgeShape = vv.getRenderContext().getMultiLayerTransformer().transform(edgeShape);
229
230
231
232 if(edgeShape.intersects(pickArea)) {
233 float cx=0;
234 float cy=0;
235 float[] f = new float[6];
236 PathIterator pi = new GeneralPath(edgeShape).getPathIterator(null);
237 if(pi.isDone()==false) {
238 pi.next();
239 pi.currentSegment(f);
240 cx = f[0];
241 cy = f[1];
242 if(pi.isDone()==false) {
243 pi.currentSegment(f);
244 cx = f[0];
245 cy = f[1];
246 }
247 }
248 float dx = (float) (cx - x);
249 float dy = (float) (cy - y);
250 float dist = dx * dx + dy * dy;
251 if (dist < minDistance) {
252 minDistance = dist;
253 closest = e;
254 }
255 }
256 }
257 break;
258 } catch(ConcurrentModificationException cme) {}
259 }
260 return closest;
261 }
262 }