// A simple tree drawing module contributed by adarovsky // See example treetest.asy real treeNodeStep = 0.5cm; real treeLevelStep = 1cm; real treeMinNodeWidth = 2cm; struct TreeNode { TreeNode parent; TreeNode[] children; frame content; pair pos; real adjust; } void add( TreeNode child, TreeNode parent ) { child.parent = parent; parent.children.push( child ); } TreeNode makeNode( TreeNode parent = null, frame f ) { TreeNode child = new TreeNode; child.content = f; if( parent != null ) { add( child, parent ); } return child; } TreeNode makeNode( TreeNode parent = null, Label label ) { frame f; box( f, label); return makeNode( parent, f ); } real layout( int level, TreeNode node ) { if( node.children.length > 0 ) { real width[] = new real[node.children.length]; real curWidth = 0; for( int i = 0; i < node.children.length; ++i ) { width[i] = layout( level+1, node.children[i] ); node.children[i].pos = (curWidth + width[i]/2, -level*treeLevelStep); curWidth += width[i] + treeNodeStep; } real midPoint = ( sum( width )+treeNodeStep*(width.length-1)) / 2; for( int i = 0; i < node.children.length; ++i ) { node.children[i].adjust = - midPoint; } return max( (max(node.content)-min(node.content)).x, sum(width)+treeNodeStep*(width.length-1) ); } else { return max( treeMinNodeWidth, (max(node.content)-min(node.content)).x ); } } void drawAll( TreeNode node, frame f ) { pair pos; if( node.parent != null ) pos = (node.parent.pos.x+node.adjust, 0); else pos = (node.adjust, 0); node.pos += pos; node.content = shift(node.pos)*node.content; add( f, node.content ); if( node.parent != null ) { path p = point(node.content, N)--point(node.parent.content,S); draw( f, p, currentpen ); } for( int i = 0; i < node.children.length; ++i ) drawAll( node.children[i], f ); } void draw( TreeNode root, pair pos ) { frame f; root.pos = (0,0); layout( 1, root ); drawAll( root, f ); add(f,pos); }