GoLayoutLayeredDigraph problem

Hello. I have a few issues with layout that I can’t seem to even begin to work out how to solve. Perhaps somebody could give me a few pointers.



Imagine the following tree and node types:



A-B-C

\

D-E-E-E

\

F

/

G



Firstly, i need to place the children of a parent in a certain order, i.e. one type of node always to the right, the other always to the left. E.g. Nodes of type D must always be above G when coming from F





Secondly, I need to ensure some sequences of nodes (a line of nodes all with one child) are always placed on the same line, effectively treated as a whole. E.g. A-B-C need to be in a straight line, as does E-E-E. These are normally messed up completely.



Thirdly, I need to ensure that all instances of “A” are placed in a column to the left of the diagram. Note this is different from longest path sink layering.

Please help!

Hmmm. I’m afraid I don’t understand what your first two requirements are; I can think of problematic cases for each. In any case I can understand why you can’t see a way to do it using the layered-digraph autolayout–the goals of layered-digraph are fairly different from what I think you want.
If you really do have a tree, it might be easiest to just do the layout yourself. That way you can be sure you encode the particular requirements your application has. There are a couple of tree drawing algorithms provided in the samples. If you want to use one of them, the one that is used by Classier is probably the easiest. However, doing a tree layout is fairly straight forward, so you probably don’t need any examples.

ok, i’ll endeavour to explain more simply. The fact is that the LD layout is far more optimal than we have time to invest to recreate. It’s NEARLY exactly what we need. It’s not a simple tree.



The first point is very straightforward. Nodes need to be thus:



A



B

/

C





NOT thus:



C



B

/

A





(where A,B and C are different TYPES of nodes)



Secondly, this relatively simple tree has offshoots from the Top port of certain nodes, think of them as call outs. These are generally a series of nodes like E, F and G, calling out from D here:



G-F-E

|

C-D



B

/

A





G-F-E should be lined up, not packed into spaced left over. If they were treated as one composite node during layout, i think it would work.



Also I think we’d get somewhere if a layout decision was made on which port the child connects to. This is an example of an incorrect layout which clearly does not consider the port:



C



G-F-E-D <- note here that C is on D’s Left port

\ and E is on D’s Top port!

B

/

A





Other approaches I’m considering involve laying out the skeleton of the tree (i.e. minus the callouts) first, then laying out the callouts afterwards. How feasible is this, and how would we approach it?

A simple tree layout is relatively straightforward, but that leaves a lot of wasted space that the LD layout algorithm reduces greatly.

The re-ordering of nodes is due to the algorithm’s trying to reduce the number of logical link crossings. You can disable that by overriding ReduceCrossings() to be a no-op.
Then you just need to make sure that for all the “children” of a node are ordered in the way you want. You can do that by overriding InitializeIndices (but note that the ordering applies to the whole layer).
Or, for a more implementation-dependent approach, you can make sure that the GoLayoutNetworkLinks for a node are added in the order you want. One way of doing that in the GoDocument is to connect up the GoLinks from each node in that order. If you can’t really modify the document, the other way to do the same thing is to construct the GoLayoutNetwork for the GoLayoutLayeredDigraph: create the GoLayoutNetworkNodes and then add the GoLayoutNetworkLinks in the right order.
For those sequences of G-F-E nodes, it might be easiest to represent them with a single GoLayoutNetworkNode in your GoLayoutNetwork. In general you won’t be able to do a simple layout and then fill in things, because there’s no way to reserve space without making sure a large GoLayoutNetworkNode is present in the network.
As far as having all those A nodes appear on the far left side, I suggest you just perform the layout, and then move all the A nodes.

I’ve tried in vain to solve this the way you describe.



Firstly, I go through the whole diagram, disconnecting and reconnecting all links in the desired order. I’ve confirmed they’re all in the correct order in the GoNode.LeftPort.Links collection.



I try the layout, but still nodes are being ordered incorrectly.



I then override GoLayoutLayeredDigraph to disable ReduceCrossings():



public class TBLayout:GoLayoutLayeredDigraph

{

public TBLayout()

{

//

// TODO: Add constructor logic here

//

}

protected override void ReduceCrossings()

{

// base.ReduceCrossings ();

}



}



I call Layout on a collection (coll) of Nodes:



TBLayout layout = this.goLayoutLayeredDigraph1;

layout.Document = this.goView.Document;

layout.Network = new GoLayoutNetwork();

layout.Network.ddNodesAndLinksFromCollection(coll, false);

layout.PerformLayout();



And still the result is some nodes go up when they should go down, and vice versa.



Please help, this is a very important requirement for us.



Kind regards,



Ben Bourner

Perhaps there’s some issue with the way I’m disconnecting and reconnecting the links? Here’s my code:



/// Copy all the links

IGoLink[] all = parent.LeftPort.CopyLinksArray();



// Disconnect them

foreach(IGoLink l in all)

{

Trace.WriteLine("0. Disconnecting " + l.FromNode.ToString());

l.ToPort=null;

}



// Add hazards(s) then target(s) then everything else



foreach(IGoLink l in all)

{

Node n = l.FromNode.UserObject as Node;

if(n!=null)

{

if(n.isHazard())

{

l.ToPort=parent.LeftPort;

Trace.WriteLine("1. Reconnected " + n.TraceName);

}

}

}



foreach(IGoLink l in all)

{

Node n = l.FromNode.UserObject as Node;

if(n!=null)

{

if(n.isTarget())

{

l.ToPort=parent.LeftPort;

Trace.WriteLine("2. Reconnected " + n.TraceName);

}

}

}



foreach(IGoLink l in all)

{

if(l.ToPort==null)

{

l.ToPort=parent.LeftPort;

Trace.WriteLine("3. Reconnected " + l.FromNode.ToString());

}



}



// Verfiy them

foreach(IGoLink l in parent.LeftPort.Links)

{

Trace.WriteLine("4. New ordered " + l.FromNode.ToString());

}

Can I expect any answer??

I suppose you can expect an answer, but since this isn’t a support channel, I only answer when I get a chance. Quick answers of course come right away.
Alas, this isn’t an easy one, so it will have to wait until I have more time to investigate.

OK thanks, just some word of acknowledgment puts my mind at ease a little.

[QUOTE=walter]

I suppose you can expect an answer, but since this isn’t a support channel, I only answer when I get a chance. Quick answers of course come right away.



Alas, this isn’t an easy one, so it will have to wait until I have more time to investigate.

[/quote]



Perhaps then you could tell me where I would find the support channel that we have paid for? It´s rather unclear to me.

That was in the mail that we sent you when you purchased.
I’m just guessing, but do you know a Ben B.? We have corresponded with him before, and “tritanium” is a sufficiently unique name…

Strange, we never received this information. We’ve now sent a formal request to your company for this information.