NodeXLControl Vertices with same location when animating graph.

May 8, 2013 at 9:04 AM
Hello,

I have written a C# Windows Form based application to display the memberOf links in active directory. The user wants to be able to show the hierarchy a level at a time and this is accomplished by creating additional vertices and edges and calling DrawGrapth(true) to re-render the graph for each iteration (a sort of step-by-step animation).
However, when I use this mechanism multiple vertices are created with the same location co-ordinates at each iteration. Does anyone have any idea why this might be happening and what can be done about it?
Coordinator
May 8, 2013 at 3:25 PM
Tony D:

I'm not sure I understand the problem you're describing. You're adding vertices and edges to the graph (but not removing any), calling DrawGraph(true), and you find that after the graph is drawn, multiple vertices end up at the exact same vertex locations? Are you determining this visually or by programmatically looking at the Vertex.Location property?

I'm not near a development computer and so I can't try your technique right now to determine if there might be a bug somewhere, but as an experiment, try inserting this line before you redraw the graph:

nodeXLControl.Layout = new Smrf.NodeXL.Layouts.FruchtermanReingoldLayout();

Does that change the results?

-- Tony C
May 9, 2013 at 11:27 AM
Tony,
Thanks for you quick response.
You have paraphrased the problem correctly: I am adding nodes and edges to the graph and redrawing at which point multiple vertices end up with the same location.
I have tried nodeXLControl.Layout = new Smrf.NodeXL.Layouts.FruchtermanReingoldLayout(); but this does not change the outcome.
To add some more detail; only the last set of vertices to be added are co-located at each redraw, previous duplications are resolved - for example:
At the first pass one vertex (1) is added
At the second pass, four further vertices (2-5) with edges to vertex 1 are added and all have the same location. This is evidenced both visually - they overlap - and by looking at the X and Y location co-ordinates which are identical.
At the third pass, 4 further vertices (6-9) are added with edges to vertices 2 and these will all have the same location. The vertices 2-5 will now have discreet locations.
And so on, leaving the last set of vertices added co-located
Here are the location data for a typical example...
ID: 1, X co-ord: 779.6434, Y co-ord: 261.4258
ID: 2, X co-ord: 585.4472, Y co-ord: 229.007
ID: 3, X co-ord: 399.4764, Y co-ord: 305.0099
ID: 4, X co-ord: 369.0031, Y co-ord: 136.486
ID: 5, X co-ord: 788, Y co-ord: 230.753
ID: 6, X co-ord: 282.7024, Y co-ord: 340.5359
ID: 7, X co-ord: 282.7024, Y co-ord: 340.5359
ID: 8, X co-ord: 282.7024, Y co-ord: 340.5359
ID: 9, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 10, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 11, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 12, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 13, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 14, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 15, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 16, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 17, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 18, X co-ord: 148.3842, Y co-ord: 41.90063
ID: 19, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 20, X co-ord: 267.7145, Y co-ord: 149.6625
ID: 21, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 22, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 23, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 24, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 25, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 26, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 27, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 28, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 29, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 30, X co-ord: 12, Y co-ord: 12.9282
ID: 31, X co-ord: 12, Y co-ord: 12.9282
ID: 32, X co-ord: 12, Y co-ord: 12.9282
ID: 33, X co-ord: 12, Y co-ord: 12.9282
ID: 34, X co-ord: 16.57254, Y co-ord: 155.1314
ID: 35, X co-ord: 16.57254, Y co-ord: 155.1314
Sorry this is so wordy; a picture would, as they say, be worth a thousand!
Regards
Tony D


Coordinator
May 9, 2013 at 4:04 PM
Edited May 9, 2013 at 4:06 PM
Tony D:

Thanks for all the details, which are very useful. You've given me the information I'll need to reproduce the problem when I get back to a development computer this weekend.

We don't use the control in this manner in our own application, and no one else has reported doing so, either. I mention that only to explain why such an obvious bug has survived for so long.

