Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Overlapping Links (Read 5477 times)
JRobere
YaBB Newbies
*
Offline


Watch This!

Posts: 8
Joined: May 19th, 2009
Overlapping Links
Nov 8th, 2009 at 1:01am
Print Post  
Hi,

Let's say we have a diagram with 2 Nodes. There are 3 Links going from the first to the second.

There are also 2 Links that have have the first Node as both the Origin and the Destination.

I'm typcially using Annealed layout with high Link and Node Crossing penalties.

Even so, the 3 Links overlapped until I added your code that makes the Links Bezier and adds Control Points to push them apart. All 3 Links start and end on the same Anchor points even though there are others open.

The 2 Links that have the same Origin and Destination degenerated into a single Anchor point and were unselectable. So I created an Anchor Pattern with 10 points that alternate Incoming Only and Outgoing Only. So Now they are visible but they still overlap each other.

If I use the same code as before then one of them goes inside the Node and becomes unselectabe.

I could modify your Control Point code for these but all of this seems to be because these Links all want to go to the same Anchors.

1) Since I've got 10 Anchors why doesn't Routing use them?

None of this extra code would be necessary if I could say that a Node's Anchors are to be as sparsely populated as possible during Routing right?

2) Can I do that? Or do I have to write more code to push the self-referencing Links away from each other but not inside the Node?

3) How do I tell a Link to use a different Anchor?

Thanks,

JR
  

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Overlapping Links
Reply #1 - Nov 9th, 2009 at 9:55am
Print Post  
Hi,

OrthogonalRouter has some code that distributes multiple links between a pair of nodes - you might try running it after AnnealLayout and resetting the links to polyline / bezier depending on whether they are self-loops:

Code
Select All
var router = new OrthogonalRouter();
router.Arrange(diagram);

foreach (DiagramLink link in diagram.Links)
{
	var pt1 = link.ControlPoints[0];
	var pt2 = link.ControlPoints[link.ControlPoints.Count - 1];
	if (link.Origin != link.Destination)
	{
		link.Style = LinkStyle.Polyline;
		link.ControlPoints = new List<Point> { pt1, pt2 };
		link.UpdateFromPoints();
	}
	else
	{
		link.Style = LinkStyle.Bezier;
		link.ControlPoints = new List<Point>
		{
			pt1,
			new Point(pt1.X - 10, pt1.Y - 30),
			new Point(pt1.X + 10, pt1.Y - 30),
			pt1
		};
		link.UpdateFromPoints();
	}
}
 



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


Watch This!

Posts: 8
Joined: May 19th, 2009
Re: Overlapping Links
Reply #2 - Nov 9th, 2009 at 1:24pm
Print Post  
Hi Stoyo,

Thanks for your reply. I've slightly modified your code that I found here in another post as shown below:

Code
Select All
private void UntangleLink(DiagramLink NewLink)
{
    try
    {
        if (NewLink.Origin == NewLink.Destination)
        {
            //it's self referential
            NewLink.Style = LinkStyle.Polyline;
            NewLink.Route();
            return;
        }
        //get all common links between start and end state
        DiagramLinkCollection commonLinks = GetCommonLinks(NewLink.Origin, NewLink.Destination);
        if (commonLinks.Count > 1)
        {
            //get the start and end point of the calling link
            Point pt1 = NewLink.ControlPoints[0];
            Point pt2 = NewLink.ControlPoints[NewLink.ControlPoints.Count - 1];
            //loop thru all the common links
            for (int c = 0; c < commonLinks.Count; ++c)
            {
                DiagramLink link = commonLinks[c];
                link.Style = LinkStyle.Bezier;
                //reset to one segment
                link.SegmentCount = 1;
                //get new control points
                Point cp1 = new Point(pt1.X + 1 * (pt2.X - pt1.X) / 3, pt1.Y + 1 * (pt2.Y - pt1.Y) / 3);
                Point cp2 = new Point(pt1.X + 2 * (pt2.X - pt1.X) / 3, pt1.Y + 2 * (pt2.Y - pt1.Y) / 3);
                float angle = 0, radius = 0;
                CartesianToPolar(pt1, pt2, ref angle, ref radius);
                int pairOffset = (c / 2 + 1) * 10;
                //if (commonLinks.Count % 2 == 0)
                //{
                PolarToCartesian(cp1, c % 2 == 0 ? angle - 90 : angle + 90, pairOffset, ref cp1);
                PolarToCartesian(cp2, c % 2 == 0 ? angle - 90 : angle + 90, pairOffset, ref cp2);
                if (link.ControlPoints[0] == pt1)
                {
                    link.ControlPoints[1] = cp1;
                    link.ControlPoints[2] = cp2;
                }
                else
                {
                    link.ControlPoints[1] = cp2;
                    link.ControlPoints[2] = cp1;
                }
                link.UpdateFromPoints();
                //}
            }
        }
    }
    catch (Exception exc)
    {
        AUISL.Utilities.LogException(exc);
    }
}

DiagramLinkCollection GetCommonLinks(DiagramNode node1, DiagramNode node2)
{
    DiagramLinkCollection commonLinks = new DiagramLinkCollection();
    foreach (DiagramLink link in node1.OutgoingLinks)
    if (link.Destination == node2)
        commonLinks.Add(link);
    foreach (DiagramLink link in node1.IncomingLinks)
        if (link.Origin == node2)
            commonLinks.Add(link);
    return commonLinks;
}

void PolarToCartesian(Point coordCenter, float a, float r, ref Point cartesian)
{
    if (r == 0)
    {
        cartesian = coordCenter;
        return;
    }
    cartesian.X = (float)(coordCenter.X + Math.Cos(a * Math.PI / 180) * r);
    cartesian.Y = (float)(coordCenter.Y - Math.Sin(a * Math.PI / 180) * r);
}

void CartesianToPolar(Point coordCenter, Point cartesian, ref float a, ref float r)
{
    if (coordCenter == cartesian)
    {
        a = 0;
        r = 0;
        return;
    }
    double dx = cartesian.X - coordCenter.X;
    double dy = cartesian.Y - coordCenter.Y;
    r = (float)(Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)));
    a = (float)(Math.Atan(-dy / dx) * 180 / Math.PI);
    if (dx < 0) a += 180;
}
  



After Annealing I run UntangleLink for every link in the diagram.

If you set up the scenario I described you'll see that this is a pretty graceful solution. �But the self-referencing links still overlap.

I guess I can just write code that separates the links but makes sure they're outside the Node.

Any other ideas?

Thanks for your help,

JR
« Last Edit: May 31st, 2021 at 1:25pm by Forum Admin »  

JR
Back to top
 
IP Logged
 
JRobere
YaBB Newbies
*
Offline


Watch This!

Posts: 8
Joined: May 19th, 2009
Re: Overlapping Links
Reply #3 - Nov 9th, 2009 at 2:16pm
Print Post  
Ok Stoyo, I modified the code for the self-referencing links this way:

[code]
private void UntangleLink(DiagramLink NewLink)
{
    Point cp1, cp2;
    int pairOffset = 0;

    try
    {
        //get all common links between start and end state
        DiagramLinkCollection commonLinks = GetCommonLinks(NewLink.Origin, NewLink.Destination);
        if (commonLinks.Count > 1)
        {
            //get the start and end point of the calling link
            Point pt1 = NewLink.ControlPoints[0];
            Point pt2 = NewLink.ControlPoints[NewLink.ControlPoints.Count - 1];
            //loop thru all the common links
            for (int c = 0; c < commonLinks.Count; ++c)
            {
                DiagramLink link = commonLinks[c];
                link.Style = LinkStyle.Bezier;
                //reset to one segment
                link.SegmentCount = 1;
                //get new control points
                cp1 = new Point(pt1.X + 1 * (pt2.X - pt1.X) / 3, pt1.Y + 1 * (pt2.Y - pt1.Y) / 3);
                cp2 = new Point(pt1.X + 2 * (pt2.X - pt1.X) / 3, pt1.Y + 2 * (pt2.Y - pt1.Y) / 3);
                float angle = 0, radius = 0;
                CartesianToPolar(pt1, pt2, ref angle, ref radius);
                if (NewLink.Origin == NewLink.Destination)
                {
                    pairOffset = c * 20;
                    //it's self referencing
                    PolarToCartesian(cp1, angle - 90, pairOffset, ref cp1);
                    PolarToCartesian(cp2, angle - 90, pairOffset, ref cp2);
                }
                else
                {
                    pairOffset = (c / 2 + 1) * 15;
                    PolarToCartesian(cp1, c % 2 == 0 ? angle - 90 : angle + 90, pairOffset, ref cp1);
                    PolarToCartesian(cp2, c % 2 == 0 ? angle - 90 : angle + 90, pairOffset, ref cp2);
                }
                if (link.ControlPoints[0] == pt1)
                {
                    link.ControlPoints[1] = cp1;
                    link.ControlPoints[2] = cp2;
                }
                else
                {
                    link.ControlPoints[1] = cp2;
                    link.ControlPoints[2] = cp1;
                }
                link.UpdateFromPoints();
            }
        }
    }
    catch (Exception exc)
    {
        AUISL.Utilities.LogException(exc);
    }
}[/code]

And that looks ok but they're still a little to close to easily select them. If I push them further apart then they begin to overlap other Nodes.

The best solution here would be to move them to other anchor points. How do I do that?

Thanks and by the way, I love this product.

JR
« Last Edit: May 31st, 2021 at 1:28pm by Forum Admin »  

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Overlapping Links
Reply #4 - Nov 9th, 2009 at 2:33pm
Print Post  
Hi JR,

Have you tried using OrthogonalRouter to push the links apart? Also there is the DiagramNode.ReassignAnchorPoints method you might use instead of OrthogonalRouter, e.g. run it on all nodes after the layout and before updating the links:

foreach (DiagramNode node in diagram.Nodes)
     node.ReassignAnchorPoints();
foreach (DiagramLink link in diagram.Links)
     Untangle(link);

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