// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.plugins.visualization.treevisualizations;
import graphtea.graph.graph.Edge;
import graphtea.graph.graph.GPoint;
import graphtea.graph.graph.GraphModel;
import graphtea.graph.graph.Vertex;
import graphtea.library.BaseVertexProperties;
import graphtea.platform.core.exception.ExceptionHandler;
import graphtea.platform.preferences.lastsettings.UserModifiableProperty;
import graphtea.plugins.graphgenerator.core.PositionGenerators;
import graphtea.plugins.visualization.corebasics.extension.VisualizationExtension;
import graphtea.ui.UIUtils;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;
/**
* @author Rouzbeh Ebrahimi
*/
public class BackwardTrees implements VisualizationExtension {
String event = UIUtils.getUIEventKey("BackwardTrees");
public Vector<Vertex> visitedVertices = new Vector<>();
public Vector<Vertex> upperLevelVertices = new Vector<>();
public HashMap<Vertex, GPoint> vertexPlaces = new HashMap<>();
public Vector<Vertex> children = new Vector<>();
public HashMap<Vertex, Double> comingFrom = new HashMap<>();
Vertex root;
static GraphModel g;
/**
* @param eventName The event name
* @param value The avlue
*/
public HashSet<Vertex> placedVertices = new HashSet<>();
@UserModifiableProperty(displayName = "BackWard Tree Visualization Radius", obeysAncestorCategory = false
, category = "Visualization Options")
public static Integer radius = 60;
private Vertex findHigherVertex(Vertex v1, Vertex v2) {
Vector<Vertex> t1 = new Vector<>();
Vector<Vertex> t2 = new Vector<>();
t1.add(v1);
t2.add(v2);
if (BFS(t1, 0) > BFS(t2, 0)) {
return v1;
} else {
return v2;
}
}
private Vertex findAppropriateRoot(GraphModel g) {
Vertex root = g.getAVertex();
Iterator<Vertex> ei = g.iterator();
for (; ei.hasNext();) {
Vertex e = ei.next();
root = findHigherVertex(e, root);
}
return root;
}
private int BFS(Vector<Vertex> currentLevel, int maxLevel) {
Vector<Vertex> nextLevel = new Vector<>();
for (Vertex v : currentLevel) {
v.setMark(true);
Iterator<Edge> em = g.edgeIterator(v);
for (; em.hasNext();) {
Edge e = em.next();
Vertex v2 = e.source;
if (!v2.getMark()) {
nextLevel.add(v2);
v2.setMark(true);
}
}
}
maxLevel++;
if (nextLevel.size() != 0) {
return BFS(nextLevel, maxLevel);
} else {
return maxLevel;
}
}
public Vector<Vertex> findNextLevelChildren(Vector<Vertex> currentLevelVertices) {
Vector<Vertex> newChildren = new Vector<>();
if (currentLevelVertices.size() != 0) {
for (Vertex v : currentLevelVertices) {
Iterator<Edge> e = g.edgeIterator(v);
for (; e.hasNext();) {
Edge ed = e.next();
Vertex dest = ed.source;
if (!visitedVertices.contains(dest)) {
newChildren.add(dest);
}
}
}
} else {
}
return newChildren;
}
public void locateAll(Vector<Vertex> currentLevelVertices, int width, int currentLevelHeight, int level, int radius) {
int currentLevelCount = currentLevelVertices.size();
int horizontalDist = width / currentLevelCount;
int i = 0;
Vector<Vertex> nextLevel = findNextLevelChildren(currentLevelVertices);
if (currentLevelCount == 1 && currentLevelVertices.elementAt(0).equals(root)) {
GPoint newPoint = new GPoint(200, 200);
vertexPlaces.put(root, newPoint);
comingFrom.put(root, 0.0);
} else {
for (Vertex v : upperLevelVertices) {
Iterator<Edge> ei = g.edgeIterator(v);
int degree = g.getInDegree(v);
double p = comingFrom.get(v);
int j = 0;
double phase;
phase = 360 / (degree);
GPoint[] circle = PositionGenerators.convert(PositionGenerators.circle((int) v.getLocation().getX(), (int) v.getLocation().getY(), radius, radius, degree));
int t = 0;
for (; ei.hasNext();) {
Vertex ver = ei.next().source;
// double x;
// double y;
// double xPhase = Math.cos(((j * phase)+p) * Math.PI / 180);
// x = vertexPlaces.get(v).getX() + radius * xPhase;
// double yPhase = Math.sin(((j * phase)+p ) * Math.PI / 180);
// y = vertexPlaces.get(v).getY() + radius * yPhase;
comingFrom.put(ver, (j * phase) + p);
// GPoint newPoint = new GPoint(x, y);
vertexPlaces.put(ver, circle[t]);
j++;
t++;
}
}
// for (Vertex v : currentLevelVertices) {
// GPoint newPoint = new GPoint(horizontalDist * i + width / (currentLevelCount + 1), currentLevelHeight);
// vertexPlaces.put(v,newPoint);
// i++;
// }
}
upperLevelVertices = currentLevelVertices;
if (!nextLevel.isEmpty()) {
visitedVertices.addAll(nextLevel);
locateAll(nextLevel, width, currentLevelHeight + 30, level + 1, radius * 9 / 16);
} else {
return;
}
}
private void unMarkVertices() {
for (Vertex v : g) {
v.setMark(false);
}
}
public void locateAllSubTrees(Vertex v, double radius, double offSet) {
if (placedVertices.contains(root)) {
double angularSpan = (Double) v.getProp().obj;
int numberOfDivides = 1;
numberOfDivides = g.getInDegree(v);
if (numberOfDivides == 0) {
return;
}
Iterator<Edge> iter = g.edgeIterator(v);
int sum = 0;
for (; iter.hasNext();) {
Edge e = iter.next();
Vertex v1 = e.source.equals(v) ? e.target : e.source;
if (!placedVertices.contains(v1)) {
sum += g.getInDegree(v1);
} else {
}
}
iter = g.edgeIterator(v);
int j = 1;
for (; iter.hasNext();) {
Edge e = iter.next();
Vertex v1 = e.source.equals(v) ? e.target : e.source;
if (!placedVertices.contains(v1)) {
double x = 350 + radius * Math.cos((angularSpan * j / (numberOfDivides) + offSet));
double y = 350 + radius * Math.sin((angularSpan * j / (numberOfDivides) + offSet));
double newOffset = (angularSpan * j / numberOfDivides + offSet);
GPoint newPoint = new GPoint(x, y);
vertexPlaces.put(v1, newPoint);
placedVertices.add(v1);
BaseVertexProperties properties = new BaseVertexProperties(v1.getColor(), v1.getMark());
properties.obj = new Double((angularSpan / (Math.abs(sum))) * (g.getInDegree(v1)));
v1.setProp(properties);
locateAllSubTrees(v1, this.radius + radius, newOffset);
j++;
} else {
}
}
return;
} else {
double x = 350;
double y = 350;
GPoint newPoint = new GPoint(x, y);
placedVertices.add(v);
vertexPlaces.put(v, newPoint);
locateAllSubTrees(v, radius, offSet);
}
}
public String getName() {
return "BackWard Tree Visualization";
}
public String getDescription() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}/*
@param g
*/
public void setWorkingGraph(GraphModel g) {
this.g = g;
}
public HashMap<Vertex, GPoint> getNewVertexPlaces() {
visitedVertices = new Vector<>();
vertexPlaces = new HashMap<>();
children = new Vector<>();
placedVertices = new HashSet<>();
try {
root = findAppropriateRoot(g);
visitedVertices.add(root);
unMarkVertices();
// locateAll(visitedVertices, 600, 50, 1,200);
BaseVertexProperties properties = new BaseVertexProperties(root.getColor(), root.getMark());
properties.obj = 2 * Math.PI;
root.setProp(properties);
locateAllSubTrees(root, radius, 0);
// GeneralAnimator t = new GeneralAnimator(vertexPlaces, g, blackboard);
// t.start();
} catch (NullPointerException e) {
// System.out.println("Graph is Empty");
ExceptionHandler.catchException(e);
}
return vertexPlaces;
}
public HashMap<Edge, GPoint> getNewEdgeCurveControlPoints() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
}