EdgeSelectionHelper.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package de.tu_darmstadt.informatik.tk.scopviz.main;
  2. import java.util.Iterator;
  3. import org.graphstream.algorithm.Toolkit;
  4. import org.graphstream.ui.geom.Point3;
  5. import org.graphstream.ui.graphicGraph.GraphPosLengthUtils;
  6. import org.graphstream.ui.view.Camera;
  7. import de.tu_darmstadt.informatik.tk.scopviz.graphs.GraphManager;
  8. import de.tu_darmstadt.informatik.tk.scopviz.graphs.MyEdge;
  9. import de.tu_darmstadt.informatik.tk.scopviz.graphs.MyNode;
  10. /**
  11. * This class contains helpful static functions.
  12. *
  13. * @author Matthias Wilhelm
  14. * @version 1.0
  15. */
  16. public final class EdgeSelectionHelper {
  17. /**
  18. * Private Constructor to prevent instantiation. private
  19. * EdgeSelectionHelper(){}
  20. *
  21. * /** Width in pixels for which the edge selection triggers.
  22. */
  23. private static final int EDGE_SELECTION_WIDTH = 5;
  24. /**
  25. * Precalculates pi / 2.
  26. */
  27. private static final double HALF_PI = Math.PI / 2;
  28. private EdgeSelectionHelper() {
  29. }
  30. // TODO optional: only update if view has changed
  31. /**
  32. * Returns the closest Edge in the current Graph to a given position. It
  33. * allows for an inaccuracy of around {@value #EDGE_SELECTION_WIDTH}px
  34. *
  35. * @param pos
  36. * The position. Expects a <b>Point3</b>, but only uses the x and
  37. * y coordinates
  38. * @return the closest Edge if a valid Edge exists, returns <b>null</b>
  39. * otherwise
  40. */
  41. public static MyEdge getClosestEdge(Point3 pos) {
  42. Camera cam = Main.getInstance().getGraphManager().getView().getCamera();
  43. // gets to points within a fixed distance of each other and calculates
  44. // the gu of those points
  45. Point3 min = cam.transformPxToGu(0, 0);
  46. Point3 max = cam.transformPxToGu(EDGE_SELECTION_WIDTH, EDGE_SELECTION_WIDTH);
  47. // calculates the approximate distance by taken the maximum of the
  48. // absolute Distances of the x's or y's
  49. double dist = Math.max(Math.abs(max.x - min.x), Math.abs(max.y - min.y));
  50. // calls the actual calculation
  51. return getClosestEdge(pos, dist);
  52. }
  53. /**
  54. * Returns the closest Edge in the current Graph to a given position within
  55. * the given maxDistance.
  56. *
  57. * @param pos
  58. * The position. Expects a <b>Point3</b>, but only uses the x and
  59. * y coordinates
  60. * @param maxDistance
  61. * the maximum distance (in gu) the edge may be away from the
  62. * position to be considered as a valid edge
  63. * @return the closest Edge if a valid Edge exists, returns <b>null</b>
  64. * otherwise
  65. */
  66. public static MyEdge getClosestEdge(Point3 pos, double maxDistance) {
  67. double x0 = pos.x;
  68. double y0 = pos.y;
  69. // keeps track of the current smallest distance to an edge;
  70. // initializes to the given maxDistance
  71. double dist = maxDistance;
  72. // keeps track of the current closest edge
  73. MyEdge result = null;
  74. GraphManager gm = Main.getInstance().getGraphManager();
  75. // Iterates over every edge, calculates the distance and updates the
  76. // best edge and corresponding distance
  77. for (Iterator<MyEdge> iterator = gm.getGraph().getEdgeIterator(); iterator.hasNext();) {
  78. MyEdge edge = iterator.next();
  79. // Get the positions of the nodes of the currently selected edge.
  80. double[] n1 = GraphPosLengthUtils.nodePosition(edge.getNode0());
  81. double[] n2 = GraphPosLengthUtils.nodePosition(edge.getNode1());
  82. // Extract the x and y values of the positions of the nodes
  83. double x1 = n1[0];
  84. double y1 = n1[1];
  85. double x2 = n2[0];
  86. double y2 = n2[1];
  87. // Calculate the distance between the nodes
  88. // Naming convention is view node 0 as A, node 1 as B and the point
  89. // as C in a triangle
  90. double c = distance(x1, y1, x2, y2); // Distance Node0 Node1
  91. // Calculate the distance between the edge and the point
  92. double cdist = Math.abs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1) / c;
  93. // Check if the edge is closer than the currently stored one
  94. if (cdist < dist) {
  95. // Calculate the distances from each node to the point
  96. double a = distance(x0, y0, x2, y2); // Distance Point Node0
  97. double b = distance(x0, y0, x1, y1); // Distance Point Node1
  98. // Precalculate the squares of the distances for later use
  99. double b2 = b * b;
  100. double a2 = a * a;
  101. double c2 = c * c;
  102. // Calculates the inner angles off the triangle
  103. double alpha = Math.acos((b2 + c2 - a2) / (2 * b * c));
  104. double beta = Math.acos((a2 + c2 - b2) / (2 * a * c));
  105. // Check if the point is actually visually next to the edge by
  106. // checking if both inner angles are less than 90°
  107. if (alpha <= HALF_PI && beta <= HALF_PI) {
  108. dist = cdist;
  109. result = edge;
  110. }
  111. }
  112. }
  113. return result;
  114. }
  115. /**
  116. * Calculates the distance between two given Nodes.
  117. *
  118. * @param a
  119. * Node 1
  120. * @param b
  121. * Node 2
  122. * @return the distance between the two Nodes as a double
  123. */
  124. public static double distance(MyNode a, MyNode b) {
  125. double[] n1 = GraphPosLengthUtils.nodePosition(a);
  126. double[] n2 = GraphPosLengthUtils.nodePosition(b);
  127. return distance(n1[0], n1[1], n2[0], n2[1]);
  128. }
  129. /**
  130. * Calculates the distance between a x,y position and a Node.
  131. *
  132. * @param x0
  133. * x cord of the position
  134. * @param y0
  135. * y cord of the position
  136. * @param a
  137. * the Node
  138. * @return the distance between the position and the Node as a double
  139. */
  140. public static double distance(double x0, double y0, MyNode a) {
  141. double[] n1 = GraphPosLengthUtils.nodePosition(a);
  142. return distance(x0, y0, n1[0], n1[1]);
  143. }
  144. /**
  145. * Calculates the distance between two x,y positions.
  146. *
  147. * @param x0
  148. * x cord of the first position
  149. * @param y0
  150. * y cord of the first position
  151. * @param x1
  152. * x cord of the second position
  153. * @param y1
  154. * y cord of the second position
  155. * @return the distance between the two positions as a double
  156. */
  157. public static double distance(double x0, double y0, double x1, double y1) {
  158. return Math.sqrt(Math.pow(y0 - y1, 2) + Math.pow(x0 - x1, 2));
  159. }
  160. }