Axiom - Scenegraph Users Reference

The Scenegraph Concept

A scenegraph consists of a number of nodes in a tree structure, the types of nodes are:

This tree is constructed by starting with the root node and adding child nodes using the addChild! function as follows:

addChild!:(n:%,c:%) -> Void

where 'c' is the child node and 'n' node that it is being added to. Any node type can be a child node or a parent (although it only makes sense to put the root node only at the root).

In general a given node will affect only those nodes under it in the tree structure.

The purpose and constructors of these nodes is as follows: (in the following definitions PT refers to an instance of SPointCategory such as SCartesian,SArgand or SConformal).

Root Node

Every scenegraph must have one root node and all other nodes must be added, in a tree structure, under this node (either directly or indirectly). So the root node can represent the whole scenegraph and it is what is passed to export routines, for example, to export the whole scenegraph. scene root
createSceneRoot:() -> %
createSceneRoot:(bb: SBoundary(PT)) -> %
createSceneRoot:(minx:I,miny:I,maxx:I,maxy:I) -> %

The parameters define the boundary. This bounding box is intended to be the area or volume in which the graphical objects are drawn, elements of the geometry outside this area will not necessarily be clipped (to be sure use a clipping node with the same boundary). The bounding box in the root node has these additional effects:

If the first version (without boundary information) is used then the boundary will be calculated, to include all the nodes, when the scene is first drawn to a file.

For more information about boundaries see page here.

Group Node

Constructs a group node, this node does not do anything itself but contains other nodes. Any node can contain other nodes - we do not need to use a group node to do this, but if we just want to group nodes without any other effects then this is a good choice.
createSceneGroup:() -> %
addSceneGroup:(n:%) -> %

addSceneGroup is a convenience function which combines the constructor createSceneGroup with addChild! This allows a scene graph node to be constructed and added to the scenegraph in one operation. Most of the scenegraph constructors have this form as an option.

Line Node

Constructs a line node, this contains a (possibly curved) line,represented by a list of points) in n-dimensional space. The dimension of the space is implicit in the type of points being used.

A Line node can hold a single line or multiple lines. The reason that a Line node needs to hold multiple lines is that, when a clip is applied to a line this might break it into several line segments.

The following form constructs a single line:

createSceneLine:(line: List PT) -> %
addSceneLine:(n:%,line: List PT) -> %

The following form constructs multiple lines:

createSceneLines:(line: LINES) -> %
addSceneLines:(n:%,line: LINES) -> %

Where: LINES==> List List PT

The following form constructs a single line where the endpoints are specified by nodes, the line is drawn upto the boundary of the nodes. This way of constructing lines is useful for drawing an 'edge' in graph theory.

createSceneLine:(st:%,en:%) -> %
addSceneLine:(n:%,st:%,en:%) -> %

Arrow Node

Constructs a arrow node, this contains a line or lines with an arrow head at the end in n-dimensional space. The dimension of the space is implicit in the type of points being used.

The size of the arrow head is controlled by 'mode' and 'size' parameters. 'mode' can have the following values:

So "proportional" would typically be used when drawing a graph (in graph theory) where it looks better if each arrow head is the same. "variable" would typically be used when drawing a force field where a bigger arrow head might indicate a stronger force.

createSceneArrows:(line: List List PT,mode:Symbol,size:DF) -> %
addSceneArrows:(n:%,line: List List PT,mode:Symbol,size:DF) -> %

The following form constructs an arrow where the endpoints are specified by names from named points node:

createSceneArrow:(st:String,en:String,offset:PT,mode:Symbol,size:DF) -> %
addSceneArrow:(n:%,st:String,en:String,offset:PT,mode:Symbol,size:DF) -> %

The following form constructs a single arrow where the endpoints are specified by nodes, the arrow is drawn upto the boundary of the nodes. This way of constructing arrows is useful for drawing an directed edge in graph theory.

createSceneArrow:(st:%,en:%,offset:PT,mode:Symbol,size:DF) -> %
addSceneArrow:(n:%,st:%,en:%,offset:PT,mode:Symbol,size:DF) -> %

More about arrows here.

Indexed Face Set (IFS) Node

Constructs an indexed face set node, this defines a surface in n-dimensional space represented by a set of polygons in n-dimensional space.

createSceneIFS:(inx: List List NNI,pts: List PT) -> %
    addSceneIFS:(n:%,inx: List List NNI,pts: List PT) -> %
    createSceneIFS:(in1: SceneIFS(PT)) -> %
    addSceneIFS:(n:%,in1: SceneIFS(PT)) -> %

A specialised constructor for an IFS node constructs a 3D box. Constructs an indexed face set node which is a 3D box of a given size

createSceneBox:(size:DF) -> %
    addSceneBox:(n:%,size:DF) -> %

Text Node

