Routing multiple lines from a single node

The application I’m developing uses the CollapsingRecordNode from Demo1. Each CollapsingRecordNode can have multiple links coming from the children nodes:

I'm using GoLinks these properties settings:
Orthogonal = true;
Style = GoStrokeStyle.RoundedLine;
FromArrowShaftLength = 15;
ToArrowShaftLength = 15;
AvoidsNodes = true;
Selectable = true;
Movable = true;
Relinkable = true
As you can see from the picture, the links all overlap so its difficult to see where each one goes. I'd like it to look more like this:
Is there a way to make that happen automatically, or do I have to sub-class GoLink or LayoutTree?

GoGeneralNode, GoMultiTextNode, and GoBoxNode (actually GoBoxPort) all do that automatically. However, CollapsingRecordNode doesn’t implement that. (That sample would be even more complicated than it already is.)

You can get a similar effect by setting the GoPort.EndSegmentLength property on each of the ports to have different values. In the case that you show, perhaps the GoPort for "ca" would be 50, for "FL" 40, for "NE" 30, etc.
But if the user moved the node "down", those values might not be optimal for where all those links come from.

That’s pretty much what I’ve come up with. I’m having some problem getting a handle of the Points in GoStroke. Is there a resource that explains all about that?

I'm actually sub-classing CollapsingRecordNode, so I may need to override some method to automatically handle the arrangement of the node's links. What method would that be?
Ideally, I'd like some way to factor the GoLinks into the rectangle of the node so that the neighboring node doesn't get positioned too closely. Some of my nodes have a dozen or more links, and I don't want to have to set the NodeSpacing to some huge value and affect everything. Is there a way to do that?

GoStroke.GetPoint is the method you can call to get the points of a stroke. GoStroke.PointsCount is the number of points in the stroke.

Well, the natural answer is to override OnBoundsChanged and LayoutChildren, calling the base method first and then updating the ports as you see fit. The former, particularly when the Size does not change, will handle the changes that might be desired because the node has moved. The latter will handle the changes that happen because of collapsing/expanding items.
So you are using one of the GoLayouts? One possibility might be to have the GoLayout...Node pretend to have a larger size than it actually does, before you call PerformLayout.


How could I specify the height of the link that plays the part of the "stem" of an Orthoganal link collection?
Meaning, is there a way to set the height at the point where several links all converge together and appear to look like one as they join the parent?

Yes, that’s what the “EndSegmentLength” specifies. The GoPort.GetFromEndSegmentLength method and the GoPort.GetToEndSegmentLength method, by default, return the value of GoPort.EndSegmentLength. But those methods are smarter when the port is a GoBoxPort or when the port is part of a GoGeneralNode or a GoMultiTextNode.
So you can just set the GoPort.EndSegmentLength property.


In addition ...
Is there also a GoNode property that will allow the user to programatically detect whether a node's physical location/position was changed?
I know there is an "onObjectSelected" event handler but what I am trying to do is reposition the location of nodes when GoDocument.IsUnOccupied returns false after a node's location changes either programatically or by user interaction. After it returns false I would like to use PickObject to get the node located at the location that the current node is trying to occupy and then reposition it and so on and so forth until no nodes are overlapping.
UPDATE: I think I may have found a possible solution here:
If there is a more direct way to try and perform what I described above please let me know.
Thanks again!


So you are using one of the GoLayouts? One possibility might be to have the GoLayout...Node pretend to have a larger size than it actually does, before you call PerformLayout.
Yes, I'm using the GoTreeLayout. That sounds like a good suggestion, but how do I do that?
Do you override the Get Bounds property and return a RectangleF that accounts for the routing of all the GoLinks that come in and out of the node?
I also think this will help links AvoidNodes with a sufficient margin to not overlap the lines coming from a node the GoLink is avoiding.

For each GoNode in your diagram, there is an equivalent GoLayoutTreeNode that is part of the GoLayoutTreeNetwork. Rather than modifying the actual nodes in your diagram, you can just iterate over the GoLayoutTreeNetwork and modify the Bounds property of each GoLayoutTreeNode. The GoLayoutTreeNode has a GoObject property that will allow you to find the specific GoNode that it corresponds to so you can set the Bounds appropriately.

Thanks for that suggestion. I gave it a try, but didn’t quite get the results I was hoping for.

I have to wait until after the GoTreeLayout PerformLayout() has completed to set the bounds of the GoTreeLayoutNodes because the arrangement of the GoLinks and the EndSegmentLengths is dependant on how the nodes are positioned relative to one another.
But if I set the bounds after PerformLayout(), I have to call PerformLayout() again for the new bounds to take affect. Is there are better way than this? Should I be sub-classing the GoTreeLayout class and overriding some specific methods.
One of the problems I was hoping this would solve is where a GoLink goes around a node, but turns back toward the node too closely after the node. I was hoping making the GoTreeLayoutNode's bounds wider would prevent this, but it doesn't seem to do so. Any suggestions for that?

Normally one would adjust the GoLayoutTreeNode.Bounds after constructing the GoLayoutTreeNetwork that is used by the GoLayoutTree before calling PerformLayout().

But I can imagine what you mean, thus needing to update the Bounds after the layout, and then doing a new layout using the old GoLayoutTreeNetwork. I think that's necessary.
I don't know about the details for your situation, but it sounds like you are on the right track regarding making the GoLayoutTreeNode's Bounds wider.