Two nodes at the same level should be placed at least a given distance apart.
A parent should be centred over its o?spring.
Tree drawings should be symmetrical with respect to re?ection a tree and
its mirror image should produce drawings that are re?ections of each other. In
particular, this means that symmetric trees will be rendered symmetrically.
Identical subtrees should be rendered identically their position in the larger
tree should not a?ect their appearance.
Trees should be as narrow as possible without violating these rules
In order to calculate nodes' positions Kennedy takes a "bottom-up" approach:
Starting from the root node, draw for each node all its subtrees without breaking any rules. Fit these subtrees together without changing their shape, and also without breaking rules 1 and 3 (i.e do not break symmetry and avoid cluttering/overlapping of nodes). Finally, center their parent above them like specified in rule 2.
The "fitting" of the subtrees is calculated by operating on subtrees extents. A subtree extent is a data structure containing the relative coordinates of the boundary of a subtree. One frequent operation between extents is merging:
Other operations involve setting the distance between two extents, translating extents, etc.
Here's my code implementation, in case you want to compare it to Kennedy's.
My version takes into account different tree layouts (left, right, bottom, top), siblings and subtrees offsets and different node sizes as opposed to Kennedy's version.