Constructs a text node, text can be used for labelling anything such as graphs, axes and so on.

createSceneText:(text: TEXT) -> %
    addSceneText:(n:%,text: TEXT) -> %
    createSceneText:(str:String,sz:NNI,pz:PT) -> %
    addSceneText:(n:%,str:String,sz:NNI,pz:PT) -> %

where: TEXT==> Record(txt:String,siz:NNI,pos:PT) which defines the text to be printed with its size and position.

Clip Node

Constructs a clip node, clips its sub nodes in the coordinate system in force at the clip node.

createSceneClip:(bb: SBoundary(PT)) -> %
addSceneClip:(n:%,bb: SBoundary(PT)) -> %

where: bb is the boundary that the node is clipped to.

Material Node

Constructs a material node

This sets:

for all nodes under it, unless overridden by another material node. That is the material parameters that apply to a given node are those of the closest material node above it in the hierarchy

createSceneMaterial:(mat:MATERIAL) -> %
addSceneMaterial:(n:%,mat:MATERIAL) -> %
createSceneMaterial:(lineW:DF,lineC:String,fillC:String) -> %
addSceneMaterial:(n:%,lineW:DF,lineC:String,fillC:String) -> %

Where: MATERIAL==> Record(lineWidth:DF,lineCol:String,fillCol:String)

Transform Node

Constructs a transform node

This transforms the points and vectors below this node If a given node has more than one transform node above it in the hierarchy then the transforms are concatenated (combined).

createSceneTransform:(tran:TR) -> %
addSceneTransform:(n:%,tran:TR) -> %

Or once the transform has already been created we can change the transform it represents, without altering the scene heirachy, this may be useful to create animations for example:

setTransform!:(n:%,tran:TR) -> Void

where tran is of type STransform(PT) and may be constructed in one of the following ways:

Construct with given matrix elements:

stransform: (m:List List DF) -> %

Construct transform in general form as a mapping from PT to PT:

stransform: (gen:PT -> PT) -> %

Construct transform as function of complex variable can only be used when PT is SArgand so this can be converted to PT -> PT:

stransform: (cpx:C -> C) -> %

Construct with a multivector:

stransform: (m: List DF) -> %

Construct transform which represents pure translation ++ we can also combine with scale which, for instance, is useful when writing to SVG file because the y dimension is inverted:

stranslate: (offsetx:DF,offsety:DF,offsetz:DF,scalex:DF,_
                 scaley:DF,scalez:DF) -> %

returns the identity element which is do nothing transform:

identity: () -> %

For more information about transformations see page here.

Shape Node

A shape is something like a rectangle or an ellipse in 2 dimensions or a sphere or box in 3 dimensions.

Its main purpose here, especially in 2 dimensions, is to provide a way to graphically show sets or visually associate things together. That is, the shape could be drawn around other elements to show that they are a set. For example we could draw Venn diagrams or show how one set of elements maps to another set of elements.

Of course we could create a shape by plotting the equation for that shape, for example, by using 'ParametricPlaneCurve'. However that would be unnecessarily complicated when we just want a shape to visually show a grouping of elements, the mathematical properties of the shape are not the issue here.

The shape is stored as follows:

SHAPE ==> Record(shptype:Symbol,centre:PT,size:PT,fill:Boolean)

where:

  addSceneLines:(n:%,line: LINES) -> %
    ++ a convenience function which combines createSceneLines with addChild!
  createSceneShape:(shape:SHAPE) -> %
    ++ This just creates the shape without adding it.

A tutorial showing examples of how to use the shape node is here.

Named Points Node

The aim of the 'named points' node and associated domain is to provide better support for drawing graphs (that is 'graphs' as in graph theory) and diagrams of trees, latices and category theory arrow diagrams. In other words, diagrams with named nodes and arrows or lines between these nodes.

createSceneNamedPoints:(np:SceneNamedPoints PT) -> %
    ++ createSceneNamedPoints(np) constructs a named points node, this
    ++ allows us to define a set of points which can be used multiple
    ++ times in the scenegraph.
addSceneNamedPoints:(n:%,np:SceneNamedPoints PT) -> %
    ++ addSceneNamedPoints(n,np) is a convenience function which
    ++ combines createSceneNamedPoints with addChild!

A tutorial showing examples of how to use the named point node is here.

Def Node

The 'def' and 'use' constructs are used together to allow us to include a branch of the scenegraph multiple times in the scene.

createSceneDef:(nam:String,nde:%) -> %
    ++ createSceneDef(nam,nde) defines a point in the scenegraph
    ++ so that it can be used elsewhere.
addSceneDef:(n:%,nam:String,nde:%) -> %
    ++ addSceneDef(n,nam,nde) is a convenience function which
    ++ combines createSceneDef with addChild!

A tutorial showing examples of how to use the def and use nodes is here.

