Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Automatic layout of genogram-style chart (Read 5002 times)
dossantos
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 21
Joined: Mar 25th, 2013
Automatic layout of genogram-style chart
Mar 25th, 2013 at 9:38am
Print Post  
Hello,


I'm currently evaluating different flowcharting libraries, and I have one use case I'd like to implement using FlowChar.net to see whether it is appropriate for my needs. I fiddled around a bit with the examples et.al. but wasn't able to get the desired behaviour yet, so maybe someone could help me a bit.

What I need is a genogram, in its strongly defined sense. So the minimum criteria are:

- Couples (man + woman) are represented by two nodes (circle for woman, square for man) that are connected by a horizontal link below the nodes, starting and ending vertically at the bottom of each node.
- Children of the couples are represented by nodes in the next layer/lane that are connected to the abovementioned link, and evenly distributed along its length.
- If there's, for example, a woman that has children with two different men, most optimally the woman-node should be positioned between the man-nodes, have one link to each of the men (going down, across, up, as mentioned above), and the children are of course positioned below the corresponding "couple-links" with vertical links to them.
- If a couple has several children, the man- and woman-nodes need to be placed with some distance between them to create enough space below their "couple-link" for the children-nodes.

I tried to use the Swimlane layout for this, and manually assign the "lane" trait to sort the people into "generations" (so couples are on the same lane, and children are in the next lane, and so on). This works fine (even for many generations).

But I failed to get the link routing to perform well automatically. For example, what I'd need is that links may be superpositioned horizontally, but have distinct sections vertically. I also tried to insert invisible helper nodes between lanes, but that's very fiddly...


Has someone suggestions how to get the desired routing? (I assume the "genogram" example in the example app was built manually, without automatic layout, is this correct?)

Thanks, cheers,
Tim


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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: Automatic layout of genogram-style chart
Reply #1 - Mar 25th, 2013 at 12:29pm
Print Post  
Hi,

I think the best result you can get with built-in layouts is via LayeredLayout with custom layers enabled to map generation to layer. Also add a fictional node for each couple with children and connect parent and child nodes to it to keep them close together. With that, you should get nice node positions without link crossings, and could do some post-processing to set link shapes, align nodes, etc. For example the code below creates a subset of the diagram shown at http://www.genopro.com/genogram/, and produces the layout shown in the image.

Code
Select All
void TestGenogram()
{
	GenerateGenogram();
	ArrangeGenogram();
}

void GenerateGenogram()
{
	diagram.ClearAll();

	var n1 = AddNode("Grand Papa", 0);
	var n2 = AddNode("Grand Maman", 0);
	var c1 = SetCouple(n1, n2);

	var n3 = AddNode("Pierre", 0);
	var n4 = AddNode("Yolande", 0);
	var c2 = SetCouple(n3, n4);

	var n5 = AddNode("Lisa", 0);
	var n6 = AddNode("Lisa's first hsb.", 0);
	var c3 = SetCouple(n5, n6);

	var n7 = AddNode("Andre", 1);
	var n8 = AddNode("Helene", 1);
	var n9 = AddNode("???", 1);
	var c4 = SetCouple(n7, n8);
	var c5 = SetCouple(n7, n9);

	SetChild(n7, c1);
	SetChild(n8, c2);
	SetChild(n9, c3);

	var n10 = AddNode("Daniel", 2);
	var n11 = AddNode("Anne", 2);
	var n12 = AddNode("Benoit", 2);
	var n13 = AddNode("Raphael", 2);
	var n14 = AddNode("Estelle", 2);
	var n15 = AddNode("Jean claude", 2);
	var n16 = AddNode("Mike", 2);

	SetChild(n10, c4);
	SetChild(n11, c4);
	SetChild(n12, c4);
	SetChild(n14, c4);
	SetChild(n15, c4);
	SetChild(n16, c5);

	SetCouple(n13, n14);
}

DiagramNode AddNode(string name, int generation)
{
	var node = diagram.Factory.CreateShapeNode(0, 0, 15, 8);
	node.Text = name;
	node.LayoutTraits[LayeredLayoutTraits.Layer] = generation * 2;
	node.Font = new Font("Arial", 7);
	return node;
}

void SetChild(DiagramNode node, DiagramNode couple)
{
	diagram.Factory.CreateDiagramLink(couple, node);
}

DiagramNode SetCouple(DiagramNode n1, DiagramNode n2)
{
	var node = diagram.Factory.CreateShapeNode(0, 0, 1, 1);
	node.Transparent = true;
	node.LayoutTraits[LayeredLayoutTraits.Layer] =
		(int)n1.LayoutTraits[LayeredLayoutTraits.Layer] + 1;
	var l1 = diagram.Factory.CreateDiagramLink(n1, node);
	l1.HeadShape = ArrowHeads.None;
	var l2 = diagram.Factory.CreateDiagramLink(n2, node);
	l2.HeadShape = ArrowHeads.None;
	return node;
}

void ArrangeGenogram()
{
	var ll = new LayeredLayout();
	ll.EnableCustomLayers = true;
	ll.LayerDistance = 10;
	ll.StraightenLongLinks = true;
	ll.Arrange(diagram);

	foreach (var link in diagram.Links)
	{
		link.Shape = LinkShape.Cascading;
		var or = link.Origin.Bounds;
		var dr = link.Destination.Bounds;
		SetLinkPoints(link,
			new PointF(or.X + or.Width / 2, or.Bottom),
			new PointF(or.X + or.Width / 2, (or.Bottom + dr.Top) / 2),
			new PointF(dr.X + dr.Width / 2, (or.Bottom + dr.Top) / 2),
			new PointF(dr.X + dr.Width / 2, dr.Top));
	}
}

void SetLinkPoints(DiagramLink link, params PointF[] points)
{
	link.AutoRoute = false;
	link.Shape = LinkShape.Cascading;
	link.ControlPoints.Clear();
	link.ControlPoints.AddRange(points);
	link.UpdateFromPoints(false, true);
} 





Some further post-processing you could do is to align parent nodes to the leftmost and rightmost coordinates of their children, and draw couple-to-child links as parallel lines starting from the parent-to-couple links.

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


I Love MindFusion!

Posts: 21
Joined: Mar 25th, 2013
Re: Automatic layout of genogram-style chart
Reply #2 - Mar 26th, 2013 at 7:04am
Print Post  
Thanks very much for the hints, this looks a bit similar to what I tried with the swimlane layout, but it seems the routing of the layered layout is a bit better suited for this kind of task.

Again, thanks, I'll try your suggestion Smiley
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint