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.graphgenerator.core.PositionGenerators;
012    import graphlab.plugins.visualization.corebasics.extension.VisualizationExtension;
013    import graphlab.ui.UIUtils;
014    
015    import java.awt.geom.Point2D;
016    import java.util.HashMap;
017    import java.util.HashSet;
018    import java.util.Iterator;
019    import java.util.Vector;
020    
021    /**
022     * @author Rouzbeh Ebrahimi
023     */
024    public class BackwardTrees implements VisualizationExtension {
025        String event = UIUtils.getUIEventKey("BackwardTrees");
026        public Vector<VertexModel> visitedVertices = new Vector<VertexModel>();
027        public Vector<VertexModel> upperLevelVertices = new Vector<VertexModel>();
028    
029        public HashMap<VertexModel, Point2D> vertexPlaces = new HashMap<VertexModel, Point2D>();
030        public Vector<VertexModel> children = new Vector<VertexModel>();
031        public HashMap<VertexModel, Double> comingFrom = new HashMap<VertexModel, Double>();
032        VertexModel root;
033    
034    
035        static GraphModel g;
036        /**
037         * @param eventName
038         * @param value
039         */
040        public HashSet<VertexModel> placedVertices = new HashSet<VertexModel>();
041        @UserModifiableProperty(displayName = "BackWard Tree Visualization Radius", obeysAncestorCategory = false
042                , category = "Visualization Options")
043        public static Integer radius = 60;
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            if (BFS(t1, 0) > BFS(t2, 0)) {
051                return v1;
052            } else {
053                return v2;
054            }
055        }
056    
057        private VertexModel findAppropriateRoot(GraphModel g) {
058            VertexModel root = g.getAVertex();
059            Iterator<VertexModel> ei = g.iterator();
060            for (; ei.hasNext();) {
061                VertexModel e = ei.next();
062                root = findHigherVertex(e, root);
063            }
064            return root;
065        }
066    
067        private int BFS(Vector<VertexModel> currentLevel, int maxLevel) {
068            Vector<VertexModel> nextLevel = new Vector<VertexModel>();
069            for (VertexModel v : currentLevel) {
070                v.setMark(true);
071                Iterator<EdgeModel> em = g.edgeIterator(v);
072                for (; em.hasNext();) {
073                    EdgeModel e = em.next();
074                    VertexModel v2 = e.source;
075                    if (!v2.getMark()) {
076                        nextLevel.add(v2);
077                        v2.setMark(true);
078                    }
079                }
080            }
081            maxLevel++;
082            if (nextLevel.size() != 0) {
083                return BFS(nextLevel, maxLevel);
084            } else {
085                return maxLevel;
086            }
087        }
088    
089        public Vector<VertexModel> findNextLevelChildren(Vector<VertexModel> currentLevelVertices) {
090            Vector<VertexModel> newChildren = new Vector<VertexModel>();
091            if (currentLevelVertices.size() != 0) {
092                for (VertexModel v : currentLevelVertices) {
093                    Iterator<EdgeModel> e = g.edgeIterator(v);
094                    for (; e.hasNext();) {
095                        EdgeModel ed = e.next();
096                        VertexModel dest = ed.source;
097                        if (!visitedVertices.contains(dest)) {
098                            newChildren.add(dest);
099                        }
100                    }
101                }
102            } else {
103            }
104            return newChildren;
105        }
106    
107        public void locateAll(Vector<VertexModel> currentLevelVertices, int width, int currentLevelHeight, int level, int radius) {
108    
109            int currentLevelCount = currentLevelVertices.size();
110            int horizontalDist = width / currentLevelCount;
111            int i = 0;
112            Vector<VertexModel> nextLevel = findNextLevelChildren(currentLevelVertices);
113            if (currentLevelCount == 1 && currentLevelVertices.elementAt(0).equals(root)) {
114                Point2D.Double newPoint = new Point2D.Double(200, 200);
115                vertexPlaces.put(root, newPoint);
116                comingFrom.put(root, 0.0);
117            } else {
118                for (VertexModel v : upperLevelVertices) {
119                    Iterator<EdgeModel> ei = g.edgeIterator(v);
120                    int degree = g.getInDegree(v);
121                    double p = comingFrom.get(v);
122                    int j = 0;
123    
124                    double phase;
125                    phase = 360 / (degree);
126                    Point2D[] circle = PositionGenerators.circle((int) v.getLocation().getX(), (int) v.getLocation().getY(), radius, radius, degree);
127                    int t = 0;
128                    for (; ei.hasNext();) {
129                        VertexModel ver = ei.next().source;
130    //                    double x;
131    //                    double y;
132    //                    double xPhase = Math.cos(((j * phase)+p) * Math.PI / 180);
133    //                    x = vertexPlaces.get(v).getX() + radius * xPhase;
134    //                    double yPhase = Math.sin(((j * phase)+p ) * Math.PI / 180);
135    //                    y = vertexPlaces.get(v).getY() + radius * yPhase;
136                        comingFrom.put(ver, (j * phase) + p);
137    //                     Point2D.Double newPoint = new Point2D.Double(x, y);
138                        vertexPlaces.put(ver, circle[t]);
139                        j++;
140                        t++;
141    
142                    }
143                }
144    
145    //        for (Vertex v : currentLevelVertices) {
146    //            Point2D.Double newPoint = new Point2D.Double(horizontalDist * i + width / (currentLevelCount + 1), currentLevelHeight);
147    //            vertexPlaces.put(v,newPoint);
148    //            i++;
149    //        }
150            }
151            upperLevelVertices = currentLevelVertices;
152            if (!nextLevel.isEmpty()) {
153                visitedVertices.addAll(nextLevel);
154                locateAll(nextLevel, width, currentLevelHeight + 30, level + 1, radius * 9 / 16);
155            } else {
156                return;
157            }
158        }
159    
160        private void unMarkVertices() {
161            for (VertexModel v : g) {
162                v.setMark(false);
163            }
164        }
165    
166    
167        public void locateAllSubTrees(VertexModel v, double radius, double offSet) {
168            if (placedVertices.contains(root)) {
169                double angularSpan = (Double) v.getProp().obj;
170                int numberOfDivides = 1;
171                numberOfDivides = g.getInDegree(v);
172                if (numberOfDivides == 0) {
173                    return;
174                }
175                Iterator<EdgeModel> iter = g.edgeIterator(v);
176                int sum = 0;
177                for (; iter.hasNext();) {
178                    EdgeModel e = iter.next();
179                    VertexModel v1 = e.source.equals(v) ? e.target : e.source;
180                    if (!placedVertices.contains(v1)) {
181                        sum += g.getInDegree(v1);
182                    } else {
183                    }
184                }
185                iter = g.edgeIterator(v);
186                int j = 1;
187                for (; iter.hasNext();) {
188                    EdgeModel e = iter.next();
189                    VertexModel v1 = e.source.equals(v) ? e.target : e.source;
190                    if (!placedVertices.contains(v1)) {
191                        double x = 350 + radius * Math.cos((angularSpan * j / (numberOfDivides) + offSet));
192                        double y = 350 + radius * Math.sin((angularSpan * j / (numberOfDivides) + offSet));
193                        double newOffset = (angularSpan * j / numberOfDivides + offSet);
194                        Point2D.Double newPoint = new Point2D.Double(x, y);
195                        vertexPlaces.put(v1, newPoint);
196                        placedVertices.add(v1);
197                        BaseVertexProperties properties = new BaseVertexProperties(v1.getColor(), v1.getMark());
198                        properties.obj = new Double((angularSpan / (Math.abs(sum))) * (g.getInDegree(v1)));
199                        v1.setProp(properties);
200                        locateAllSubTrees(v1, this.radius + radius, newOffset);
201                        j++;
202    
203                    } else {
204                    }
205    
206                }
207                return;
208            } else {
209                double x = 350;
210                double y = 350;
211                Point2D.Double newPoint = new Point2D.Double(x, y);
212                placedVertices.add(v);
213                vertexPlaces.put(v, newPoint);
214                locateAllSubTrees(v, radius, offSet);
215            }
216        }
217    
218        public String getName() {
219            return "BackWard Tree Visualization";
220        }
221    
222        public String getDescription() {
223            return null;  //To change body of implemented methods use File | Settings | File Templates.
224        }/*
225         @param g
226        */
227    
228        public void setWorkingGraph(GraphModel g) {
229            this.g = g;
230        }
231    
232        public HashMap<VertexModel, Point2D> getNewVertexPlaces() {
233            visitedVertices = new Vector<VertexModel>();
234            vertexPlaces = new HashMap<VertexModel, Point2D>();
235            children = new Vector<VertexModel>();
236            placedVertices = new HashSet<VertexModel>();
237            try {
238                root = findAppropriateRoot(g);
239                visitedVertices.add(root);
240                unMarkVertices();
241    //            locateAll(visitedVertices, 600, 50, 1,200);
242                BaseVertexProperties properties = new BaseVertexProperties(root.getColor(), root.getMark());
243                properties.obj = new Double(2 * Math.PI);
244                root.setProp(properties);
245    
246                locateAllSubTrees(root, radius, 0);
247    //            GeneralAnimator t = new GeneralAnimator(vertexPlaces, g, blackboard);
248    //            t.start();
249            } catch (NullPointerException e) {
250    //            System.out.println("Graph is Empty");
251                e.printStackTrace();
252            }
253            return vertexPlaces;
254        }
255    
256        public HashMap<EdgeModel, Point2D> getNewEdgeCurveControlPoints() {
257            return null;  //To change body of implemented methods use File | Settings | File Templates.
258        }
259    }
260