Use Node

The 'def' and 'use' constructs are used together to allow us to include a branch of the scenegraph multiple times in the scene.

createSceneUse:(nam:String) -> %
    ++ createSceneUse(nam) uses another point in the scenegraph.
addSceneUse:(n:%,nam:String) -> %
    ++ addSceneUse(n,nam) is a convenience function which
    ++ combines createSceneUse with addChild!

A tutorial showing examples of how to use the def and use nodes is here.

Drawing Plots and grids

The following constructors create 'compound' nodes in that the node returned has subnodes under it.

Grids and Patterns

Grids are useful as a background to plots, they consist of various straight, horizontal and vertical lines.

Since the lines in grids are defined by the endpoints of the lines, it does not make sense to apply a non-linear transform to them as the lines will remain straight and won't be transformed as they should.

Patterns are used to show the effect of transforms. Although they may be approximated by straight lines the points are intended to be close enough together to transform reasonably accurately.

Grid - The form with step uses the prevailing colour and thickness and the stepSize parameter defines the spacing between lines in local coordinates.

createSceneGrid:(stepSize:DF_
                    ,bb: SBoundary(PT)) -> %
addSceneGrid:(n:%,stepSize:DF,_
                     bb: SBoundary(PT)) -> %
grid 1

Grid - The form without the step size constructs a grid with:

  • narrow blue lines every 20 units
  • wide blue lines every 100 units
  • wide red lines every 200 units
createSceneGrid:(bb: SBoundary(PT)) -> %
addSceneGrid:(n:%,bb: SBoundary(PT)) -> %
grid 2

Pattern GRID - horizontal and vertical lines

Contruct a set of horizontal and vertical lines in the current clip boundary and current material with a spacing between lines given by the step parameter.

createScenePattern:_
  ("GRID"::Symbol,_
            step:NNI,bb: SBoundary(PT)) -> %
addScenePattern:_
  (n:%,"GRID"::Symbol,_
            step:NNI,bb: SBoundary(PT)) -> %
pattern 1

Pattern SIERPINSKI- Sierpinski fractel

Constructs a Sierpinski fractel. step parameter gives the level of subdivision.

createScenePattern:_
  ("SIERPINSKI"::Symbol,_
          level:NNI,bb: SBoundary(PT)) -> %
addScenePattern:_
  (n:%,"SIERPINSKI"::Symbol,_
          level:NNI,bb: SBoundary(PT)) -> %
pattern 2

Pattern 3 - HOUSE

createScenePattern:_
  ("HOUSE"::Symbol,_
          level:NNI,bb: SBoundary(PT)) -> %
addScenePattern:_
  (n:%,"HOUSE"::Symbol,_
          level:NNI,bb: SBoundary(PT)) -> %
 

Ruler

Creates a scale that can be used to provide numeric values for an axis:

  • ptype="HORIZONTAL"::Symbol: horizontal axis.
  • ptype="VERTICAL"::Symbol: vertical axis.
  • ptype="DEBTH"::Symbol: debth axis.
createSceneRuler:_
  (ptype:Symbol,_
          offset:PT,bb: SBoundary(PT)) -> %
addSceneRuler:_
   (n:%,ptype:Symbol,_
          offset:PT,bb: SBoundary(PT)) -> %
 

One Dimensional subspace in Two Dimensions

This represents 1 dimension (line - possibly curved) in 2 dimensions (plane) The line is approximated as end-to-end straight lines defined by a list of points. In theory a line has no width but in that case we would not see it so we give it a width given by the material node that is applicable in this part of the scene graph.

The plot is defined by a function and a range of values. There are various ways to define this function:

Where:
DF ==> DoubleFloat
PT ==> SPointCategory -- an instance of SPointCategory represents a point.

We can also create the plot using an indirect parameter. (parametric)

PPC is ParametricPlaneCurve(DF -> DF) which is created with curve(f1,f2)

where f1 and f2 are functions of type ComponentFunction, in this case DF -> DF

createPlot1Din2D: (f:DF -> PT,tRange:SEG,numPts:NNI) -> %
addPlot1Din2D: (n:%,f:DF -> PT,tRange:SEG,numPts:NNI) -> %
createPlot1Din2D: (DF -> DF,SEG,numPts:NNI) -> %
addPlot1Din2D: (n:%,DF -> DF,SEG,numPts:NNI) -> %
createPlot1Din2Dparametric: (PPC,SEG,numPts:NNI) -> %
addPlot1Din2Dparametric: (n:%,PPC,SEG,numPts:NNI) -> %

One Dimensional subspace in Three Dimensions

create a line (1D subspace) in 3D space. This represents 1 dimension (line - possibly curved) in 3 dimensions. In theory a line has no width but in that case we would not see it so we give it a width given by the material node that is applicable in this part of the scene graph.

