12 Tree Layout
These functions specify tree layouts and functions that render them as picts.
(require pict/tree-layout) | package: pict-lib |
procedure
(tree-layout [#:pict node-pict] child ...) → tree-layout?
node-pict : (or/c #f pict?) = #f child : (or/c tree-layout? tree-edge? #f)
If the children are tree-layout?s, then they have edges created by passing the corresponding tree-layout?s directly to tree-edge. Children that are #f correspond to leaf nodes that are not drawn.
The default node-pict (used when node-pict is #f) is .
procedure
(tree-edge node [ #:edge-color edge-color #:edge-width edge-width #:edge-style edge-style]) → tree-edge? node : (and/c tree-layout? (not/c #f))
edge-color :
(or/c string? (is-a?/c color%) (list/c byte? byte? byte?)) = "gray" edge-width : (or/c 'unspecified real? #f) = 'unspecified
edge-style :
(or/c 'unspecified 'transparent 'solid 'xor 'hilite 'dot 'long-dash 'short-dash 'dot-dash 'xor-dot 'xor-long-dash 'xor-short-dash 'xor-dot-dash) = 'unspecified
When edge-width is 'unspecified, the line width will not be set. This is intended to allow the line width to be set for the whole pict via linewidth. Otherwise, edge-width is interpreted the same way as the width argument for the linewidth function. edge-style behaves similarly, its argument interpreted as the style argument for the linestyle function.
> (naive-layered (tree-layout (tree-edge #:edge-width 3 (tree-layout)) (tree-edge #:edge-color "red" #:edge-style 'dot (tree-layout))))
Changed in version 1.3 of package pict-lib: Added the #:edge-width option.
Changed in version 1.9: Added the #:edge-style option.
procedure
(tree-layout? v) → boolean?
v : any/c
procedure
(binary-tree-layout? v) → boolean?
v : any/c
> (binary-tree-layout? (tree-layout #f #f)) #t
> (binary-tree-layout? #f) #t
> (binary-tree-layout? (tree-layout (tree-layout) (tree-layout))) #f
procedure
(tree-edge? v) → boolean?
v : any/c
procedure
(naive-layered tree-layout [ #:x-spacing x-spacing #:y-spacing y-spacing #:transform transform]) → pict? tree-layout : tree-layout? x-spacing : (or/c (and/c real? positive?) #f) = #f y-spacing : (or/c (and/c real? positive?) #f) = #f transform : (-> real? real? (values real? real?)) = values
The transform argument applies a coordinate transformation to each of the nodes after it has been layed out. The bounding box of the resulting pict encompasses the corners of the original bounding box after the transformation has been applied to them.
> (define (complete d) (cond [(zero? d) #f] [else (define s (complete (- d 1))) (tree-layout s s)])) > (naive-layered (complete 4)) > (naive-layered (complete 4) #:transform (lambda (x y) (values y x)))
> (naive-layered (tree-layout (tree-layout) (tree-layout) (tree-layout (tree-layout) (tree-layout) (tree-layout (tree-layout) (tree-layout)))))
> (define right-subtree-with-left-chain (tree-layout (tree-layout (tree-layout #f #f) (tree-layout (tree-layout #f #f) #f)) (tree-layout (tree-layout (tree-layout (tree-layout (tree-layout #f #f) #f) #f) #f) #f))) > (naive-layered right-subtree-with-left-chain)
Changed in version 1.13 of package pict-lib: Added the #:transform option.
procedure
(binary-tidier tree-layout [ #:x-spacing x-spacing #:y-spacing y-spacing #:transform transform]) → pict? tree-layout : binary-tree-layout? x-spacing : (or/c (and/c real? positive?) #f) = #f y-spacing : (or/c (and/c real? positive?) #f) = #f transform : (-> real? real? (values real? real?)) = values
nodes at the same level of tree appear at the same vertical distance from the top of the pict
parents are centered over their children, which are placed from left to right,
isomorphic subtrees are drawn the same way, no matter where they appear in the complete tree, and
a tree and its mirror image produce picts that are mirror images of each other (which also holds for subtrees of the complete tree).
More precisely, it recursively lays out the two subtree and then, without adjusting the layout of the two subtrees, moves them as close together as it can, putting the root of the new tree centered on top of its children. (It does this in linear time, using clever techniques as discussed in the paper.)
The x-spacing and y-spacing are the amount of space that each row and each column takes up, measured in pixels. If x-spacing is #f, it is the width of the widest node pict? in the tree. If y-spacing is #f, it is 1.5 times the width of the widest node pict? in the tree. The transform is the same as in naive-layered.
> (binary-tidier (complete 4)) > (define (dl t) (tree-layout (tree-layout #f #f) t)) > (define (dr t) (tree-layout t (tree-layout #f #f)))
> (binary-tidier (tree-layout (dr (dr (dr (dl (dl (dl (complete 2))))))) (dl (dl (dl (dr (dr (dr (complete 2))))))))) > (binary-tidier right-subtree-with-left-chain)
Changed in version 1.13 of package pict-lib: Added the #:transform option.
procedure
(hv-alternating tree-layout [ #:x-spacing x-spacing #:y-spacing y-spacing #:transform transform]) → pict? tree-layout : binary-tree-layout? x-spacing : (or/c (and/c real? positive?) #f) = #f y-spacing : (or/c (and/c real? positive?) #f) = #f transform : (-> real? real? (values real? real?)) = values
It adds horizontal and vertical space between layers based on x-spacing and y-spacing. If either is #f, 1.5 times the size of the biggest node is used. The transform is the same as in naive-layered.
> (hv-alternating (complete 8))
Changed in version 1.13 of package pict-lib: Added the #:transform option.
Added in version 6.0.1.4 of package pict-lib.