Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Layout Challenge (Read 4490 times)
jlj30
Full Member
***
Offline


I love YaBB 1G - SP1!

Posts: 183
Joined: Sep 4th, 2011
Layout Challenge
Mar 5th, 2013 at 5:34pm
Print Post  
Hi,

I have attached 2 screenshots.
One is the actual diagram that is rendered (with the red arrow and textbox); the other is how we'd like it to look.

The main concern is the placement of the start shape (the solid circle).

Any suggestions on how we might be able to locate this symbol as indicated?

I have also included the relevant C# code below.

Thanks

Jim

Code (C++)
Select All
case "Orthogonal":
                {
                    OrthogonalLayout layout = new OrthogonalLayout();
                    layout.Padding = 25;
                    layout.Arrange(diagram);
                    OrthogonalRouter layout2 = new OrthogonalRouter();
                    layout2.Arrange(diagram);
                    MirrorVertically(diagram);  // Increase the likelihood of the start shape being at the top of the diagram
                    setLinksToSingleSegment(diagram);  // Make the text on the links be center'd
                    fixSelfLoopBackLinks(diagram); // Draws a more attractive (bezier curve)
                    break;
                } 



Code (C++)
Select All
protected void MirrorVertically(Diagram diagram)
    {
        // Adapted from code provided by MF

        var bounds = diagram.GetContentBounds(false, true);
        var y = bounds.Y + bounds.Height / 2;
        foreach (DiagramNode node in diagram.Nodes)
        {
            var ny = node.GetCenter().Y;
            var dy = ny - y;
            MoveNode(node, y - dy);
        }
        foreach (DiagramLink link in diagram.Links)
        {
            for (int i = 0; i < link.ControlPoints.Count; i++)
            {
                var p = link.ControlPoints[i];
                var dy = p.Y - y;
                p.Y = y - dy;
                link.ControlPoints[i] = p;
            }
            link.UpdateFromPoints(false, false);
        }
        diagram.Invalidate();
    }

    protected void MoveNode(DiagramNode node, float newY)
    {
        var bounds = node.Bounds;
        bounds.Y = newY - bounds.Height / 2;
        node.SetBounds(bounds, false, false);
    }  



Code (C++)
Select All
protected void setLinksToSingleSegment(Diagram diagram)
    {
        foreach (DiagramLink link in diagram.Links)
        {
            // If the link is vertical (all X coordinates the same) then reduce the # of segments to 1
            // This will ensure that the Rotate LinkTextStyle and StringAlignment.Center work properly
            // Adapted from code provided by MF

            if (link.SegmentCount == 3 && link.ControlPoints[0].X == link.ControlPoints[1].X && link.ControlPoints[1].X == link.ControlPoints[2].X && link.ControlPoints[2].X == link.ControlPoints[3].X)
            {
	            var p1 = link.ControlPoints[0];
	            var p2 = link.ControlPoints[3];
	            link.Style = LinkStyle.Polyline;
                //link.Shape = LinkShape.Polyline; // NetDiagram V5
	            link.SegmentCount = 1;
	            link.ControlPoints[0] = p1;
	            link.ControlPoints[1] = p2;
	            link.UpdateFromPoints();
            }

            // If the link is horizontal (all Y coordinates the same) then reduce the # of segments to 1
            // This will ensure that the Rotate LinkTextStyle and StringAlignment.Center work properly

            if (link.SegmentCount == 3 && link.ControlPoints[0].Y == link.ControlPoints[1].Y && link.ControlPoints[1].Y == link.ControlPoints[2].Y && link.ControlPoints[2].Y == link.ControlPoints[3].Y)
            {
                var p1 = link.ControlPoints[0];
                var p2 = link.ControlPoints[3];
                link.Style = LinkStyle.Polyline;
                //link.Shape = LinkShape.Polyline; // NetDiagram V5
                link.SegmentCount = 1;
                link.ControlPoints[0] = p1;
                link.ControlPoints[1] = p2;
                link.UpdateFromPoints();
            }
        }
    } 



Code (C++)
Select All
protected void fixSelfLoopBackLinks(Diagram diagram)
    {
        foreach (DiagramLink link in diagram.Links)
        {
            if (link.Origin == link.Destination)  // Is this a loop back to the same state?
            {
                RectangleF r = link.Origin.Bounds;
                float centerx = r.Left + r.Width / 2;
                float dist = 16;
                SetLinkPoints(link,
                    new PointF(centerx, r.Top),
                    new PointF(centerx - dist, r.Top - dist),
                    new PointF(centerx + dist, r.Top - dist),
                    new PointF(centerx, r.Top));
            }
        }
    } 

  

NetDiagram_-_State_Diagram_As_Desired.png (Attachment deleted)
NetDiagram_-_State_Diagram_As_Generated.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Layout Challenge
Reply #1 - Mar 5th, 2013 at 6:01pm
Print Post  
Please attach the diagram xml file.
  
Back to top
 
IP Logged
 
jlj30
Full Member
***
Offline


I love YaBB 1G - SP1!

Posts: 183
Joined: Sep 4th, 2011
Re: Layout Challenge
Reply #2 - Mar 5th, 2013 at 6:17pm
Print Post  
Here's the XML file.
I changed the suffix to txt.
Jim
  

Change_Management__V3__State_Diagram_05Mar2013-1314-52.txt (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Layout Challenge
Reply #3 - Mar 6th, 2013 at 3:45pm
Print Post  
What OrthogonalLayout does is to arrange faces in the graph by some rectangle-tesselation method, and it selects the largest face as the external rectangle. So you should be able to ensure your start and end nodes are not inside other faces (face meaning a plane region enclosed by links) by creating a long enough virtual path from start to end, which should make their face the largest:

Code
Select All
List<DiagramItem> CreateVirtualPath(DiagramNode node1, DiagramNode node2, int len)
{
	var path = new List<DiagramItem>();
	var prev = node1;
	for (int i = 0; i < len; i++)
	{
		var virtualNode = diagram.Factory.CreateShapeNode(0, 0, 10, 10);
		var virtualLink = diagram.Factory.CreateDiagramLink(prev, virtualNode);
		virtualLink.Pen = new Pen(Color.Red);
		prev = virtualNode;
		path.Add(virtualNode);
		path.Add(virtualLink);
	}
	path.Add(diagram.Factory.CreateDiagramLink(prev, node2));
	return path;
}

private void btnOthogonalLayout_Click(object sender, EventArgs e)
{
	var start = diagram.Nodes[0];
	var end = diagram.Nodes[13];
	var vp = CreateVirtualPath(start, end, 2);

	OrthogonalLayout layout = new OrthogonalLayout();
	layout.Padding = 25;
	layout.Arrange(diagram);
	OrthogonalRouter layout2 = new OrthogonalRouter();
	layout2.Arrange(diagram);
	MirrorVertically(diagram);  // Increase the likelihood of the start shape being at the top of the diagram
	setLinksToSingleSegment(diagram);  // Make the text on the links be center'd
	fixSelfLoopBackLinks(diagram); // Draws a more attractive (bezier curve)

	diagram.ResizeToFitItems(5);
	foreach (var item in vp)
		if (diagram.Items.Contains(item))
			diagram.Items.Remove(item);
} 





Our layout developer isn't sure if this will work for non-planar graphs, he'll check this and try to add Start/EndNode options for next release.

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: Layout Challenge
Reply #4 - Mar 6th, 2013 at 8:25pm
Print Post  
Stoyan,

I tried out the code you provided and it's better.
I won't pretend to understand it, but thanks again for some useful code.

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