Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Links origin point after arranging/routing (Read 4080 times)
lenix
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 31
Joined: Apr 6th, 2011
Links origin point after arranging/routing
Apr 16th, 2011 at 9:34am
Print Post  
Hello,

I'm drawing some complex diagrams using your nice libraries.

After I call an automatic layout to be applied on the diagram ( e.g.: spring layout ) and then reroute the links, I get the following:


Now it's fine and all but why some links have the same originating point?

I don't want any links to be drawn from the same point. I want to make use of the free node space.

Hoping for a quick reply, thanks a lot in advance Smiley


edit: I'd like to say that each of the two links originating from the same point are ending at the same point too. Maybe that's the reason.
In my diagram I need to draw more than one link between two nodes.
Is there any solution?
« Last Edit: Apr 16th, 2011 at 1:33pm by lenix »  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Links origin point after arranging/routing
Reply #1 - Apr 18th, 2011 at 7:43am
Print Post  
Hi,

Yes, most layout classes ignore repeating links between a pair of nodes, and they end up in the same position. Call the DistributeLinks method below on all nodes after layout to distribute the links uniformly along their current node sides.

Code
Select All
void DistributeLinks(DiagramNode node)
{
	var allLinks = node.GetAllLinks();

	var leftLinks = (from DiagramLink link in allLinks
		where (Math.Abs(node.Bounds.Left - AdjacentPoint(node, link).X) < 0.1)
		select link).ToList();
	leftLinks.Sort(new LinkComparer(node, false));
	DistributeVertically(leftLinks, node, node.Bounds.Left);

	var topLinks = (from DiagramLink link in allLinks
		where (Math.Abs(node.Bounds.Top - AdjacentPoint(node, link).Y) < 0.1)
		select link).ToList();
	topLinks.Sort(new LinkComparer(node, true));
	DistributeHorizontally(topLinks, node, node.Bounds.Top);

	var rightLinks = (from DiagramLink link in allLinks
		where (Math.Abs(node.Bounds.Right - AdjacentPoint(node, link).X) < 0.1)
		select link).ToList();
	rightLinks.Sort(new LinkComparer(node, false));
	DistributeVertically(rightLinks, node, node.Bounds.Right);

	var bottomLinks = (from DiagramLink link in allLinks
		where (Math.Abs(node.Bounds.Bottom - AdjacentPoint(node, link).Y) < 0.1)
		select link).ToList();
	bottomLinks.Sort(new LinkComparer(node, true));
	DistributeHorizontally(bottomLinks, node, node.Bounds.Bottom);
}

private void DistributeHorizontally(IList<DiagramLink> links, DiagramNode node, float y)
{
	float d = node.Bounds.Width / (links.Count + 1);
	float x = node.Bounds.Left + d;
	foreach (DiagramLink link in links)
	{
		int index = link.Origin == node ? 0 : link.ControlPoints.Count - 1;
		PointF c = node.GetCenter();
		float h = node.Bounds.Height;
		PointF p1 = new PointF(x, y + (c.Y > y ? - h: +h));
		PointF p2 = new PointF(x, c.Y);
		PointF p = node.GetIntersection(p1, p2);
		link.ControlPoints[index] = p;
		link.UpdateFromPoints(true, false);
		x += d;
	}
}

private void DistributeVertically(IList<DiagramLink> links, DiagramNode node, float x)
{
	float d = node.Bounds.Height / (links.Count + 1);
	float y = node.Bounds.Top + d;
	foreach (DiagramLink link in links)
	{
		int index = link.Origin == node ? 0 : link.ControlPoints.Count - 1;
		PointF c = node.GetCenter();
		float w = node.Bounds.Width;
		PointF p1 = new PointF(x + (c.X > x ? -w : +w), y);
		PointF p2 = new PointF(c.X, y);
		PointF p = node.GetIntersection(p1, p2);
		link.ControlPoints[index] = p;
		link.UpdateFromPoints(true, false);
		y += d;
	}
}

static PointF FarPoint(DiagramNode node, DiagramLink link)
{
	if (node == link.Destination)
		return link.ControlPoints[0];
	else
		return link.ControlPoints[link.ControlPoints.Count - 1];
}

static PointF AdjacentPoint(DiagramNode node, DiagramLink link)
{
	if (node == link.Origin)
		return link.ControlPoints[0];
	else
		return link.ControlPoints[link.ControlPoints.Count - 1];
}

public class LinkComparer : IComparer<DiagramLink>
{
	public LinkComparer(DiagramNode node, bool byX)
	{
		this.node = node;
		this.byX = byX;
	}

	public int Compare(DiagramLink link1, DiagramLink link2)
	{
		var a1 = byX ? AdjacentPoint(node, link1).X : AdjacentPoint(node, link1).Y;
		var a2 = byX ? AdjacentPoint(node, link2).X : AdjacentPoint(node, link2).Y;
		var f1 = byX ? FarPoint(node, link1).X : FarPoint(node, link1).Y;
		var f2 = byX ? FarPoint(node, link2).X : FarPoint(node, link2).Y;

		int result = a1.CompareTo(a2);
		if (result == 0)
			result = f1.CompareTo(f2);
		return result;
	}

	private DiagramNode node;
	private bool byX;
} 



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


I love YaBB 1G - SP1!

Posts: 31
Joined: Apr 6th, 2011
Re: Links origin point after arranging/routing
Reply #2 - Apr 20th, 2011 at 7:28am
Print Post  
Hey,
Thanks a lot for the methods, you guys rock and a purchase order will be coming your way soon.

Still a problem though, after I call the method, the links gets distributed, but they still don't look neat.

Check this:


Is there a way to make the links travel in straight lines and not diagonally like shown above?

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Links origin point after arranging/routing
Reply #3 - Apr 20th, 2011 at 7:36am
Print Post  
Hi,

Try calling the Distribute method after layout.Arrange but before diagram.RouteAllLinks().

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


I love YaBB 1G - SP1!

Posts: 31
Joined: Apr 6th, 2011
Re: Links origin point after arranging/routing
Reply #4 - Apr 20th, 2011 at 8:33am
Print Post  
If I call the distribute function before diagram.RouteAllLinks(), nothing happens, the points doesn't get distributed. Because the RouteAllLinks function is the one responsible for nodes originating/ending at same point.

Thanks,

edit: Like this
Code
Select All
     SpringLayout sl = new SpringLayout();
		sl.LinkType = SpringLayoutLinkType.Straight;
		sl.IterationCount = 1000;
		sl.NodeDistance = 30;
		sl.KeepGroupLayout = true;
		sl.Arrange(diagram1);
		foreach (DiagramNode node in diagram1.Nodes)
		{
		    DistributeLinks(node);
		}
		diagram1.RouteAllLinks(); 

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Links origin point after arranging/routing
Reply #5 - Apr 20th, 2011 at 9:38am
Print Post  
Works fine in my test project. If you have enabled the Dynamic property of links, try setting it to false before routing. Also try different values of RoutingOptions.Anchoring.
  
Back to top
 
IP Logged
 
lenix
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 31
Joined: Apr 6th, 2011
Re: Links origin point after arranging/routing
Reply #6 - Apr 23rd, 2011 at 6:55am
Print Post  
I got it working... thanks a lot ( I think it was something to do with the Dynamic property of links ).

I still have more questions for you if you don't mind, I'll open a new thread because its about something else.

Many thanks,
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint