001 // GraphLab Project: http://graphlab.sharif.edu 002 // Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology 003 // Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/ 004 package graphlab.plugins.visualization.treevisualizations; 005 006 import graphlab.graph.graph.EdgeModel; 007 import graphlab.graph.graph.GraphModel; 008 import graphlab.graph.graph.VertexModel; 009 import graphlab.library.BaseVertexProperties; 010 import graphlab.platform.preferences.lastsettings.UserModifiableProperty; 011 import graphlab.plugins.visualization.corebasics.extension.VisualizationExtension; 012 import graphlab.ui.UIUtils; 013 014 import java.awt.geom.Point2D; 015 import java.util.HashMap; 016 import java.util.HashSet; 017 import java.util.Iterator; 018 import java.util.Vector; 019 020 /** 021 * @author Rouzbeh Ebrahimi 022 */ 023 public class CircularTreeVisualization implements VisualizationExtension { 024 String event = UIUtils.getUIEventKey("CircularTreeVisualization"); 025 public Vector<VertexModel> visitedVertices = new Vector<VertexModel>(); 026 public HashSet<VertexModel> placedVertices = new HashSet<VertexModel>(); 027 public HashMap<VertexModel, Point2D> vertexPlaces = new HashMap<VertexModel, Point2D>(); 028 VertexModel root; 029 public Vector<VertexModel> children = new Vector<VertexModel>(); 030 public HashMap<VertexModel, Integer> vertexHeights = new HashMap<VertexModel, Integer>(); 031 @UserModifiableProperty(displayName = "Circular Tree Visualization Radius", obeysAncestorCategory = false 032 , category = "Visualization Options") 033 public static Integer radius = 80; 034 035 private VertexModel findAppropriateRoot(GraphModel g) { 036 VertexModel root = g.getAVertex(); 037 Iterator<VertexModel> ei = g.iterator(); 038 for (; ei.hasNext();) { 039 VertexModel e = ei.next(); 040 root = findHigherVertex(e, root); 041 } 042 return root; 043 } 044 045 private VertexModel findHigherVertex(VertexModel v1, VertexModel v2) { 046 Vector<VertexModel> t1 = new Vector<VertexModel>(); 047 Vector<VertexModel> t2 = new Vector<VertexModel>(); 048 t1.add(v1); 049 t2.add(v2); 050 int i = maxHeight(t1, 0); 051 vertexHeights.put(v1, i); 052 int j = maxHeight(t2, 0); 053 vertexHeights.put(v2, i); 054 if (i > j) { 055 return v1; 056 } else { 057 return v2; 058 } 059 } 060 061 private int maxHeight(Vector<VertexModel> currentLevel, int maxLevel) { 062 063 Vector<VertexModel> nextLevel = new Vector<VertexModel>(); 064 for (VertexModel v : currentLevel) { 065 v.setMark(true); 066 Iterator<EdgeModel> em = g.edgeIterator(v); 067 for (; em.hasNext();) { 068 EdgeModel e = em.next(); 069 VertexModel v2 = e.source; 070 if (!v2.getMark()) { 071 nextLevel.add(v2); 072 v2.setMark(true); 073 } 074 } 075 } 076 maxLevel++; 077 if (nextLevel.size() != 0) { 078 return maxHeight(nextLevel, maxLevel); 079 } else { 080 return maxLevel; 081 } 082 } 083 084 static GraphModel g; 085 086 /* public void performJob(Event eventName, Object value) { 087 visitedVertices = new Vector<VertexModel>(); 088 vertexPlaces = new HashMap<VertexModel, Point2D>(); 089 children = new Vector<VertexModel>(); 090 placedVertices = new HashSet<VertexModel>(); 091 092 try { 093 root = findAppropriateRoot(g); 094 unMarkVertices(); 095 visitedVertices.add(root); 096 locateAll(visitedVertices, 800, 80); 097 *//*BaseVertexProperties properties = new BaseVertexProperties(root.getColor(), root.getMark()); 098 properties.obj = new Double(2*Math.PI); 099 root.setProp(properties); 100 locateAllSubTrees(root, 40, 0);*//* 101 GeneralAnimator t = new GeneralAnimator(vertexPlaces, g, blackboard); 102 t.start(); 103 } catch (NullPointerException e) { 104 System.out.println("Graph is Empty"); 105 // e.printStackTrace(); 106 } 107 108 }*/ 109 110 public void locateAllSubTrees(VertexModel v, double radius, double offSet) { 111 if (placedVertices.contains(root)) { 112 double angularSpan = (Double) v.getProp().obj; 113 int numberOfDivides = 1; 114 numberOfDivides = g.getOutDegree(v); 115 if (numberOfDivides == 0) { 116 return; 117 } 118 Iterator<EdgeModel> iter = g.edgeIterator(v); 119 int j = 0; 120 int sum = 0; 121 for (; iter.hasNext();) { 122 EdgeModel e = iter.next(); 123 VertexModel v1 = e.source.equals(v) ? e.target : e.source; 124 if (!placedVertices.contains(v1)) { 125 sum += g.getOutDegree(v1); 126 } else { 127 } 128 } 129 iter = g.edgeIterator(v); 130 for (; iter.hasNext();) { 131 EdgeModel e = iter.next(); 132 VertexModel v1 = e.source.equals(v) ? e.target : e.source; 133 if (!placedVertices.contains(v1)) { 134 double x = 350 + radius * Math.cos((angularSpan * j / (numberOfDivides + 1) + offSet)); 135 double y = 350 + radius * Math.sin((angularSpan * j / (numberOfDivides + 1) + offSet)); 136 double newOffset = (angularSpan * j / numberOfDivides + offSet); 137 Point2D.Double newPoint = new Point2D.Double(x, y); 138 vertexPlaces.put(v1, newPoint); 139 placedVertices.add(v1); 140 BaseVertexProperties properties = new BaseVertexProperties(v1.getColor(), v1.getMark()); 141 properties.obj = new Double((angularSpan / sum) * (g.getOutDegree(v))); 142 v1.setProp(properties); 143 locateAllSubTrees(v1, 2 * radius, newOffset); 144 j++; 145 146 } else { 147 } 148 149 } 150 return; 151 } else { 152 double x = 350; 153 double y = 350; 154 Point2D.Double newPoint = new Point2D.Double(x, y); 155 placedVertices.add(v); 156 vertexPlaces.put(v, newPoint); 157 locateAllSubTrees(v, radius, offSet); 158 } 159 } 160 161 private void unMarkVertices() { 162 for (VertexModel v : g) { 163 v.setMark(false); 164 } 165 } 166 167 168 public Vector<VertexModel> findNextLevelChildren(Vector<VertexModel> currentLevelVertices) { 169 Vector<VertexModel> newChildren = new Vector<VertexModel>(); 170 for (VertexModel v : currentLevelVertices) { 171 Iterator<EdgeModel> e = g.edgeIterator(v); 172 for (; e.hasNext();) { 173 EdgeModel ed = e.next(); 174 VertexModel dest = ed.source; 175 if (!visitedVertices.contains(dest)) { 176 newChildren.add(dest); 177 } 178 } 179 } 180 return newChildren; 181 } 182 183 184 public void locateAll(Vector<VertexModel> currentLevelVertices, int width, int radius) { 185 int currentLevelCount = currentLevelVertices.size(); 186 Vector<VertexModel> nextLevel = findNextLevelChildren(currentLevelVertices); 187 int nextLevelCount = nextLevel.size(); 188 double degree = 360 / currentLevelCount; 189 int j = 0; 190 if (currentLevelCount == 1 && currentLevelVertices.elementAt(0).equals(root)) { 191 Point2D.Double newPoint = new Point2D.Double(350, 350); 192 vertexPlaces.put(root, newPoint); 193 194 } else { 195 for (VertexModel v : currentLevelVertices) { 196 double x = 350 + radius * Math.cos((Math.PI / 180) * (j * degree)); 197 double y = 350 + radius * Math.sin((Math.PI / 180) * (j * degree)); 198 Point2D.Double newPoint = new Point2D.Double(x, y); 199 vertexPlaces.put(v, newPoint); 200 j++; 201 202 } 203 } 204 205 if (!nextLevel.isEmpty()) { 206 visitedVertices.addAll(nextLevel); 207 locateAll(nextLevel, width, radius + radius * 3 / 8); 208 } else { 209 return; 210 } 211 } 212 213 public String getName() { 214 return "Circular Tree Visualization"; 215 } 216 217 public String getDescription() { 218 return null; //To change body of implemented methods use File | Settings | File Templates. 219 }/* 220 @param g 221 */ 222 223 public void setWorkingGraph(GraphModel g) { 224 this.g = g; 225 } 226 227 public HashMap<VertexModel, Point2D> getNewVertexPlaces() { 228 visitedVertices = new Vector<VertexModel>(); 229 vertexPlaces = new HashMap<VertexModel, Point2D>(); 230 children = new Vector<VertexModel>(); 231 placedVertices = new HashSet<VertexModel>(); 232 233 try { 234 root = findAppropriateRoot(g); 235 unMarkVertices(); 236 visitedVertices.add(root); 237 locateAll(visitedVertices, 800, radius); 238 /*BaseVertexProperties properties = new BaseVertexProperties(root.getColor(), root.getMark()); 239 properties.obj = new Double(2*Math.PI); 240 root.setProp(properties); 241 locateAllSubTrees(root, 40, 0);*/ 242 243 } catch (NullPointerException e) { 244 System.out.println("Graph is Empty"); 245 // e.printStackTrace(); 246 } 247 return vertexPlaces; 248 } 249 250 public HashMap<EdgeModel, Point2D> getNewEdgeCurveControlPoints() { 251 return null; //To change body of implemented methods use File | Settings | File Templates. 252 } 253 }