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.
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