prologues := 1; tracingequations := 1; % maintain maximal height and width of node labels nodemaxheight := 0; nodemaxwidth := 0; def Node(suffix $)(expr nodelabel)(suffix leftnode, rightnode) = boolean $.node; $.node := true; pair $.c, $.n, $.s, $.e, $.w, $.nw, $.ne, $.se, $.sw; $.height = nodeheight; $.width = nodewidth; xpart $.n = xpart $.c = xpart $.s; ypart $.w = ypart $.c = ypart $.e; $.c = 1/2[$.n,$.s] = 1/2[$.w,$.e]; ypart $.n - ypart $.s = $.height; xpart $.e - xpart $.w = $.width; ypart $.nw = ypart $.n = ypart $.ne; ypart $.sw = ypart $.s = ypart $.se; xpart $.nw = xpart $.w = xpart $.sw; xpart $.ne = xpart $.e = xpart $.se; % measure caption and update nodemaxheight and nodemaxwidth, if necessary picture $.caption; $.caption = thelabel(nodelabel, origin); cw := xpart(lrcorner $.caption - llcorner $.caption); ch := ypart(ulcorner $.caption - llcorner $.caption); if cw > nodemaxwidth: nodemaxwidth := cw; fi; if ch > nodemaxheight: nodemaxheight := ch; fi; % width method vardef $.Width = 1.2 $.width + leftnode.Width + rightnode.Width enddef; % draw method boolean $.drawn; $.drawn := false; vardef $.Draw = if not $.drawn: $.drawn := true; if not known nodeheight: nodeheight = 4 nodemaxheight; fi; if not known nodewidth: nodewidth = 1.2 nodemaxwidth; fi; if not known $.c: $.c = origin; fi; path $.p; $.p := $.nw -- $.ne -- $.se -- $.sw -- cycle; draw $.p; draw $.w -- $.e; draw $.c -- $.s; draw $.caption shifted 0.5[$.n,$.c]; forsuffixes $$ = leftnode, rightnode: if $$.node: ypart $$.c = ypart $.c - 2 nodeheight; fi; endfor; if leftnode.node and rightnode.node: xpart leftnode.c + 1/2 * (leftnode.Width + rightnode.Width) = xpart rightnode.c; xpart $.c = xpart 0.5[leftnode.c,rightnode.c]; elseif leftnode.node: xpart leftnode.c = xpart $.c - 1/2 nodewidth; elseif rightnode.node: xpart rightnode.c = xpart $.c + 1/2 nodewidth; fi; leftnode.Draw; Arrow(0.5[$.c,$.sw], leftnode); rightnode.Draw; Arrow(0.5[$.c,$.se], rightnode); fi; enddef; enddef; def Arrow(expr pfrom)(suffix target) = if target.node: path dline; dline := pfrom -- target.c; pair pto; pto := dline intersectionpoint target.p; drawarrow pfrom -- pto; fi; enddef; boolean Nil.node; Nil.node := false; vardef Nil.Width = 0 enddef; vardef Nil.Draw = enddef; beginfig(1); pickup pencircle scaled 1pt; Node(A, btex A etex, Nil, Nil); Node(B, btex B etex, Nil, Nil); Node(C, btex C etex, A, B); Node(D, btex D etex, Nil, Nil); Node(E, btex E etex, D, Nil); Node(F, btex F etex, Nil, E); Node(G, btex G etex, C, F); Node(H, btex H etex, K, Nil); Node(I, btex I etex, Nil, Nil); Node(J, btex J etex, H, I); Node(K, btex K etex, L, Nil); Node(L, btex L etex, M, Nil); Node(M, btex MMMMMMMMMMM etex, Nil, Nil); Node(Root, btex Root etex, G, J); Root.Draw; endfig; end.