Page Index Toggle Pages: 1 Send TopicPrint
Hot Topic (More than 10 Replies) Flowchart diagram with diagonal links (instead of horizontal & vertical) (Read 9650 times)
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Flowchart diagram with diagonal links (instead of horizontal & vertical)
Jun 11th, 2012 at 9:11pm
Print Post  
Flowchart Layout algorithm renders our diagrams quite nicely. But there are certain cases where we hope it could be improved. We are looking forward to your suggestions and help in solving these items:

  1. By default, the Flowchart Layout renders with horizontal/vertical orientation of the links. I have noticed that if I apply the FlowLayout on top of the FlowchartLayout like this:

    FlowLayout flow2 = new FlowLayout();
    flow2.AutoRoute = true;
    flow2.LinksBend = false;


    it will make the links diagonal (see 1st screenshot). Is there any way to achieve diagonal orientation of the links directly with the FlowchartLayout?
  2. In the 1st screenshot, you will notice that one of the links comes out from the side of my node. Is there any way we can force the links to always come out from the bottom of the node (just like the other 3 links in the screenshot)?
  3. In the 2nd screenshot, notice that the node at the bottom is a parent node that has 4 links going upwards to 4 nodes that are its siblings - we would certainly expect that siblings would always be rendered beneath the parent (i.e. the node at the bottom would actually be above the 4 nodes it is pointing to). Is this something that can be addressed? This is quite important to our workflow.

By the way, I was able to solve points 1 and 3 above by applying the TreeLayout (see 3rd screenshot), but then too many links started crossing over the nodes. If there's any way around this, then we would be happy to use the TreeLayout instead of Flowchart (+ we still hope that #2 can be solved).

Thank you for all your help and support!



Some useful details:
  • I'm currently running an unofficial release of the NetDiagram package (MindFusion.Diagramming.dll 5.8.0.34649) that you built for me that exposes ClientSideMode support for "SvgImage". The diagram below is rendered in "SvgImage" client-side mode.
  • All the nodes in my diagrams are TableNode's.
« Last Edit: Jun 12th, 2012 at 2:13pm by LGK »  

Flowchart_with_diagonal_links.png (Attachment deleted)
Flowchart_with_diagonal_links_2.png (Attachment deleted)
Tree_with_crossing_links.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #1 - Jun 12th, 2012 at 8:24am
Print Post  
I think you will get layouts like this with the default LayeredLayout settings. You could also experiment with these LayeredLayout properties:

- StraightenLongLinks: ensures that there are no more than two bends per link, and tries to set as much vertical links as possible
- EnforceLinkFlow: assigns nodes to layers in such a way that all links flow in the same direction (possible only if the graph is acyclic).
- StartNode and EndNode: if you need specific nodes to be placed on the first/last layer

If you prefer to have single-segment diagonal links after FlowchartLayout or LayeredLayout, you can loop over all links and reset their SegmentCount to 1 after applying the layout:

Code
Select All
layout.Arrange(diagram);

foreach (DiagramLink link in diagram.Links)
{
    link.AutoRoute = false;
    link.SegmentCount = 1;
} 



You can further ensure that links connect to the top or bottom sides of node either by using anchor points, or by manually setting ControlPoints[0] and ControlPoints[count - 1] positions. E.g. in the same loop check if (point0.X == srcRect.Left || point0.X == srcRect.Right), and move the control point somewhere along the source node's bottom border; also add a symmetric case for the last point and the link's destination.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #2 - Jun 12th, 2012 at 8:07pm
Print Post  
Thank you for your recommendations, Stoyan - we're making good progress!


Regarding your last point:

Quote:
You can further ensure that links connect to the top or bottom sides of node either by using anchor points, or by manually setting ControlPoints[0] and ControlPoints[count - 1] positions. E.g. in the same loop check if (point0.X == srcRect.Left || point0.X == srcRect.Right), and move the control point somewhere along the source node's bottom border; also add a symmetric case for the last point and the link's destination.


I gave the following a try:


    if (link.ControlPoints[0].X == link.Origin.Bounds.Left || link.ControlPoints[0].X == link.Origin.Bounds.Right)
    {
        link.ControlPoints[0].X = (link.Origin.Bounds.Right - link.Origin.Bounds.Left) / 2;
    }


But I get:


    Cannot modify the return value of 'MindFusion.Diagramming.PointCollection.this[int]' because it is not a variable


Is this along the lines of what you were suggesting?

In the meantime, I will give anchor points a try!

Thank you!
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #3 - Jun 13th, 2012 at 6:49am
Print Post  
Hi,

The compiler just prevents against losing the assigned X value silently; since Point is a value type, the indexer returns a temporary stack value whose X member change would be lost if you don't assign the point back. Whereas if Point was a reference type, setting X on the returned reference would change the original object. So replace this line:

Code
Select All
link.ControlPoints[0].X = (link.Origin.Bounds.Right - link.Origin.Bounds.Left) / 2; 



with

Code
Select All
PointF point = link.ControlPoints[0];
point.X = (link.Origin.Bounds.Right - link.Origin.Bounds.Left) / 2;
link.ControlPoints[0] = point; 



and this should compile successfully. However I think you should set X = (Right + Left) / 2 if you want to center it, instead of (Right - Left) / 2, and also set point.Y = Bottom to align the link to the node's bottom border.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #4 - Jun 13th, 2012 at 7:43pm
Print Post  
Fantastic - thanks!
  
Back to top
 
IP Logged
 
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #5 - Jun 18th, 2012 at 8:33pm
Print Post  
As a result of your insightful suggestions, we have built a gorgeous Layered graph (see screenshot).

One question that has come up multiple times is:

Is there any way to prevent all links on the graph from intercepting with any of the nodes?

In the attached screenshot, there's one link that falls behind a node. I have actually noticed that it's unpredictable when a link may be drawn on top of a node or fall behind it, so in order to deal with that, I have explicitly set the ZIndex of all nodes and links so that links always end up under the nodes...But it would be better if they never intercepted.

I look forward to your helpful recommendations! And thank you for your time & help!
  

Layered_Layout_-_link_intercept_with_node.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #6 - Jun 19th, 2012 at 6:59am
Print Post  
Usually links won't intersect with nodes after LayeredLayout, but bend around them. Since you are re-setting links to straight lines, you will also have to take care of any intersections this creates. You can use the DiagramLink.Intersects() method to find if a link intersects any nodes, and then decide what to do.

One option I can think of is to save the link's ControlPoints and restore them back if you detect intersections after setting SegmentCount to 1. So in the end the graph will contain a minimum number of links with more than one segment.

Another option is to shift the intersected nodes to the left or right of the link, along with any other nodes on the layer - you can use LayeredLayout.Statistics to find all nodes on the same layer as the intersected one. However, shifting the nodes might create new intersections on adjacent layers, so you might have to do several sweeps across layers to remove all intersections.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #7 - Jun 19th, 2012 at 7:17pm
Print Post  
These are really great options - thanks!

So, what I did first was I took out all of the customization code that I wrote on top of the default LayeredLayout because I wanted to confirm that links won't intersect with any nodes based on what you said:

Quote:
Usually links won't intersect with nodes after LayeredLayout, but bend around them.


But I found that to be untrue - screenshot attached.

This is the current definition of the LayeredLayout without any extra customizations (such as setting SegmentCount to 1 or moving any of the control points to a new position):

Code
Select All
LayeredLayout ll = new LayeredLayout();
ll.Orientation = MindFusion.Diagramming.Layout.Orientation.Vertical;
ll.Anchoring = Anchoring.Reassign;
ll.Direction = Direction.Straight;
ll.LinkType = LayeredLayoutLinkType.Straight;
ll.SplitLayers = true;
ll.NodeDistance = 50f;
ll.LayerDistance = 25f;
ll.Arrange(PFVDiagram.Diagram);
 



Would any of the above settings be the reason why links are still crossing nodes?

Thank you!
  

Layered_Layout_-_links_intercept_with_nodes.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #8 - Jun 20th, 2012 at 10:24am
Print Post  
You will have to set larger LayerDistance to avoid these. Since links point to node centers by default, a larger LayerDistance will make the link's incline angle larger and avoid cutting the corners of adjacent nodes. However this will also require more space for the overall layout, so it's a tradeoff between how much of the diagram you will see on a single screen and avoiding the cut corners.

You shouldn’t be seeing much of these anyway when aligning link end points to top/bottom sides of nodes - then they could happen only with links that cross more than one layer, and LayeredLayout minimizes the number of such links.

Stoyan
  
Back to top
 
IP Logged
 
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #9 - Jun 20th, 2012 at 3:00pm
Print Post  
So, it sounds like the Layered layout doesn't have a predictable behavior when we're talking about links crossing nodes. Even if I increased the LayerDistance for this particular graph, there still may be a case where this distance may not be sufficient and result in links nabbing the edge(s) of a node. By default, the algorithm has built-in logic to avoid crossing with other edges, but not with nodes unfortunately for my use case (from documentation):

Quote:
The LayeredLayout algorithm arranges diagram nodes in layers according to several criteria, most important of which are: ... links must not cross other links.


I will often have graphs containing links that cross multiple layers (as shown in my screenshots above), and it sounds like the only reliable way to avoid interception with other nodes is to write custom logic that analyzes each of the links and readjusts the nodes on each layer...which I would expect to have an impact on performance in some situations.


  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #10 - Jun 21st, 2012 at 8:11am
Print Post  
Just move the link end points to the top/bottom of nodes; that will remove most of cut corners.
  

layered.png (Attachment deleted)
Back to top
 
IP Logged
 
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #11 - Jun 21st, 2012 at 3:59pm
Print Post  
Wow! How are you achieving that? Would you mind posting some code OR reviewing mine below please?

In my graph, I haven't been able to generate that layout whatever I do (see screenshot). The link on left keeps nabbing (even barely) the leftmost node...

Here is my code that sets up the LayeredLayout:

Code (C++)
Select All
LayeredLayout l4 = new LayeredLayout();
l4.Orientation = MindFusion.Diagramming.Layout.Orientation.Vertical;
l4.Anchoring = Anchoring.Reassign;
l4.Direction = Direction.Straight;
l4.LinkType = LayeredLayoutLinkType.Straight;
l4.SplitLayers = true;
l4.NodeDistance = 50f;
l4.LayerDistance = 35f;
l4.Arrange(PFVDiagram.Diagram);

foreach (DiagramLink link in PFVDiagram.Diagram.Links)
{
    System.Drawing.PointF startPoint = link.ControlPoints[0];
    startPoint.Y = link.Origin.Bounds.Bottom + 0.5f;
    // center link's exit point on bottom of node
    startPoint.X = (link.Origin.Bounds.Left + link.Origin.Bounds.Right) / 2;
    link.ControlPoints[0] = startPoint;

    System.Drawing.PointF endPoint = link.ControlPoints[link.ControlPoints.Count - 1];
    endPoint.Y = link.Destination.Bounds.Top - 0.5f;
    // center link's entry point on top of node
    endPoint.X = (link.Destination.Bounds.Left + link.Destination.Bounds.Right) / 2;
    link.ControlPoints[link.ControlPoints.Count - 1] = endPoint;

    // it doesn't seem to make any difference if I call this method or not
    link.UpdateFromPoints();
}
 

« Last Edit: Jun 21st, 2012 at 6:19pm by LGK »  

Layered_Layout_-_link_intercept_with_node_2.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #12 - Jun 21st, 2012 at 6:24pm
Print Post  
I've used the same layout settings, but the nodes I've drawn to copy yours might be slightly smaller, and they have the default ShapeNode's rounded-rect shape so the corner is further from the link's path (you can round tables corners too by setting TableNode.Style).

In any case, this layout is as nice at it can get without worsening other layout aesthetics. If you absolutely must have the links away from the node corners, you will have to either set larger layer distance and fit less nodes on a page, or you will have to add extra link bends - e.g. by duplicating each internal control point, and then moving the paired points to Y positions corresponding to the top / bottom sides of the other nodes on the layer.
  
Back to top
 
IP Logged
 
LGK
YaBB Newbies
*
Offline



Posts: 30
Location: Boston, MA
Joined: Mar 29th, 2012
Re: Flowchart diagram with diagonal links (instead of horizontal & vertical)
Reply #13 - Jun 22nd, 2012 at 7:55pm
Print Post  
Thank you for your feedback - I really appreciate it!
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint