Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic How to avoid overlapping links (Read 5291 times)
jlj30
Full Member
***
Offline


I love YaBB 1G - SP1!

Posts: 183
Joined: Sep 4th, 2011
How to avoid overlapping links
Dec 23rd, 2013 at 8:04pm
Print Post  
Hi,

Please have a look at the attached screenshot.
I had previously been assigning anchor points to the links coming into the left side of my task shapes (rounded rectangles).
My algorithm was lacking, so I decided to make NO anchor assignments to these links and hope that the automatic routing would do what I wanted.

For other shapes, like the decision box, I AM assigning anchor points. So, I want to keep those anchor points that I am assigning, but let the GridRouter do its thing for the rest.

My current "costs" are as follows.  My prior values (which had the same results) are in brackets:

CrossingCost = 25 (50)
LengthCost = 5 (10)
NodeVicinityCost = 0 (5)
TurnCost = 20 (10)

Any suggestions?

My thanks in advance.

Jim


  

Task_Incoming_Links_-_Overlapping_Issue_-_23Dec2013.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: How to avoid overlapping links
Reply #1 - Dec 27th, 2013 at 12:05am
Print Post  
Hi,

The router cannot distribute links along one side of a node as in your image, so you'll still have to use a custom funtion to assign links' end points. E.g. try sorting the links by the angular positions of origin nodes around the target node, that seems to work fine in my test:



Code
Select All
var center = e.Node.GetCenter();
foreach (var inlink in e.Node.IncomingLinks)
{
	// display angles
	var org = inlink.Origin.GetCenter();
	float angle = 0, radius = 0;
	MindFusion.Geometry.Geometry2D.Convert.CartesianToPolar(
		center, org, ref angle, ref radius);
	if (angle < 0)
		angle += 360;
	(inlink.Origin as InplaceEditable).SetEditedText(angle.ToString());
}

// sort incoming links by polar positions (angles) of link origin
// nodes around the clicked node
var links = e.Node.GetAllIncomingLinks();
links.Sort((l1, l2) =>
{
	var o1 = l1.Origin;
	var o2 = l2.Origin;
	var c1 = o1.GetCenter();
	var c2 = o2.GetCenter();
	float a1 = 0, a2 = 0, r = 0;
	MindFusion.Geometry.Geometry2D.Convert.CartesianToPolar(
		center, c1, ref a1, ref r);
	MindFusion.Geometry.Geometry2D.Convert.CartesianToPolar(
		center, c2, ref a2, ref r);
	if (a1 < 0)
		a1 += 360;
	if (a2 < 0)
		a2 += 360;
	return a1.CompareTo(a2);
});

// distribute the sorted links along the node's left side
var dy = e.Node.Bounds.Height / (links.Count + 1);
var y = e.Node.Bounds.Top + dy;
foreach (var link in links)
{
	link.EndPoint = new PointF(e.Node.Bounds.Left, y);
	link.UpdateFromPoints();
	y += dy;
	link.HeadShapeSize = 1;
	link.HeadShape = ArrowHeads.Triangle;
}

// route the links
diagram.LinkRouter = new GridRouter();
if (diagram.RoutingOptions.GridSize > dy / 2)
	diagram.RoutingOptions.GridSize = dy / 2;
diagram.RouteAllLinks(); 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
jlj30
Full Member
***
Offline


I love YaBB 1G - SP1!

Posts: 183
Joined: Sep 4th, 2011
Re: How to avoid overlapping links
Reply #2 - Dec 27th, 2013 at 5:23pm
Print Post  
Hi,

This looks great, but I just have one question.
Where should this code be placed?
It appears to be within an event handler (based on your use of the "e").
Please advise.

Thanks for this.

Jim
  
Back to top
 
IP Logged
 
jlj30
Full Member
***
Offline


I love YaBB 1G - SP1!

Posts: 183
Joined: Sep 4th, 2011
Re: How to avoid overlapping links
Reply #3 - Dec 28th, 2013 at 8:35pm
Print Post  
Me again,

OK, so I believe the code should be placed in the NodeDraw event.
I've attempted to do this, but am getting compile errors.

Here's my code:

Code
Select All
protected void OnDrawNode(object sender, DrawNodeEventArgs e)
	{
        PointF center = e.Node.GetCenter();
        // sort incoming links by polar positions (angles) of link origin
        // nodes around the clicked node
        var links = e.Node.GetAllIncomingLinks();

        links.Sort((l1, l2) =>  // Get a compile error here - doesn't understand "Sort"
        {
            var o1 = l1.Origin;
            var o2 = l2.Origin;
            var c1 = o1.GetCenter();
            var c2 = o2.GetCenter();
            float a1 = 0, a2 = 0, r = 0;
            MindFusion.Geometry.Geometry2D.Convert.CartesianToPolar(
                center, c1, ref a1, ref r);
            MindFusion.Geometry.Geometry2D.Convert.CartesianToPolar(
                center, c2, ref a2, ref r);
            if (a1 < 0)
                a1 += 360;
            if (a2 < 0)
                a2 += 360;
            return a1.CompareTo(a2);
        });

        // distribute the sorted links along the node's left side
        float dy = e.Node.Bounds.Height / (links.Count + 1);
        float y = e.Node.Bounds.Top + dy;
        foreach (DiagramLink link in links)
        {
            link.EndPoint = new PointF(e.Node.Bounds.Left, y);  // Get a complile error here as well - doesn't understand "EndPoint"
            link.UpdateFromPoints();
            y += dy;
            link.HeadShapeSize = 1;
            link.HeadShape = ArrowHeads.Triangle;
        }
	} 



The 2 lines that are flagged in error are the links.Sort and link.EndPoint.

I'm not accustomed to using "var" in my C# code behind.  I prefer typing.  Is the lack of typing perhaps the issue here?

Please advise.

I'm really looking forward to getting this working, so many thanks for helping me through this.

Jim
  
Back to top
 
IP Logged
 
jlj30
Full Member
***
Offline


I love YaBB 1G - SP1!

Posts: 183
Joined: Sep 4th, 2011
Re: How to avoid overlapping links
Reply #4 - Dec 29th, 2013 at 9:41pm
Print Post  
Hi,

I've made some progress and seem to have it working.
Here's my code at this point:

Code
Select All
    protected void SortRoutedLinksTaskLeft(Diagram diagram)
	{
        foreach (ShapeNode node in diagram.Nodes)
        {
            // Only care about task shapes
            if (node.Shape != Shapes.RoundRect)
                continue; // stops processing here, and gets the next node in the collection

            // sort incoming links by polar positions (angles) of link origin
            // nodes around the clicked node
            PointF center = node.GetCenter();
            List<DiagramLink> links = LeftInLinks(node);
            if (links.Count > 1)
            {
                links.Sort((l1, l2) =>
                {
                    DiagramNode o1 = l1.Origin;
                    DiagramNode o2 = l2.Origin;
                    PointF c1 = o1.GetCenter();
                    PointF c2 = o2.GetCenter();
                    float a1 = 0, a2 = 0, r = 0;
                    MindFusion.Geometry.Geometry2D.Convert.CartesianToPolar(
                        center, c1, ref a1, ref r);
                    MindFusion.Geometry.Geometry2D.Convert.CartesianToPolar(
                        center, c2, ref a2, ref r);
                    if (a1 < 0)
                        a1 += 360;
                    if (a2 < 0)
                        a2 += 360;
                    return a1.CompareTo(a2);
                });

                // distribute the sorted links along the node's left side
                float dy = node.Bounds.Height / (links.Count + 1);
                float y = node.Bounds.Top + dy;
                foreach (DiagramLink link in links)
                {
                    Int32 EndPoint = link.ControlPoints.Count - 1;
                    link.ControlPoints[EndPoint] = new PointF(node.Bounds.Left, y);
                    link.UpdateFromPoints();
                    y += dy;
                }
            }
        }
	}

	protected List<DiagramLink> LeftInLinks(DiagramNode node)
	{
		List<DiagramLink> links = new List<DiagramLink>();
		foreach (DiagramLink link in node.IncomingLinks)
		{
			if (link.DestinationAnchor < 5)
				links.Add(link);
		}
		return links;
	}
 



Rather than placing this code in the DrawNode event handler, I call this method after I've created all the shapes and the links between them.

After calling the above code, I then perform the diagram.RouteAllLinks().

I now need to apply this same logic to links exiting the right and bottom of my task shapes.

I think I'm good for now. 

Many thanks for the code - I would have never thought of taking this approach.

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: How to avoid overlapping links
Reply #5 - Dec 30th, 2013 at 7:11am
Print Post  
Hi,

I was calling this from NodeClicked handler in my test project.

Quote:
The 2 lines that are flagged in error are the links.Sort and link.EndPoint.


LinkCollection.Sort and links' StartPoint/EndPoint properties were added with the version 5 release. You guys are on active maintenance and can find new versions at http://clientsarea.eu/, please upgrade already Smiley

Quote:
I now need to apply this same logic to links exiting the right and bottom of my task shapes.


That should look similar, only sorting on the right side should be done in opposite direction I think: return a2.CompareTo(a1); Also you will be comparing Destination node positions if right side is for outgoing links.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
jlj30
Full Member
***
Offline


I love YaBB 1G - SP1!

Posts: 183
Joined: Sep 4th, 2011
Re: How to avoid overlapping links
Reply #6 - Dec 30th, 2013 at 2:06pm
Print Post  
Hi,

I just looked at the releases that were available to me for download and the latest was 4.2.  I then noticed that I had not added my latest Order Number, so I just did that.  Apparently the administrator now needs to do something in order for me to see the truly latest release downloads.

Thanks for all of your help.
Using the "angle" approach has made our diagrams look much better.

Jim
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint