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.platform.preferences.lastsettings.UserModifiableProperty;
010    import graphlab.plugins.visualization.corebasics.extension.VisualizationExtension;
011    import graphlab.ui.UIUtils;
012    
013    import java.awt.geom.Point2D;
014    import java.util.HashMap;
015    import java.util.Iterator;
016    import java.util.Vector;
017    
018    /**
019     * @author Rouzbeh Ebrahimi
020     */
021    public class SparseTreeVisualization implements VisualizationExtension {
022        String event = UIUtils.getUIEventKey("SparseTreeVisualization");
023        public Vector<VertexModel> visitedVertices = new Vector<VertexModel>();
024        public HashMap<VertexModel, Point2D> vertexPlaces;
025        public Vector<VertexModel> children;
026    
027        private void unMarkVertices() {
028            for (VertexModel v : graph) {
029                v.setMark(false);
030            }
031        }
032    
033    
034        private VertexModel findAppropriateRoot(GraphModel g) {
035            VertexModel root = g.getAVertex();
036            Iterator<VertexModel> ei = g.iterator();
037            for (; ei.hasNext();) {
038                VertexModel e = ei.next();
039                root = findHigherVertex(e, root);
040            }
041            return root;
042        }
043    
044        private VertexModel findHigherVertex(VertexModel v1, VertexModel v2) {
045            Vector<VertexModel> t1 = new Vector<VertexModel>();
046            Vector<VertexModel> t2 = new Vector<VertexModel>();
047            t1.add(v1);
048            t2.add(v2);
049            if (BFS(t1, 0) > BFS(t2, 0)) {
050                return v1;
051            } else {
052                return v2;
053            }
054        }
055    
056        private int BFS(Vector<VertexModel> currentLevel, int maxLevel) {
057            Vector<VertexModel> nextLevel = new Vector<VertexModel>();
058            for (VertexModel v : currentLevel) {
059                v.setMark(true);
060                Iterator<EdgeModel> em = graph.edgeIterator(v);
061                for (; em.hasNext();) {
062                    EdgeModel e = em.next();
063                    VertexModel v2 = e.source;
064                    if (!v2.getMark()) {
065                        nextLevel.add(v2);
066                        v2.setMark(true);
067                    }
068                }
069            }
070            maxLevel++;
071            if (nextLevel.size() != 0) {
072                return BFS(nextLevel, maxLevel);
073            } else {
074                return maxLevel;
075            }
076        }
077    
078        static GraphModel graph;
079    
080        public void performJob(String eventName, Object value) {
081            visitedVertices = new Vector<VertexModel>();
082            vertexPlaces = new HashMap<VertexModel, Point2D>();
083            children = new Vector<VertexModel>();
084            try {
085                VertexModel root = findAppropriateRoot(graph);
086                visitedVertices.add(root);
087                unMarkVertices();
088                locateAll(visitedVertices, width, eachLevelHeigh);
089            } catch (NullPointerException e) {
090                System.out.println("Graph is Empty");
091    //            e.printStackTrace();
092            }
093    
094        }
095    
096    
097        public Vector<VertexModel> findNextLevelChildren(Vector<VertexModel> currentLevelVertices) {
098            Vector<VertexModel> newChildren = new Vector<VertexModel>();
099            for (VertexModel v : currentLevelVertices) {
100                Iterator<EdgeModel> e = graph.edgeIterator(v);
101                for (; e.hasNext();) {
102                    EdgeModel ed = e.next();
103                    VertexModel dest = ed.source;
104                    if (!visitedVertices.contains(dest)) {
105                        newChildren.add(dest);
106                    }
107                }
108            }
109            return newChildren;
110        }
111    
112        public void locateAll(Vector<VertexModel> currentLevelVertices, int width, int LevelHeight) {
113            int currentLevelCount = currentLevelVertices.size();
114            int i = 0;
115    
116            Vector<VertexModel> nextLevel = findNextLevelChildren(currentLevelVertices);
117            int nextLevelCount = nextLevel.size();
118            int horizontalDist = width / (currentLevelCount + nextLevelCount);
119    
120            for (VertexModel x : currentLevelVertices) {
121    
122            }
123            for (VertexModel v : currentLevelVertices) {
124                if (nextLevelCount != 0) {
125                    Point2D.Double newPoint = new Point2D.Double(horizontalDist * (i + 1) + width / (nextLevelCount + currentLevelCount), LevelHeight);
126                    vertexPlaces.put(v, newPoint);
127                    i += graph.getOutDegree(v);
128                } else {
129                    Point2D.Double newPoint = new Point2D.Double(horizontalDist * (i) + width / (currentLevelCount), LevelHeight);
130                    vertexPlaces.put(v, newPoint);
131                    i++;
132                }
133            }
134    
135            if (!nextLevel.isEmpty()) {
136                visitedVertices.addAll(nextLevel);
137                locateAll(nextLevel, width, LevelHeight + eachLevelHeigh);
138            } else {
139                return;
140            }
141        }
142    
143        public String getName() {
144            return "Sparse Tree Visualization";
145        }
146    
147        public String getDescription() {
148            return "Sparse Tree Visualization";
149        }/*
150         @param g
151        */
152    
153        public void setWorkingGraph(GraphModel g) {
154            this.graph = g;
155        }
156    
157        @UserModifiableProperty(displayName = "Sparse Tree Visualization Width", obeysAncestorCategory = false
158                , category = "Visualization Options")
159        public static Integer width = 800;
160        @UserModifiableProperty(displayName = "Sparse Tree Visualization : Each Level's height", obeysAncestorCategory = false
161                , category = "Visualization Options")
162        public static Integer eachLevelHeigh = 50;
163    
164        public HashMap<VertexModel, Point2D> getNewVertexPlaces() {
165            visitedVertices = new Vector<VertexModel>();
166            vertexPlaces = new HashMap<VertexModel, Point2D>();
167            children = new Vector<VertexModel>();
168            try {
169                VertexModel root = findAppropriateRoot(graph);
170                visitedVertices.add(root);
171                unMarkVertices();
172                locateAll(visitedVertices, width, eachLevelHeigh);
173            } catch (NullPointerException e) {
174                System.out.println("Graph is Empty");
175    //            e.printStackTrace();
176            }
177            return vertexPlaces;
178        }
179    
180        public HashMap<EdgeModel, Point2D> getNewEdgeCurveControlPoints() {
181            return null;  //To change body of implemented methods use File | Settings | File Templates.
182        }
183    }