Force-Directed Edge Bundling
 All Classes Functions
Edge.java
1 import java.util.ArrayList;
2 
9 public class Edge {
10 
11  private ArrayList<Node> subNodes;
12  private ArrayList<Node> tempSubNodes;
13  private Node endNode;
14  private Node startNode;
15 
21  public Edge(Node startNode, Node endNode){
22  if(startNode.getX() <= endNode.getX()){
23  this.startNode = startNode;
24  this.endNode = endNode;
25  } else{
26  this.endNode = startNode;
27  this.startNode = endNode;
28  }
29  }
30 
35  public Node getEndNode() {
36  return endNode;
37  }
38 
43  public void setEndNode(Node endNode) {
44  this.endNode = endNode;
45  }
46 
51  public Node getStartNode() {
52  return startNode;
53  }
54 
59  public void setStartNode(Node startNode) {
60  this.startNode = startNode;
61  }
62 
67  public ArrayList<Node> getSubNodes(){
68  return subNodes;
69  }
70 
75  public ArrayList<Node> getTempSubNodes(){
76  return tempSubNodes;
77  }
78 
83  public void setTempSubNodes(ArrayList<Node> subNodes){
84  tempSubNodes = subNodes;
85  }
86 
92  public boolean isIncident(Node node){
93  return (node.equals(startNode) || node.equals(endNode));
94  }
95 
100  public double dx(){
101  return endNode.getX()-startNode.getX();
102  }
103 
108  public double dy(){
109  return endNode.getY()-startNode.getY();
110  }
111 
117  public double compatibility(Edge other){
118  return angleComp(other)*posComp(other)*scaleComp(other)*visComp(other);
119  }
120 
125  public double magnitude(){
126  return Math.sqrt(dx()*dx()+dy()*dy());
127  }
128 
135  public double visibility(Edge other){
136  Node ds = new Node(other.getStartNode().getX()+dy(), other.getStartNode().getY()-dx());
137  Node de = new Node(other.getEndNode().getX()+dy(), other.getEndNode().getY()-dx());
138  Node is = lineIntersection(new Edge(other.getStartNode(), ds));
139  Node ie = lineIntersection(new Edge(other.getEndNode(), de));
140  Node im = new Edge(is, ie).midPoint();
141  if(is == null || im == null || ie == null)
142  return 0;
143  return Math.max(0, 1-(2*midPoint().distance(im))/is.distance(ie));
144  }
145 
150  public int[] subNodesXInt(){
151  int[] subX = new int[subNodes.size()];
152  for(int i=0; i < subNodes.size(); i++){
153  subX[i] = subNodes.get(i).getXInt();
154  }
155  return subX;
156  }
157 
162  public int[] subNodesYInt(){
163  int[] subY = new int[subNodes.size()];
164  for(int i=0; i < subNodes.size(); i++){
165  subY[i] = subNodes.get(i).getYInt();
166  }
167  return subY;
168  }
169 
174  public Node midPoint(){
175  double x = (startNode.getX()+endNode.getX())/2;
176  double y = (startNode.getY()+endNode.getY())/2;
177  return new Node(x,y);
178  }
179 
183  public void deleteSubNodes(){
184  subNodes = null;
185  }
186 
190  public void finalizeSubNodes(){
191  subNodes = tempSubNodes;
192  tempSubNodes = null;
193  }
194 
198  public void increaseSubNodes(){
199  if (subNodes == null){
200  subNodes = new ArrayList<Node>();
201  subNodes.add(startNode);
202  subNodes.add(midPoint());
203  subNodes.add(endNode);
204  } else{
205  ArrayList<Node> tempList = new ArrayList<Node>();
206  for(int i=0; i < subNodes.size()-1; i++){
207  tempList.add(subNodes.get(i));
208  tempList.add(new Node((subNodes.get(i).getX()+subNodes.get(i+1).getX())/2,
209  (subNodes.get(i).getY()+subNodes.get(i+1).getY())/2));
210  }
211  tempList.add(endNode);
212  subNodes = tempList;
213  }
214  }
215 
221  private double angleComp(Edge other){
222  double angle = Math.cos(Math.acos(Math.abs((dx()*other.dx()+dy()*other.dy())
223  / (magnitude()*other.magnitude()))));
224  return angle;
225  }
226 
232  private double posComp(Edge other){
233  Edge bridge = new Edge(midPoint(), other.midPoint());
234  double lavg = (magnitude()+other.magnitude())/2;
235  double pos = lavg/(lavg+bridge.magnitude());
236  return pos;
237  }
238 
244  private double scaleComp(Edge other){
245  double lavg = (magnitude()+other.magnitude())/2;
246  double scale = 2/(lavg/Math.min(magnitude(), other.magnitude())
247  + Math.max(magnitude(), other.magnitude())/lavg);
248  return scale;
249  }
250 
256  private double visComp(Edge other){
257  return Math.min(visibility(other), other.visibility(this));
258  }
259 
266  private Node lineIntersection(Edge other){
267  double x1 = startNode.getX();
268  double y1 = startNode.getY();
269  double x2 = endNode.getX();
270  double y2 = endNode.getY();
271  double x3 = other.getStartNode().getX();
272  double y3 = other.getStartNode().getY();
273  double x4 = other.getEndNode().getX();
274  double y4 = other.getEndNode().getY();
275 
276  if((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4) == 0)
277  return null;
278  double px = ((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));
279  double py = ((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4));
280  return new Node(px, py);
281  }
282 }