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.hierarchical;
005    
006    import graphlab.graph.atributeset.GraphAttrSet;
007    import graphlab.graph.graph.EdgeModel;
008    import graphlab.graph.graph.GraphModel;
009    import graphlab.graph.graph.VertexModel;
010    import graphlab.platform.core.AbstractAction;
011    import graphlab.platform.core.BlackBoard;
012    import graphlab.plugins.visualization.corebasics.animator.GeneralAnimator;
013    import graphlab.ui.UIUtils;
014    
015    import java.awt.geom.Point2D;
016    import java.util.HashMap;
017    import java.util.Iterator;
018    import java.util.Vector;
019    
020    /**
021     * @author Rouzbeh Ebrahimi
022     */
023    public class BendedTrees extends AbstractAction {
024        String event = UIUtils.getUIEventKey("BendedTrees");
025        public Vector<VertexModel> visitedVertices = new Vector<VertexModel>();
026        public HashMap<VertexModel, Point2D> vertexPlaces = new HashMap<VertexModel, Point2D>();
027        public HashMap<EdgeModel, Vector<Point2D>> edgeBendPoints = new HashMap<EdgeModel, Vector<Point2D>>();
028        public Vector<VertexModel> children = new Vector<VertexModel>();
029        public GraphModel graph;
030    
031        /**
032         * constructor
033         *
034         * @param bb the blackboard of the action
035         */
036        public BendedTrees(BlackBoard bb) {
037            super(bb);
038            listen4Event(event);
039        }
040    
041        private VertexModel findAppropriateRoot(GraphModel g) {
042            VertexModel root = g.getAVertex();
043            Iterator<VertexModel> ei = g.iterator();
044            for (; ei.hasNext();) {
045                VertexModel e = ei.next();
046                root = findHigherVertex(e, root);
047            }
048            return root;
049        }
050    
051        private VertexModel findHigherVertex(VertexModel v1, VertexModel v2) {
052            Vector<VertexModel> t1 = new Vector<VertexModel>();
053            Vector<VertexModel> t2 = new Vector<VertexModel>();
054            t1.add(v1);
055            t2.add(v2);
056            if (BFS(new Vector<VertexModel>(), t1, 0) > BFS(new Vector<VertexModel>(), t2, 0)) {
057                return v1;
058            } else {
059                return v2;
060            }
061        }
062    
063        private int BFS(Vector<VertexModel> marked, Vector<VertexModel> currentLevel, int maxLevel) {
064            marked.addAll(currentLevel);
065            Vector<VertexModel> nextLevel = new Vector<VertexModel>();
066            for (VertexModel v : currentLevel) {
067                v.setMark(true);
068                Iterator<EdgeModel> em = g.edgeIterator(v);
069                for (; em.hasNext();) {
070                    EdgeModel e = em.next();
071                    VertexModel v2 = e.source;
072                    if (!marked.contains(v2)) {
073                        nextLevel.add(v2);
074                    }
075                }
076            }
077            maxLevel++;
078            if (nextLevel.size() != 0) {
079                return BFS(marked, nextLevel, maxLevel);
080            } else {
081                return maxLevel;
082            }
083        }
084    
085        static GraphModel g;
086    
087        public void performAction(String eventName, Object value) {
088            visitedVertices = new Vector<VertexModel>();
089            vertexPlaces = new HashMap<VertexModel, Point2D>();
090            children = new Vector<VertexModel>();
091            edgeBendPoints = new HashMap<EdgeModel, Vector<Point2D>>();
092            g = ((GraphModel) (blackboard.getData(GraphAttrSet.name)));
093            try {
094                this.graph = g;
095                VertexModel root = findAppropriateRoot(g);
096                visitedVertices.add(root);
097                locateAllVertices(visitedVertices, 800, 50);
098                reshapeAllEdges();
099                GeneralAnimator t = new GeneralAnimator(vertexPlaces, edgeBendPoints, g, blackboard);
100                t.start();
101            } catch (NullPointerException e) {
102                System.out.println("Graph is Empty");
103    //            e.printStackTrace();
104            }
105    
106        }
107    
108        public Vector<VertexModel> findNextLevelChildren(Vector<VertexModel> currentLevelVertices) {
109            Vector<VertexModel> newChildren = new Vector<VertexModel>();
110            for (VertexModel v : currentLevelVertices) {
111                Iterator<EdgeModel> e = g.edgeIterator(v);
112                for (; e.hasNext();) {
113                    EdgeModel ed = e.next();
114                    VertexModel dest = ed.source;
115                    if (!visitedVertices.contains(dest)) {
116                        newChildren.add(dest);
117                    }
118                }
119            }
120            return newChildren;
121        }
122    
123        public void reshapeAllEdges() {
124            Iterator<EdgeModel> ei = graph.edgeIterator();
125            for (; ei.hasNext();) {
126                EdgeModel e = ei.next();
127                Point2D d1 = vertexPlaces.get(e.target);
128                Point2D d2 = vertexPlaces.get(e.source);
129                Vector<Point2D> bendPoints = new Vector<Point2D>();
130                bendPoints.add(new Point2D.Double(d1.getX(), d1.getY() - 15));
131                bendPoints.add(new Point2D.Double(d2.getX(), d2.getY() + 15));
132                edgeBendPoints.put(e, bendPoints);
133            }
134        }
135    
136        public void locateAllVertices(Vector<VertexModel> currentLevelVertices, int width, int currentLevelHeight) {
137            int currentLevelCount = currentLevelVertices.size();
138            int i = 0;
139    
140            Vector<VertexModel> nextLevel = findNextLevelChildren(currentLevelVertices);
141            int nextLevelCount = nextLevel.size();
142            int horizontalDist = width / (currentLevelCount + nextLevelCount);
143    
144    
145            for (VertexModel v : currentLevelVertices) {
146                if (nextLevelCount != 0) {
147                    Point2D.Double newPoint = new Point2D.Double(horizontalDist * (i + 1) + width / (nextLevelCount + currentLevelCount), currentLevelHeight);
148                    vertexPlaces.put(v, newPoint);
149                    i += g.getInDegree(v);
150                } else {
151                    Point2D.Double newPoint = new Point2D.Double(horizontalDist * (i) + width / (currentLevelCount), currentLevelHeight);
152                    vertexPlaces.put(v, newPoint);
153                    i++;
154                }
155            }
156    
157            if (!nextLevel.isEmpty()) {
158                visitedVertices.addAll(nextLevel);
159                locateAllVertices(nextLevel, width, currentLevelHeight + 30);
160            } else {
161                return;
162            }
163        }
164    }