In the meantime, I think I know what's going on. The Fruchterman-Reingold layout algorithm requires that vertex locations be initially randomized. NodeXL does this automatically the first time it lays out the graph. It then marks the graph with a "graph has been laid out at least once" metadata key, which it uses to avoid randomizing the vertices again if you lay out the graph again. That way the graph can be laid out iteratively, with the previously laid out locations used as the starting point for the next iteration.

You, however, are adding vertices between iterations, and the locations of those additional vertices never get randomized. The added vertices all have default locations of 0,0, and Fruchterman-Reingold doesn't properly lay out vertices with the same locations. (That's why they have to be randomized.)

So as a temporary workaround--or maybe a permanent one, I'm not sure yet--assign random locations to your new vertices before you add them to the graph. Or as a simpler technique, assign Vertex.ID to the X- and Y-coordinates of each added vertex. IDs are unique, so that should keep the vertices from having the same initial locations.

An alternative workaround is to remove the "graph has been laid out at least once" marker from the graph before you add more vertices. That will cause all vertex locations to be randomized with each iteration. You would do that by calling LayoutMetadataUtil.MarkGraphAsNotLaidOut(nodeXLControl.Graph).

In any case, let me know what happens.

-- Tony C
Coordinator
May 12, 2013 at 6:47 PM
Edited May 12, 2013 at 8:28 PM
I tried what you're doing and my guess about the cause of the problem turns out to be correct.

I'm not sure what the long-term fix for this should be. For now, you can use either of the workarounds I suggested. I tried both and they worked.

-- Tony
May 13, 2013 at 6:39 PM
On 09/05/2013 16:04, tcap479 wrote:

From: tcap479

Tony D:

Thanks for all the details, which are very useful. You've given me the information I'll need to reproduce the problem when I get back to a development computer this weekend.

We don't use the control in this manner in our own application, and no one else has reported doing so, either. I mention that only to explain why such an obvious bug has survived for so long.

In the meantime, I think I know what's going on. The Fruchterman-Reingold layout algorithm requires that vertex locations be initially randomized. NodeXL does this automatically the first time it lays out the graph. It then marks the graph with a "graph has been laid out at least once" metadata key, which it uses to avoid randomizing the vertices again if you lay out the graph again. That way the graph can be laid out iteratively, with the previously laid out locations used as the starting point for the next iteration.

You, however, are adding vertices between iterations, and the locations of those additional vertices never get randomized. The added vertices all have default locations of 0,0, and Fruchterman-Reingold doesn't properly lay out vertices with the same locations. (That's why they have to be randomized.)

So as a temporary workaround--or maybe a permanent one, I'm not sure yet--assign random locations to your new vertices before you add them to the graph. Or as a simpler technique, assign Vertex.ID to the X- and Y-coordinates of each added vertex. IDs are unique, so that should keep the vertices from having the same initial locations.

An alternative workaround is to remove the "graph has been laid out at least once" marker from the graph before you add more vertices. That will cause all vertex locations to be randomized with each iteration. You would do that by calling LayoutMetadataUtil.MarkGraphAsNotLaidOut(nodeXLControl.Graph).

In any case, let me know what happens.

-- Tony

Tony,

Again, many thanks for your swift response. Unfortunately I am on leave at present so will not be able to test your suggested fixes until next week but will try then as soon as I return.

Regards

Tony D

May 13, 2013 at 6:56 PM
On 12/05/2013 18:47, tcap479 wrote:

From: tcap479

I tried what you're doing and my guess about the cause of the problem turns out to be correct.

I'm not sure what the long-term fix for this should be. For now, you can use either of the workarounds I suggested. They worked when I tried them.

-- Tony
Cheers, will do!
May 22, 2013 at 9:40 AM
Tony,

I have updated the code using the workarounds (both of them for luck) and the issues have been fully resolved. Once again thanks for the prompt and detailed responses.

Tony D.
Coordinator
May 22, 2013 at 4:04 PM
And thank you for letting me know the outcome. As I mentioned, I'm not sure of a good long-term fix (everything I've thought of has drawbacks), but now I know what to recommend if other programmers encounter this behavior.

-- Tony