I download GVF and run the demo. It is very cool.
I am wondering if it is possible to use the auto-layout algorithm in GVF and display the graph in my application (Not in Royere)?
If yes, can someone please tell me how to do it?
Thank you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
All of the layout algorithms in Royere extend the royere.cwi.layout.Layout class, and the key method in the Layout class is computePositions(). This method takes a graph object and assigns coordinates to all of its nodes.
If you prefer to render the graphs in your own application, you would do this:
(1) Convert your graph's node and edge objects to the Royere object model (i.e., instances of royere.cwi.structure.Node and royere.cwi.structure.Edge). Then populate a royere.cwi.structure.Graph object with them via the Graph.add() method.
(2) Choose a layout algorithm. This will be a subclass of royere.cwi.layout.Layout. (For example, royere.cwi.layout.ReingoldTilford.) However, you don't instantiate a layout object directly; layouts are constructed via LayoutFactory:
(3) Invoke the layout's computePositions() method to lay out the graph.
(4) Now, for every node in the graph, ask the layout object for the node's coordinates. (You can iterate through a graph's nodes via the Graph.getNodeTraversal() method.) Every node's coordinates will be an instance of royere.cwi.layout.Coordinates.
(5) Convert the Coordinates objects back to your object model.
(6) You now have coordinates for every node in the graph, so you can draw the graph however you want to in your application.
Does this answer your question?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for your detailed answer. Do you know what layout algorithm is/will support in GVF?
I got these layout algorithm from ilog's jviews.
# Hierarchical
# Tree
# Radial tree
# Topological mesh
# Circular (ring and star) and bus
# Spring embedder, uniform length and grid
thank you
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I tried what you suggested, but I got NullPointerException
java.lang.NullPointerException
at royere.cwi.layout.ReingoldTilford.setYcoordinates(ReingoldTilford.java:497)
at royere.cwi.layout.ReingoldTilford.setYcoordinates(ReingoldTilford.java:385)
at royere.cwi.layout.ReingoldTilford.secondWalk(ReingoldTilford.java:240)
at royere.cwi.layout.ReingoldTilford.computePositions(ReingoldTilford.java:296)
at Test.main(Test.java:43)
Here is my small test program:
import royere.cwi.layout.Coordinates;
import royere.cwi.layout.LayoutFactory;
import royere.cwi.layout.ReingoldTilford;
import royere.cwi.structure.Edge;
import royere.cwi.structure.Graph;
import royere.cwi.structure.Node;
public class Test {
public static void main(String[] args) {
Graph g = new Graph();
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
Node n4 = new Node();
Node n5 = new Node();
Node n6 = new Node();
Edge e1 = new Edge(n1, n2);
Edge e2 = new Edge(n2, n3);
Edge e3 = new Edge(n3, n4);
Edge e4 = new Edge(n4, n5);
Edge e5 = new Edge(n5, n6);
Could you please tell me what do I miss? And the computePositions() method is protected. Can that change to public? I am forced to cast the Layout object returned from LayoutFactory to ReingoldTilford because of that.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I can't test this directly because my test environment is currently broken but my initial guess is that what you're missing is the "directed" property for the graph:
g.setProperty(Keys.ISDIRECTED, Boolean.TRUE);
If you set this graph property *before* adding edges, then the lists of successors and predecessors for the affected nodes are updated whenever you add/remove an edge.
Note that if you attempted the same layout by calling the LayoutManager, you would get a "PropertyMismatch" error in the error log. Your test file is bypassing the pipeline and some of the builtin safeguards.
We are looking at changing some of the protected methods in a new release to make your type of application simpler to implement.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> I tried what you suggested, but I got NullPointerException
> java.lang.NullPointerException
> at
> royere.cwi.layout.ReingoldTilford.setYcoordinates(ReingoldTilford.java:497)
I was able to reproduce your error. Try inserting
layout.setGraph(g);
just before
layout.computePositions(g);
That solved the problem for me.
> And the computePositions() method is
> protected. Can that change to public?
We will change it to public in the next release.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
But when I layout the following graph using ReingoldTilford, all 4 nodes are layout hortonizally.
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
Node n4 = new Node();
Edge e1 = new Edge(n1, n2);
Edge e2 = new Edge(n1, n3);
Edge e3 = new Edge(n1, n4);
Why all 4 points are on the same line (y=0.0), I expect node 1 to be above node 2,3,4 (a hierachy structure).
Is this a correct assumption? Do I miss something?
Thank you.
Sam
========================================
the complete code:
public static void main(String[] args) {
Graph g = new Graph();
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
Node n4 = new Node();
Edge e1 = new Edge(n1, n2);
Edge e2 = new Edge(n1, n3);
Edge e3 = new Edge(n1, n4);
Reingold-Tilford uses the depth of each node (relative to the root) to determinte the node's Y coordinate. In order to determine depth, the edges must be directed. So you must explicitly set each edge's ISDIRECTED property to true:
It might be more user-friendly if the Graph.add(Edge) method automatically set this edge property for you, in those situations where the containing graph has been marked as directed. However, this assumes that the user would never want to insert an undirected edge into a graph that has directed edges (creating a hybrid graph). So, the responsibility is placed on whoever creates the Edge object to explicitly mark it as directed.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If I set the ISDIRECTED property to true, does that mean the To node (n1) and From node (n2) of an edge matters?
Edge e1 = new Edge(n1, n2);
Can I use different layout algorithms within the same graph?
For example, I want to use GVF to layout UML elements.
For Inheritance relationships, I want to use the Hirerachy layout, and for association relationships, I want to use the Ring layout. Is that possible?
One think I can think of is to use a 2 steps approach.
- walk thru the whole graph and find nodes with inheritance relationship only, build Graph, Node, Edges objects for that
- use GVF to layout that Graph ONLY using Hirerachy layout.
- lock all the nodes.
-add Node, Edges objects for nodes with association relationship,
- use GVF to layout the graph again using Ring layout.
Will this work? Does this make sense?
Thanks.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> If I set the ISDIRECTED property to true, does
> that mean the
> To node (n1) and
> From node (n2) of an edge matters?
> Edge e1 = new Edge(n1, n2);
The order of the parameters matters, i.e., n1 is the source node and n2 is the target node.
> Can I use different layout algorithms within the
> same graph?
>
> For example, I want to use GVF to layout UML elements.
>
> For Inheritance relationships, I want to use the
> Hirerachy layout, and
> for association relationships, I want to use the
> Ring layout.
> Is that possible?
Hello,
I tried to extend the example that is given here, and tried to print out the coordinates-set of the edges in the example. But I always got
NullPointerExceptions. So as a test, I added the following lines of code
So, for all the edges, I always get a null-object; and no coordinates-set for the edge.
I've tried to look at the problem myself, but can't to find the origin of the problem, or a solution. Maybe you can help me?
Thanks!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
> Coordinates[] edgeCoord = layout.getCoordinateSet(e1,g);
> System.out.println("edgeCoord: " + edgeCoord);
>
> And then I got as output
> edgeCoord: null
>
> So, for all the edges, I always get a null-object;
> and no coordinates-set for the edge.
Presently, Royere layouts assign coordinates to nodes, not edges.
The getCoordinateSet() and setCoordinateSet() methods exist to support "polyline" edges. A polyline edge consists of multiple line segments between the source and target nodes. This is useful, for example, if you want to approximate an arc.
A while ago I modified the code (specifically, the DCEdge constructor in DrawingControl.java) to make the simplifying assumption that an edge is always a single straight line segment from source to target. This makes it easier to deal with edges that start inside one graph and terminate inside a different one. (I can elaborate on this if you like, although it's a bit off-topic.) Abandoning polyline edges was admittedly a non-backward-compatible change; however, none of the stock Royere layout algorithms use polyline edges, and I wasn't aware of any users who needed this feature.
Do you need polyline edges? If so, I can update DrawingControl.java to support them. Of course, you would have to extend the appropriate Layout subclass and add the logic to assign the edge coordinates the way you want.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thanks for the quick response.
For now, I don't need polyline edges. So it's not necessary to adapt DrawingControl.java.
But I am still in a beginning phase of my project, so it is possible that in some time I notice that I would need them after all; and then I can contact you again,
Michael...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi,
I download GVF and run the demo. It is very cool.
I am wondering if it is possible to use the auto-layout algorithm in GVF and display the graph in my application (Not in Royere)?
If yes, can someone please tell me how to do it?
Thank you.
All of the layout algorithms in Royere extend the royere.cwi.layout.Layout class, and the key method in the Layout class is computePositions(). This method takes a graph object and assigns coordinates to all of its nodes.
If you prefer to render the graphs in your own application, you would do this:
(1) Convert your graph's node and edge objects to the Royere object model (i.e., instances of royere.cwi.structure.Node and royere.cwi.structure.Edge). Then populate a royere.cwi.structure.Graph object with them via the Graph.add() method.
(2) Choose a layout algorithm. This will be a subclass of royere.cwi.layout.Layout. (For example, royere.cwi.layout.ReingoldTilford.) However, you don't instantiate a layout object directly; layouts are constructed via LayoutFactory:
String layoutName = "Reingold-Tilford";
Layout rtLayout = LayoutFactory.createLayout(layoutName);
(3) Invoke the layout's computePositions() method to lay out the graph.
(4) Now, for every node in the graph, ask the layout object for the node's coordinates. (You can iterate through a graph's nodes via the Graph.getNodeTraversal() method.) Every node's coordinates will be an instance of royere.cwi.layout.Coordinates.
(5) Convert the Coordinates objects back to your object model.
(6) You now have coordinates for every node in the graph, so you can draw the graph however you want to in your application.
Does this answer your question?
Thanks for your detailed answer. Do you know what layout algorithm is/will support in GVF?
I got these layout algorithm from ilog's jviews.
# Hierarchical
# Tree
# Radial tree
# Topological mesh
# Circular (ring and star) and bus
# Spring embedder, uniform length and grid
thank you
> I got these layout algorithm from ilog's jviews.
I assume you mean http://www.ilog.com/products/jviews/graphlayout/ .
> Hierarchical
See royere.cwi.layout.ReingoldTilford.
> Tree
See royere.cwi.layout.ReingoldTilford.
> Radial tree
See royere.cwi.layout.Radial.
> Topological mesh
N/A. You'd have to implement this one yourself.
> Circular (ring and star) and bus
See royere.cwi.layout.Ring. No star or bus.
> Spring embedder, uniform length and grid
See royere.bath.layout.GEM -- this is a spring (force-directed) layout.
Thanks again.
Hi,
I tried what you suggested, but I got NullPointerException
java.lang.NullPointerException
at royere.cwi.layout.ReingoldTilford.setYcoordinates(ReingoldTilford.java:497)
at royere.cwi.layout.ReingoldTilford.setYcoordinates(ReingoldTilford.java:385)
at royere.cwi.layout.ReingoldTilford.secondWalk(ReingoldTilford.java:240)
at royere.cwi.layout.ReingoldTilford.computePositions(ReingoldTilford.java:296)
at Test.main(Test.java:43)
Here is my small test program:
import royere.cwi.layout.Coordinates;
import royere.cwi.layout.LayoutFactory;
import royere.cwi.layout.ReingoldTilford;
import royere.cwi.structure.Edge;
import royere.cwi.structure.Graph;
import royere.cwi.structure.Node;
public class Test {
public static void main(String[] args) {
Graph g = new Graph();
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
Node n4 = new Node();
Node n5 = new Node();
Node n6 = new Node();
Edge e1 = new Edge(n1, n2);
Edge e2 = new Edge(n2, n3);
Edge e3 = new Edge(n3, n4);
Edge e4 = new Edge(n4, n5);
Edge e5 = new Edge(n5, n6);
g.add(n1);
g.add(n2);
g.add(n3);
g.add(n4);
g.add(n5);
g.add(n6);
g.add(e1);
g.add(e2);
g.add(e3);
g.add(e4);
g.add(e5);
ReingoldTilford layout = (ReingoldTilford) LayoutFactory.createLayout("ReingoldTilford");
layout.computePositions(g);
Coordinates c = layout.getCoordinates(n1, g);
System.out.println("x=" + c.getX() + " y=" + c.getY());
c = layout.getCoordinates(n2, g);
System.out.println("x=" + c.getX() + " y=" + c.getY());
}
}
Could you please tell me what do I miss? And the computePositions() method is protected. Can that change to public? I am forced to cast the Layout object returned from LayoutFactory to ReingoldTilford because of that.
I can't test this directly because my test environment is currently broken but my initial guess is that what you're missing is the "directed" property for the graph:
g.setProperty(Keys.ISDIRECTED, Boolean.TRUE);
If you set this graph property *before* adding edges, then the lists of successors and predecessors for the affected nodes are updated whenever you add/remove an edge.
Note that if you attempted the same layout by calling the LayoutManager, you would get a "PropertyMismatch" error in the error log. Your test file is bypassing the pipeline and some of the builtin safeguards.
We are looking at changing some of the protected methods in a new release to make your type of application simpler to implement.
Thanks for your suggestion. I tried that, but it still gives me the same problem.
> I tried what you suggested, but I got NullPointerException
> java.lang.NullPointerException
> at
> royere.cwi.layout.ReingoldTilford.setYcoordinates(ReingoldTilford.java:497)
I was able to reproduce your error. Try inserting
layout.setGraph(g);
just before
layout.computePositions(g);
That solved the problem for me.
> And the computePositions() method is
> protected. Can that change to public?
We will change it to public in the next release.
Thanks. I got that to work.
But when I layout the following graph using ReingoldTilford, all 4 nodes are layout hortonizally.
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
Node n4 = new Node();
Edge e1 = new Edge(n1, n2);
Edge e2 = new Edge(n1, n3);
Edge e3 = new Edge(n1, n4);
g.setProperty(Keys.ISDIRECTED, Boolean.TRUE);
g.add(n1);
g.add(n2);
g.add(n3);
g.add(n4);
g.add(e1);
g.add(e2);
g.add(e3);
When I print out the co-ordinate, I got this:
x=0.0 y=0.0
x=1.2000000000000002 y=0.0
x=2.4000000000000004 y=0.0
x=3.6000000000000005 y=0.0
Why all 4 points are on the same line (y=0.0), I expect node 1 to be above node 2,3,4 (a hierachy structure).
Is this a correct assumption? Do I miss something?
Thank you.
Sam
========================================
the complete code:
public static void main(String[] args) {
Graph g = new Graph();
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
Node n4 = new Node();
Edge e1 = new Edge(n1, n2);
Edge e2 = new Edge(n1, n3);
Edge e3 = new Edge(n1, n4);
g.setProperty(Keys.ISDIRECTED, Boolean.TRUE);
g.add(n1);
g.add(n2);
g.add(n3);
g.add(n4);
g.add(e1);
g.add(e2);
g.add(e3);
ReingoldTilford layout =
(ReingoldTilford) LayoutFactory.createLayout("ReingoldTilford");
layout.setGraph(g);
layout.computePositions(g);
Coordinates c = layout.getCoordinates(n1, g);
System.out.println("x=" + c.getX() + " y=" + c.getY());
c = layout.getCoordinates(n2, g);
System.out.println("x=" + c.getX() + " y=" + c.getY());
c = layout.getCoordinates(n3, g);
System.out.println("x=" + c.getX() + " y=" + c.getY());
c = layout.getCoordinates(n4, g);
System.out.println("x=" + c.getX() + " y=" + c.getY());
}
Reingold-Tilford uses the depth of each node (relative to the root) to determinte the node's Y coordinate. In order to determine depth, the edges must be directed. So you must explicitly set each edge's ISDIRECTED property to true:
e1.setProperty(Keys.ISDIRECTED, Boolean.TRUE);
e2.setProperty(Keys.ISDIRECTED, Boolean.TRUE);
e3.setProperty(Keys.ISDIRECTED, Boolean.TRUE);
It might be more user-friendly if the Graph.add(Edge) method automatically set this edge property for you, in those situations where the containing graph has been marked as directed. However, this assumes that the user would never want to insert an undirected edge into a graph that has directed edges (creating a hybrid graph). So, the responsibility is placed on whoever creates the Edge object to explicitly mark it as directed.
Thanks again.
If I set the ISDIRECTED property to true, does that mean the To node (n1) and From node (n2) of an edge matters?
Edge e1 = new Edge(n1, n2);
Can I use different layout algorithms within the same graph?
For example, I want to use GVF to layout UML elements.
For Inheritance relationships, I want to use the Hirerachy layout, and for association relationships, I want to use the Ring layout. Is that possible?
One think I can think of is to use a 2 steps approach.
- walk thru the whole graph and find nodes with inheritance relationship only, build Graph, Node, Edges objects for that
- use GVF to layout that Graph ONLY using Hirerachy layout.
- lock all the nodes.
-add Node, Edges objects for nodes with association relationship,
- use GVF to layout the graph again using Ring layout.
Will this work? Does this make sense?
Thanks.
> If I set the ISDIRECTED property to true, does
> that mean the
> To node (n1) and
> From node (n2) of an edge matters?
> Edge e1 = new Edge(n1, n2);
The order of the parameters matters, i.e., n1 is the source node and n2 is the target node.
> Can I use different layout algorithms within the
> same graph?
>
> For example, I want to use GVF to layout UML elements.
>
> For Inheritance relationships, I want to use the
> Hirerachy layout, and
> for association relationships, I want to use the
> Ring layout.
> Is that possible?
Let's handle this question in a separate thread (see "Using multiple layout algorithms in one view" at
http://sourceforge.net/forum/forum.php?thread_id=768684&forum_id=126557\).
Hello,
I tried to extend the example that is given here, and tried to print out the coordinates-set of the edges in the example. But I always got
NullPointerExceptions. So as a test, I added the following lines of code
Coordinates[] edgeCoord = layout.getCoordinateSet(e1,g);
System.out.println("edgeCoord: " + edgeCoord);
And then I got as output
edgeCoord: null
So, for all the edges, I always get a null-object; and no coordinates-set for the edge.
I've tried to look at the problem myself, but can't to find the origin of the problem, or a solution. Maybe you can help me?
Thanks!
> Coordinates[] edgeCoord = layout.getCoordinateSet(e1,g);
> System.out.println("edgeCoord: " + edgeCoord);
>
> And then I got as output
> edgeCoord: null
>
> So, for all the edges, I always get a null-object;
> and no coordinates-set for the edge.
Presently, Royere layouts assign coordinates to nodes, not edges.
The getCoordinateSet() and setCoordinateSet() methods exist to support "polyline" edges. A polyline edge consists of multiple line segments between the source and target nodes. This is useful, for example, if you want to approximate an arc.
A while ago I modified the code (specifically, the DCEdge constructor in DrawingControl.java) to make the simplifying assumption that an edge is always a single straight line segment from source to target. This makes it easier to deal with edges that start inside one graph and terminate inside a different one. (I can elaborate on this if you like, although it's a bit off-topic.) Abandoning polyline edges was admittedly a non-backward-compatible change; however, none of the stock Royere layout algorithms use polyline edges, and I wasn't aware of any users who needed this feature.
Do you need polyline edges? If so, I can update DrawingControl.java to support them. Of course, you would have to extend the appropriate Layout subclass and add the logic to assign the edge coordinates the way you want.
Thanks for the quick response.
For now, I don't need polyline edges. So it's not necessary to adapt DrawingControl.java.
But I am still in a beginning phase of my project, so it is possible that in some time I notice that I would need them after all; and then I can contact you again,
Michael...