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.