Again there are various ways to define this function:
PCFUN is a function from float to point: DF -> PT
PSC ParametricSpaceCurve(DF -> DF) is created with curve(f1,f2,f3)
where f1,f2 and f3 are functions of type ComponentFunction, in this case DF -> DF

createPlot1Din3Dparametric: (PSC,SEG,numPts:NNI) -> %
addPlot1Din3Dparametric: (n:%,PSC,SEG,numPts:NNI) -> %
createPlot1Din3Dparametric: (PCFUN,SEG,numPts:NNI) -> %
addPlot1Din3Dparametric: (n:%,PCFUN,SEG,numPts:NNI) -> %

Two Dimensional subspace in Three Dimensions

create a surface (2D subspace) in 3D space

The surface is approximated by polygons which are represented by in indexed face set (IFS) node:

createPlot2Din3D: (ptFun:PSFUN,uSeg:SEG,vSeg:SEG,numPts:NNI) -> %
createPlot2Din3D: ((DF,DF) -> DF,SEG,SEG,numPts:NNI) -> %
addPlot2Din3D: (n:%,(DF,DF) -> DF,SEG,SEG,numPts:NNI) -> %
createPlot2Din3Dparametric: (PSFUN, SEG, SEG,numPts:NNI) -> %
addPlot2Din3Dparametric: (n:%,PSFUN, SEG, SEG,numPts:NNI) -> %
createPlot2Din3Dparametric: (PSF,SEG,SEG,numPts:NNI) -> %
addPlot2Din3Dparametric: (n:%,PSF,SEG,SEG,numPts:NNI) -> %

Arrows

Displays multiple arrows on the screen. This is represented by a list, each element in this list represents a single arrow, This is represented by a list containing the start and end points.

createSceneArrows:(line: List List PT,ls:NNI,le:NNI) -> %
addSceneArrows:(n:%,line: List List PT,ls:NNI,le:NNI) -> %

We can represent transforms using arrows in various ways. The following example displays the function 'fn' which maps each point to a point 50 units to its right.

DF ==> DoubleFloat
fn(x:SCartesian(2)):SCartesian(2) ==
   spnt(screenCoordX(x)$SCartesian(2) +50::DF,_
     screenCoordY(x)$SCartesian(2))$SCartesian(2)
view:= boxBoundary(sipnt(0,0)$SCartesian(2),_
            sipnt(1200,1000)$SCartesian(2))
sc := createSceneRoot(view)$Scene(SCartesian(2))
gd := addArrows2Din2D(sc,fn,_
       1..1000,1..1000,15)$Scene(SCartesian(2))
writeSvg(sc,"exampleArrow2.svg")

svg plot

Exporting the graphics

This scenegraph framework currently exports to the following file formats:

To export a scenegraph to one of these file formats use the following function calls:

Write an 'SVG' representation of node 'n' (usually the root node) to the filename supplied:

writeSvg:(n:%,filename:String) -> Void

Or we can do the same, but this version outputs all points using integer values, since the drawing width is usually normalised to be a 1000 units across this should give enough resolution and will make the file a lot smaller:

writeSvgQuantised:(n:%,filename:String) -> Void

Write an 'X3D' representation of node 'n' (usually the root node) to the filename supplied.

writeX3d:(n:%,filename:String) -> Void

Write a 'VRML' representation of node 'n' (usually the root node) to the filename supplied.

writeVRML:(n:%,filename:String) -> Void

Write an 'OBJ' (Wavefront) representation of node 'n' (usually the root node) to the filename supplied.

writeObj:(n:%,filename:String) -> Void

If we only want to create an XML structure without writing to a file we can use these functions:

create an XmlElement containing a 'SVG' representation of node 'n' and the nodes below it:

toSVG:(n:%,mat:MATERIAL,tran:TR,bb: SBoundary(PT)) -> XmlElement

Create an XmlElement containing a 'X3D' representation of node 'n' and the nodes below it:

toX3D:(n:%,mat:MATERIAL,tran:TR,bb: SBoundary(PT)) -> XmlElement

Creates .OBJ (Wavefront) structures from scenegraph tree structure called recursively for each node, so when called on root node in scenegraph all other nodes in the scenegraph will get called. When called the reference values should be empty or zero and when the function returns they will be set.

toObj:(n:%,ptLst: Reference List PT,_
    indexLst:Reference List List NNI,_
    indexNxt:Reference NNI,tran:TR,bb: SBoundary(PT)) -> Void

Compiling the code

This code is availible in FriCAS since FriCAS 1.1.1 but if you need to install a later version see page here.

Further Information


metadata block
see also:
Correspondence about this page

This site may have errors. Don't use for critical systems.

Copyright (c) 1998-2023 Martin John Baker - All rights reserved - privacy policy.