GraphStream Users

Archives de la liste Aide


Re: Questions about RMI


Chronologique Discussions 
  • From: Antoine Dutot <antoine.dutot AT gmail.com>
  • To: graphstream-users AT litislab.fr
  • Subject: Re: Questions about RMI
  • Date: Tue, 25 Oct 2011 17:33:51 +0200

Hi Nuno,

The viewer runs in a different thread than the main thread. This is the viewer thread that manages how to compute the xyz (from yet another thread in fact). In the viewer thread a "graphic graph" is used to store all the data needed to visualize the graph, and these "xyz" attributes.

Using several threads allows to take account of multiple CPU cores, and having a separate graphic graph allows to avoid to much synchronization between the two threads (the critical section would be the graph, which is clearly the main data structure).

The viewer is a sink for your graph as soon as you call graph.display(). All your changes are reflected in the graphic graph. This is done automatically by the viewer that regularly "synchronize" the graphic graph with your graph. So to get back the data from the graphic graph, you should make your graph a sink of the graphic graph (yes, it forms a loop :-)). This could be tricky since the two graphs are in different threads, but a special class was created for this purpose. The only "drawback" is that you must regularly look at what happened in the graphic graph to get back the "xyz" from the graphic thread.

    Graph graph = new MultiGraph("main graph");
    Viewer viewer = graph.display(); // Creation of the graphic graph.
    ViewerPipe fromView = viewer.newViewerPipe(); // An object allowing thread-safe communication with the viewer
    fromView.addAttributeSink(graph); // Listen at the changes in the graphic graph.

    ...

    while(true) {
        fromView.pump(); // Look regularly at the graphic thread to get back information.
        System.out.printf("Node positions:%n");
        for(Node node:graph) {
            double[] pos = nodePosition(node);
            System.out.printf("    [%s] (%f, %f, %f)%n", node.getId(), pos[0], pos[1], pos[2]);
        }
    }

I attach to this reply a full example.

The reason this is not yet in the documentation section, is that the "pipe" from the viewer is still a work in progress (but usable, though). 

Hope it will help you,

Antoine

2011/10/25 Stefan Balev <stefan.balev AT gmail.com>
Hi Nuno,
The layout algorithm uses a special object of type GraphicGraph which
is a sort of copy of your original graph. It changes the "xyz"
attributes of this object. I am not yet quite sure why it does not
provide a coordinate feedback, this should be either unimplemented
feature or a bug. While waiting for a fix, you have two possible
workarounds.
1. Get a reference to the GraphicGraph and use it instead of the original graph:
Viewer v = g.display();Graph gg = v.getGraphicGraph();
2. A better solution is perhaps to get the coordinate changes back to
your original graph. To see how this works, please take a look on this
thread:http://sympa.litislab.fr/sympa/arc/graphstream-users/2011-08/msg00000.html
Hope this helps,
--Stefan

