I’m using a tree layout with vertices of varying sizes and I would like to have all descendants at a given depth from a vertex to be at the same level.

That’s on the list of requested features. Let me see what’s been done there, if anything.

OK, the following code only works with horizontally growing trees (i.e. Angle == 0 or Angle == 180):

[code] // This assumes the tree only grows horizontally: Angle == 0 or 180

public class CustomTreeLayout : TreeLayout {

// Assign each TreeVertex.Bounds.Width to be the same for all vertexes in the same layer,

// and just big enough to hold any vertex in that layer.

// This will cause all of the nodes in any layer to be aligned with each other.

protected override void LayoutTree(TreeVertex v) {

// compute maximum tree depth for all trees (not just the one with V at the root)

int maxdepth = 0;

foreach (Node root in this.Roots) {

TreeVertex rootv = this.Network.FindVertex(root);

if (rootv == null) continue;

maxdepth = Math.Max(maxdepth, rootv.MaxGenerationCount + 1);

}

```
// this array remembers the needed width for each layer of nodes
double[] allwidths = new double[maxdepth];
// find out how wide each layer must be
foreach (TreeVertex t in this.Network.Vertexes) {
double d = allwidths[t.Level];
allwidths[t.Level] = Math.Max(d, t.Bounds.Width);
}
// assign all TreeVertex.Bounds.Width values
foreach (TreeVertex t in this.Network.Vertexes) {
Rect b = v.Bounds;
b.Width = allwidths[v.Level];
v.Bounds = b;
}
// now do the normal tree layout
base.LayoutTree(v);
}
// If links are orthogonal, modify their middle points so that the vertical segments
// in each layer are all co-linear.
protected override void LayoutLinks() {
foreach (TreeVertex v in this.Network.Vertexes) {
double x = (v.Angle == 0) ? Double.PositiveInfinity : Double.NegativeInfinity;
foreach (TreeEdge e in v.DestinationEdges) {
if (v.Angle == 0) {
x = Math.Min(x, e.ToVertex.Bounds.Left);
} else {
x = Math.Max(x, e.ToVertex.Bounds.Right);
}
}
if (Double.IsInfinity(x)) continue;
foreach (TreeEdge e in v.DestinationEdges) {
Link link = e.Link;
if (link == null) continue;
Route route = link.Route;
if (route.Routing == LinkRouting.Normal) continue;
// require orthogonal links
Point p2 = route.GetPoint(2);
Point p3 = route.GetPoint(3);
if (v.Angle == 0) {
p2.X = x - 25;
p3.X = x - 25;
} else {
p2.X = x + 25;
p3.X = x + 25;
}
route.SetPoint(2, p2);
route.SetPoint(3, p3);
}
}
base.LayoutLinks();
}
```

}[/code]

This works by assigning a TreeVertex.Bounds.Width to each TreeVertex that is wide enough to hold all of the nodes/vertexes that are in that layer. This means you do **not** have to change the width of each Node.

This also changes the routes of orthogonal links by making sure the vertical middle segments are all co-linear and near the children. This should help reduce unintentional link crossings over nodes when the nodes have dramatically differing sizes.

If you want to handle vertical trees (e.g. Angle == 90), you’ll need to adapt this code.