Javascript
Javascript
Tree drawing
A tree does not record its absolute position, but its position
relative to its parent. The rigid information we have is:
\begin{itemize}
\item {\tt w}: width of bounding box
\item {\tt offset}: left edge of bounding box relative to parent
\item \verb|labOffset|: left edge of label relative to left edge
of bounding box
\item \verb|labW|: width of label
\end{itemize}
From that we can compute:
\begin{itemize}
\item {\tt x = px + offset}
\end{itemize}
We do not set {\tt x} permanently, because we may need to move the
tree repeatedly, and each move would require a walk over all the nodes
of the tree. Instead, we set {\tt x} temporarily, in the context of a
particular recursive descent of the tree. When {\tt x} is set, we can
compute:
\begin{itemize}
\item {\tt r = x + w}
\item \verb|labX = x + labOffset|
\item \verb|labR = labX + labW|
\item \verb|labCtr = labX + labW/2|
\end{itemize}
When we first create a tree, the {\tt offset} is set to 0. The {\tt offset}
is set to something meaningful when the tree becomes a child in a
larger tree.
To assemble a tree from a given {\tt label} and a list of {\tt children},
we must set the {\tt offset} of each child, and we must compute \verb|labOffset|
and {\tt w} for the new (parent) tree. Assume that {\tt spacer} is
also given: this is the minimum space we want between a pair of
adjacent labels.
The first child's offset is 0. Iterate through the remaining
children, and position them. Then {\tt w} is {\tt r} of the last
child. The desired center position is {\tt w}/2, so:
\begin{verbatim}
labOffset = w/2 - labW/2
\end{verbatim}
To position a {\tt child}, let {\tt prev} be the preceding child. We
do a recursive walk of the right edge of {\tt prev} and the left edge
of {\tt child}. At each step in the walk, we are given the current
descendant of {\tt prev} ({\tt pnode}),
the current descendant of {\tt child} ({\tt cnode}),
and the current estimate of {\tt offset}.
Both {\tt pnode} and {\tt cnode} have their {\tt x} values temporarily
set. (The setting of {\tt cnode.x} assumes that {\tt offset} is correct.)
The minimum $x$ position for {\tt cnode}'s label is
\begin{verbatim}
minleft = pnode.labR + spacer
\end{verbatim}
If \verb|cnode.labL| is less than {\tt minleft}, then add the
difference to {\tt offset} and also to {\tt cnode.x}. Then recurse.
When the recursion bottoms out, we will have the needed {\tt offset}
for {\tt child}.
After positioning all children, recall that we will need {\tt r} for
the last child. That can be computed by setting its {\tt x} value to
its {\tt offset}. The last child's parent is the node we are creating,
so we can safely define {\tt px} = 0.