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