Swank Canvas Scene Graph

Advanced graphics applications often arrange the display items as a collection of nodes in a graph structure known as a Scene Graph . Rendering of the items is then done by traversing the scene graph and rendering each viewable item. Whether or not items are rendered in front of or behind other items depends on their relative position in the scene graph. A scene graph is being developed for the Swank canvas. As currently implemented (and not yet released as of 4 Jan 2010) the Swank canvas scene graph is implemented by adding a new "-node" configuration option for each item on the canvas and adding a new node item type. Each traditional item on a canvas (arc, rectangle, line etc.) exists as leaf node on the graph and can not have other items attached. Only the new node item can have descendants, which may be traditional display items, or additional nodes.

If nodes are not specified the canvas acts as the traditional Tk canvas, effectively being a scene graph with one root node and zero or more visual items that are rendered in order of their attachment to the root node. The scene graph is rendered in a depth-first (post-ordered) fashion with children at each node rendered from left to right (first to last added). The bounding box (returned with the "canvas bbox" command) is the union of the bounds of all the items below that node. Node items are also rendered if they have a non empty fill or outline parameter. They are rendered as rectangles whose size is the same as the bounding box described above. Note that if the fill parameter is set, and is a not transparent, all items below that node will be obscured as the node is drawn after the items below it on the graph.

The raise and lower canvas subcommands have a modified behavior with respect to scene graphs that have more than one node. A raise command issued without a "aboveThis" argument will move the specified items to be the last items of the node to which they are attached. If an "aboveThis" argument is specified, the aboveThis item must be attached to the same node as any items to be moved. Thus raise (and the comparable holds for lower) will only change the display order of items relative to other items attached to the same node (but, note that node items themselves can be raised or lowered).

If the the "-state" option is set to "hidden" for a node, then all items below that node will not be visible.

Still under development, is the ability to set transforms to nodes that will apply to all items below it. Rendering of each item will be done with an affine transform that is the product of the transforms of all nodes above it.

The following script is an example of using nodes.

pack [canvas .c -width 200 -height 200 -bg white] -fill both -expand y

set node0 [.c create node 0 0 -outline blue -width 2]
set node1 [.c create node 0 0 -outline green -width 2]

set red [.c create rectangle 50 50 100 100 -fill red]
set yellow [.c create rectangle 60 60 110 110 -fill yellow]
set green [.c create rectangle 70 70 120 120 -fill green]
set purple [.c create rectangle 80 80 130 130 -fill purple]


.c itemconfigure $red -node $node0
.c itemconfigure $yellow -node $node1
.c itemconfigure $green -node $node1
.c itemconfigure $node1 -node $node0
.c itemconfigure $purple -node $node0
.c raise $red $purple
vwait done