2011/10/25  <Nuno.Carvalho AT uk.fujitsu.com>:
> Hi Yoann, all,
>
> Yes, that worked very well, thanks!
>
> Now I have another issue. I'm doing some tests on a small example, without using RMI.
>
> I'm creating nodes and letting the toolkit position them freely. But then, I want to retrieve their position to (for instance) change the view center to a specific node and zoom on it. But I can't retrieve their x,y position.
>
> I tried the Toolkit.nodePosition(node) and node.getNumber("x"), etc, everything gives me a null, or NaN or 0.0.
> I read somewhere that I need to enable the feedback on these variables, so I tried calling Viewer.enableXYZfeedback(true) on the viewer returned by graph.display() and still nothing.
>
> Can someone help me?
>
> Thanks and kind regards,
> Nuno
>
> -----Original Message-----
> From: Yoann Pigné [mailto:yoann.pigne AT gmail.com]
> Sent: 20 October 2011 15:28
> To: graphstream-users AT litislab.fr
> Subject: Re: Questions about RMI
>
> Hi Numo,
>
>
> In the documentation, the "Generator" part is just an example. Actually the RMISink only waits for a source to register on it. A Graph is a source too, so you can replace the "generator" part with your graph.
>
> From the example on the documentation :
>
> Generator gen = new XXXGenerator();
> gen.addSink(sink);
>
> can become:
>
> Graph g = new DefaultGraph("My graph");
> g.addSink(sink);
>
> and then you can use the  addNode/Edge methods you are used to :
>
> g.addNode("node1");
> g.addNode("node2");
> g.addEdge("edge1", "node1","node2");
>
> Hope It will help you,
>
> Let us know,
>
> Yoann
>
>
> On Oct 20, 2011, at 3:55 PM, <Nuno.Carvalho AT uk.fujitsu.com> wrote:
>
>> Dear all,
>>
>> I'm just started using GraphStream and I must say that this is a very powerful tool.
>> Now I want to use it with the RMI functionality. I want to implement the following scenario:
>>
>> -          Process A is generating Nodes and Edges for the Graph
>> -          Process B is just getting the new nodes and edges and displaying it on the screen.
>>
>> For that, I've been trying to follow this tutorial:
>> http://graphstream-project.org/doc/Tutorials/Using-remote-source_1.0/
>>
>> So, before I had something like this:
>>
>> Graph graph = new SingleGraph("g");
>> graph.display();
>> graph.addNode(...);
>> graph.addEdge(...);
>> // and so on...
>>
>> Now I have this code split in two parts:
>>
>> On one side, I have the part that displays the graph on the screen, which is very simple:
>> RMISource source = new RMISource();
>> Graph graph = new DefaultGraph("g");
>> source.addSink(graph);
>> graph.display();
>>
>>
>> On the other process, I must have an RMISink where I push the new nodes and edges, right?
>> So, I must have the following:
>> RMISink sink = new RMISink();
>> Sink.register(...);
>>
>> Then, according to the Tutorial, I have to create a Generator, connect it to the Sink and start loop on the generator.nextEvents();
>>
>> The questions that I have are the following:
>> -          The generator must be implemented by myself, based on my graph data source, or I can use some already implemented Generator with a interface similar to what I have for graphs(addNode, addEdge, etc)?
>> -          If I need to implement my own generator, how should I do it? Is there any tutorial to do this? I'm missing this part: how to add nodes and edges, and push it to the RMISink...
>>
>> All help will be much appreciated!
>>
>> Thanks and kind regards,
>> Nuno
>>
>>
>>
>> ______________________________________________________________________
>>
>>  Fujitsu Laboratories of Europe Limited
>>  Hayes Park Central, Hayes End Road, Hayes, Middlesex, UB4 8FE
>>  Registered No. 4153469
>>
>>  This e-mail and any attachments are for the sole use of addressee(s) and
>>  may contain information which is privileged and confidential. Unauthorised
>>  use or copying for disclosure is strictly prohibited. The fact that this
>>  e-mail has been scanned by Trendmicro Interscan does not guarantee that
>>  it has not been intercepted or amended nor that it is virus-free.
>>
>
> ______________________________________________________________________
>
>  Fujitsu Laboratories of Europe Limited
>  Hayes Park Central, Hayes End Road, Hayes, Middlesex, UB4 8FE
>  Registered No. 4153469
>
>  This e-mail and any attachments are for the sole use of addressee(s) and
>  may contain information which is privileged and confidential. Unauthorised
>  use or copying for disclosure is strictly prohibited. The fact that this
>  e-mail has been scanned by Trendmicro Interscan does not guarantee that
>  it has not been intercepted or amended nor that it is virus-free.
>
>

package org.graphstream.ui.viewer.test;

import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.MultiGraph;
import org.graphstream.ui.swingViewer.Viewer;
import org.graphstream.ui.swingViewer.ViewerListener;
import org.graphstream.ui.swingViewer.ViewerPipe;

import static org.graphstream.ui.graphicGraph.GraphPosLengthUtils.*;

public class TestEvents implements ViewerListener {

	public static void main(String args[]) {
		new TestEvents();
	}
	
	public TestEvents() {
		Graph graph = new MultiGraph("main graph");
		Viewer viewer = graph.display();
		ViewerPipe fromView = viewer.newViewerPipe();
		fromView.addAttributeSink(graph);
		fromView.addViewerListener(this);

		graph.addNode("A");
		graph.addNode("B");
		graph.addNode("C");
		graph.addEdge("AB", "A", "B");
		graph.addEdge("BC", "B", "C");
		graph.addEdge("CA", "C", "A");
		
		//viewer.setCloseFramePolicy(Viewer.CloseFramePolicy.HIDE_ONLY);
		
		while(true) {
			fromView.pump();
			
			try { Thread.sleep(10); } catch (Exception e) {}
			
			System.out.printf("Node positions:%n");
			for(Node node:graph) {
				double[] pos = nodePosition(node);
				System.out.printf("    [%s] (%f, %f, %f)%n", node.getId(), pos[0], pos[1], pos[2]);
			}
		}
	}

	
	public void viewClosed(String viewName) {
		System.err.printf("View closed%n");
	}

	public void buttonPushed(String id) {
		System.err.printf("pushed %s%n", id);
	}

	public void buttonReleased(String id) {
		System.err.printf("released %s%n", id);
	}
}



Archives gérées par MHonArc 2.6.16.

Top of page