1 /*
2 * Copyright (c) 2005, the JUNG Project and the Regents of the University of
3 * California All rights reserved.
4 *
5 * This software is open-source under the BSD license; see either "license.txt"
6 * or http://jung.sourceforge.net/license.txt for a description.
7 *
8 *
9 * Created on Apr 12, 2005
10 */
11 package edu.uci.ics.jung.algorithms.layout3d;
12
13 import java.util.ConcurrentModificationException;
14
15 import javax.vecmath.Point3f;
16
17
18
19 /**
20 * Simple implementation of PickSupport that returns the vertex or edge
21 * that is closest to the specified location. This implementation
22 * provides the same picking options that were available in
23 * previous versions of AbstractLayout.
24 *
25 * <p>No element will be returned that is farther away than the specified
26 * maximum distance.
27 *
28 * @author Tom Nelson
29 * @author Joshua O'Madadhain
30 */
31 public class RadiusGraphElementAccessor<V, E> implements GraphElementAccessor<V, E> {
32
33 protected double maxDistance;
34
35 /**
36 * Creates an instance with an effectively infinite default maximum distance.
37 */
38 public RadiusGraphElementAccessor() {
39 this(Math.sqrt(Double.MAX_VALUE - 1000));
40 }
41
42 /**
43 * Creates an instance with the specified default maximum distance.
44 */
45 public RadiusGraphElementAccessor(double maxDistance) {
46 this.maxDistance = maxDistance;
47 }
48
49 /**
50 * Gets the vertex nearest to the location of the (x,y) location selected,
51 * within a distance of <tt>maxDistance</tt>. Iterates through all
52 * visible vertices and checks their distance from the click. Override this
53 * method to provde a more efficient implementation.
54 */
55 public V getVertex(Layout<V,E> layout, Point3f p) {
56 return getVertex(layout, p, this.maxDistance);
57 }
58
59 /**
60 * Gets the vertex nearest to the location of the (x,y) location selected,
61 * within a distance of <tt>maxDistance</tt>. Iterates through all
62 * visible vertices and checks their distance from the click. Override this
63 * method to provde a more efficient implementation.
64 * @param x
65 * @param y
66 * @param maxDistance temporarily overrides member maxDistance
67 */
68 public V getVertex(Layout<V,E> layout, Point3f p, double maxDistance) {
69 double minDistance = maxDistance * maxDistance;
70 V closest = null;
71 while(true) {
72 try {
73 for(V v : layout.getGraph().getVertices()) {
74
75 Point3f p2 = layout.transform(v);
76 double dist = p.distance(p2);
77 if (dist < minDistance) {
78 minDistance = dist;
79 closest = v;
80 }
81 }
82 break;
83 } catch(ConcurrentModificationException cme) {}
84 }
85 return closest;
86 }
87
88 /**
89 * Gets the edge nearest to the location of the (x,y) location selected.
90 * Calls the longer form of the call.
91 */
92 // public E getEdge(Layout<V,E> layout, double x, double y) {
93 // return getEdge(layout, x, y, this.maxDistance);
94 // }
95
96 /**
97 * Gets the edge nearest to the location of the (x,y) location selected,
98 * within a distance of <tt>maxDistance</tt>, Iterates through all
99 * visible edges and checks their distance from the click. Override this
100 * method to provide a more efficient implementation.
101 *
102 * @param x
103 * @param y
104 * @param maxDistance temporarily overrides member maxDistance
105 * @return Edge closest to the click.
106 */
107 // public E getEdge(Layout<V,E> layout, Point3f p, double maxDistance) {
108 // double minDistance = maxDistance * maxDistance;
109 // E closest = null;
110 // while(true) {
111 // try {
112 // for(E e : layout.getGraph().getEdges()) {
113 //
114 // // Could replace all this set stuff with getFrom_internal() etc.
115 // Graph<V, E> graph = layout.getGraph();
116 // Collection<V> vertices = graph.getIncidentVertices(e);
117 // Iterator<V> vertexIterator = vertices.iterator();
118 // V v1 = vertexIterator.next();
119 // V v2 = vertexIterator.next();
120 // // Get coords
121 // Point3f p1 = layout.transform(v1);
122 // Point3f p2 = layout.transform(v2);
123 // double x = p.getX();
124 // double y = p.getY();
125 // double z = p.getZ();
126 // double x1 = p1.getX();
127 // double y1 = p1.getY();
128 // double z1 = p1.getZ();
129 // double x2 = p2.getX();
130 // double y2 = p2.getY();
131 // double z2 = p2.getZ();
132 //
133 // // Calculate location on line closest to (x,y)
134 // // First, check that v1 and v2 are not coincident.
135 // if (x1 == x2 && y1 == y2 && z1 == z2)
136 // continue;
137 // double b =
138 // ((y - y1) * (y2 - y1) + (x - x1) * (x2 - x1))
139 // / ((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
140 // //
141 // double distance2; // square of the distance
142 // if (b <= 0)
143 // distance2 = (x - x1) * (x - x1) + (y - y1) * (y - y1);
144 // else if (b >= 1)
145 // distance2 = (x - x2) * (x - x2) + (y - y2) * (y - y2);
146 // else {
147 // double x3 = x1 + b * (x2 - x1);
148 // double y3 = y1 + b * (y2 - y1);
149 // distance2 = (x - x3) * (x - x3) + (y - y3) * (y - y3);
150 // }
151 //
152 // if (distance2 < minDistance) {
153 // minDistance = distance2;
154 // closest = e;
155 // }
156 // }
157 // break;
158 // } catch(ConcurrentModificationException cme) {}
159 // }
160 // return closest;
161 // }
162 }