Axiom - Geometry Structures Tutorial

There is some tutorial stuff here:

But it not quite what I need so I have been putting together this information gathered from what I can work out from the source code. Since I would like to use ThreeSpace and related domains to output graphical information to a file I need to understand them.

ThreeSpace

space.spad

ThreeSpace is a domain that holds various geometry primitives. It holds separate lists of:

So lets create the various geometry types and see what we can do with them.

Points

We can define:

First we can create some 3 dimensional points to work with, we can do this using the point function (defined in the Point domain), we could define the coordinates using Float values but I have used DoubleFloat here because that will be needed later when we call makeViewport3D to display the results:

(1) -> p1 := point[0.1@DoubleFloat,0.2@DoubleFloat,0.3@DoubleFloat]
   (1)  [0.1,0.2,0.30000000000000004]
                                                 Type: Point(DoubleFloat)
(2) -> p2 := point[0.3@DoubleFloat,0.4@DoubleFloat,0.5@DoubleFloat]

   (2)  [0.30000000000000004,0.4,0.5]
                                                 Type: Point(DoubleFloat)
(3) -> p3 := point[0.2@DoubleFloat,0.4@DoubleFloat,0.6@DoubleFloat]

   (3)  [0.2,0.4,0.6000000000000001]
                                                 Type: Point(DoubleFloat)

We can now put the points into ThreeSpace, we can do this using a different point function (this time the point function defined in ThreeSpace domain):

(4) -> ts1 := point(p1)

   (4)  3-Space with 1 component
                                            Type: ThreeSpace(DoubleFloat)

We can always check what our ThreeSpace contains by using its objects procedure:

(5) -> objects(ts1)

   (5)  [points= 1,curves= 0,polygons= 0,constructs= 0]
Type: Record(points: NonNegativeInteger,curves: NonNegativeInteger,
             polygons: NonNegativeInteger,constructs: NonNegativeInteger)

We can add the other points to our ThreeSpace as follows:

(6) -> point(ts1,p2)

   (6)  3-Space with 2 components
                                            Type: ThreeSpace(DoubleFloat)
(7) -> point(ts1,p3)

   (7)  3-Space with 3 components
                                            Type: ThreeSpace(DoubleFloat)

To see these three points in an x-window we use makeViewport3D as follows:

(8) -> makeViewport3D(ts1,[toScale(true)])

   Transmitting data...

  (8)ThreeDimensionalViewport: "FriCAS3D"
                   Type: ThreeDimensionalViewport

This brings up the x-window on the right, we can just see the three points in the window.

x-window snapshot 1

We can add points of a different dimension, in this case 2, but I suggest you don't try this at home as it will prevent makeViewport3D from working, it does not work with mixed dimensions as you can see here:

(8) -> p4 := point[0.1@DoubleFloat,0.5@DoubleFloat]


   (8)  [0.1,0.5]
                                                     Type: Point(DoubleFloat)
(9) -> point(ts1,p4)


   (9)  3-Space with 4 components
                                                Type: ThreeSpace(DoubleFloat)
(10) -> makeViewport3D(ts1,[toScale(true)])

   Transmitting data...

   >> Error detected within library code:
   All points should have the same dimension

Curves

Now lets add a curve, we can either create it from a list of points, or avoid point definitions by using a list of list of floats, here we will use explicit point definitions:

(9) ->p5 := point[0.1@DoubleFloat,0.9@DoubleFloat,0.3@DoubleFloat]
   (9)  [0.1,0.9,0.30000000000000004]
                                                 Type: Point(DoubleFloat)
(10) ->p6 := point[0.2@DoubleFloat,0.1@DoubleFloat,0.5@DoubleFloat]
   (10)  [0.2,0.1,0.5]
                                                 Type: Point(DoubleFloat)
(11) ->p7 := point[0.3@DoubleFloat,0.9@DoubleFloat,0.6@DoubleFloat]
   (11)  [0.30000000000000004,0.9,0.6000000000000001]
                                                 Type: Point(DoubleFloat)
(12) ->p8 := point[0.4@DoubleFloat,0.1@DoubleFloat,0.5@DoubleFloat]
   (12)  [0.4,0.1,0.5]
                                                 Type: Point(DoubleFloat)
(13) ->p9 := point[0.5@DoubleFloat,0.9@DoubleFloat,0.6@DoubleFloat]

   (13)  [0.5,0.9,0.6000000000000001]
                                                 Type: Point(DoubleFloat)
(14) ->curve(ts1,[p5,p6,p7,p8,p9])

   (14)  3-Space with 4 components
                                            Type: ThreeSpace(DoubleFloat)
(15) ->objects(ts1)

   (15)  [points= 3,curves= 1,polygons= 0,constructs= 0]
Type: Record(points: NonNegativeInteger,curves: NonNegativeInteger,_
       polygons: NonNegativeInteger,constructs: NonNegativeInteger)
(16) ->makeViewport3D(ts1,[toScale(true)])
   Transmitting data...

   (16)  ThreeDimensionalViewport: "FriCAS3D"
                                           Type: ThreeDimensionalViewport

This produces the output shown on the right:

The 'curve' produces a set of lines joining up the points.

We could have made this a 'closed curve', that is include a line from the last point back to the first point by changing the function call from:
curve(ts1,[p5,p6,p7,p8,p9])
to
closedCurve(ts1,[p5,p6,p7,p8,p9])

snapshot 2

Polygons

Polygons are similar to curves except the points are in a plane and the polygon is always closed. Polygons are often used to construct a surface so the plane inside the polygon can be drawn filled in with colour:

p10 := point[0.1@DoubleFloat,0.9@DoubleFloat,0.9@DoubleFloat]

   (17)  [0.1,0.9,0.9]
                                                 Type: Point(DoubleFloat)
p11 := point[0.2@DoubleFloat,0.1@DoubleFloat,0.9@DoubleFloat]

   (18)  [0.2,0.1,0.9]
                                                 Type: Point(DoubleFloat)
p12 := point[0.3@DoubleFloat,0.5@DoubleFloat,0.9@DoubleFloat]

   (19)  [0.30000000000000004,0.5,0.9]
                                                 Type: Point(DoubleFloat)
p13 := point[0.4@DoubleFloat,0.1@DoubleFloat,0.9@DoubleFloat]

   (20)  [0.4,0.1,0.9]
                                                 Type: Point(DoubleFloat)
p14 := point[0.5@DoubleFloat,0.9@DoubleFloat,0.9@DoubleFloat]

   (21)  [0.5,0.9,0.9]
                                                 Type: Point(DoubleFloat)
polygon(ts1,[p10,p11,p12,p13,p14])

   (22)  3-Space with 5 components
                                            Type: ThreeSpace(DoubleFloat)
objects(ts1)

   (23)  [points= 3,curves= 1,polygons= 1,constructs= 0]
Type: Record(points: NonNegativeInteger,curves: NonNegativeInteger,
              polygons: NonNegativeInteger,constructs: NonNegativeInteger)
makeViewport3D(ts1,[toScale(true)])

   Transmitting data...

   (24)  ThreeDimensionalViewport: "FriCAS3D"
                                           Type: ThreeDimensionalViewport

The polygon is the purple line here:

snapshot 3

Mesh

A mesh can represent a complete curved surface. This in made up of an array of squares which can be defined by a two dimensional (list of list) array of points. This is very useful for producing graphical representations of functions.

p15 := point[0.1@DoubleFloat,0.1@DoubleFloat,0.9@DoubleFloat]

   (25)  [0.1,0.1,0.9]
                                                     Type: Point(DoubleFloat)
p16 := point[0.4@DoubleFloat,0.1@DoubleFloat,0.8@DoubleFloat]

   (26)  [0.4,0.1,0.8]
                                                 Type: Point(DoubleFloat)
p17 := point[0.7@DoubleFloat,0.1@DoubleFloat,0.7@DoubleFloat]

   (27)  [0.7000000000000001,0.1,0.7000000000000001]
                                                 Type: Point(DoubleFloat)
p18 := point[0.1@DoubleFloat,0.4@DoubleFloat,0.8@DoubleFloat]

   (28)  [0.1,0.4,0.8]
                                                 Type: Point(DoubleFloat)
p19 := point[0.4@DoubleFloat,0.4@DoubleFloat,0.8@DoubleFloat]

   (29)  [0.4,0.4,0.8]
                                                 Type: Point(DoubleFloat)
p20 := point[0.7@DoubleFloat,0.4@DoubleFloat,0.8@DoubleFloat]

   (30)  [0.7000000000000001,0.4,0.8]
                                                 Type: Point(DoubleFloat)
p21 := point[0.1@DoubleFloat,0.7@DoubleFloat,0.7@DoubleFloat]

   (31)  [0.1,0.7000000000000001,0.7000000000000001]
                                                 Type: Point(DoubleFloat)
p22 := point[0.4@DoubleFloat,0.7@DoubleFloat,0.8@DoubleFloat]


   (32)  [0.4,0.7000000000000001,0.8]
                                                 Type: Point(DoubleFloat)
p23 := point[0.7@DoubleFloat,0.7@DoubleFloat,0.9@DoubleFloat]


   (33)  [0.7000000000000001,0.7000000000000001,0.9]
                                                 Type: Point(DoubleFloat)
mesh(ts1,[[p15,p16,p17],[p18,p19,p20],[p21,p22,p23]],true,true)


   (34)  3-Space with 6 components
                                            Type: ThreeSpace(DoubleFloat)
objects(ts1)


   (35)  [points= 3,curves= 1,polygons= 1,constructs= 1]
Type: Record(points: NonNegativeInteger,curves: NonNegativeInteger,
      polygons: NonNegativeInteger,constructs: NonNegativeInteger)
makeViewport3D(ts1,[toScale(true)])

   Transmitting data...

   (36)  ThreeDimensionalViewport: "FriCAS3D"
                                           Type: ThreeDimensionalViewport

The mesh is the blue grid here:

notice that the mesh is listed as a 'construct' when listed by the objects function.

snapshot 4

Internal structure of ThreeSpace

We have now put various point, curve, polygon and mesh components into our ThreeSpace instance: ts1, this is stored as a record as follows:

Rep := Record( subspaceField:SUBSPACE, compositesField:L SUBSPACE, _
rep3DField:REP3D, objectsField:OBJ3D, _
converted:B)

where:

REP3D ==> Record(lp:L POINT,llliPt:L L L NNI, llProp:L L PROP, lProp:L PROP)
so this holds the main geometric data.

OBJ3D ==> Record(points:NNI, curves:NNI, polygons:NNI, constructs:NNI)
this gives the number of each type of component.

We can get to this data with the following calls:

(42) -> components(ts1)

   (42)
   [3-Space with 1 component, 3-Space with 1 component,
    3-Space with 1 component, 3-Space with 1 component,
    3-Space with 1 component, 3-Space with 1 component]
                                       Type: List(ThreeSpace(DoubleFloat))
(43) -> composites(ts1)

   (43)  []
                                       Type: List(ThreeSpace(DoubleFloat))
(44) -> subspace(ts1)

   (44)  3-Space with depth of 3 and 6 components
                                             Type: SubSpace(3,DoubleFloat)

These components can have the following boolean properties:

we can test the property values with the llprop function:

(38) -> llprop(ts1)

   (38)
   [[Component is not closed, not solid], [Component is not closed, not solid],
    [Component is not closed, not solid], [Component is not closed, not solid],
    [Component is not closed, not solid,Component is not closed, not solid],

     [Component is closed, not solid, Component is closed, not solid,
      Component is closed, not solid]
     ]
                                  Type: List(List(SubSpaceComponentProperty))

Solid Mesh using SubSpaceComponentProperty

In order to display the mesh so that it looks solid (as opposed to the wireframe view we have see so far) we need to make three changes from what we have been doing until now:

sscp := new()$SubSpaceComponentProperty

   (41)  Component is not closed, not solid
                                          Type: SubSpaceComponentProperty
solid(sscp,true)

   (42)  true
                                                            Type: Boolean
close(sscp,true)

   (43)  true
                                                            Type: Boolean
p25 := point[0.1@DoubleFloat,0.1@DoubleFloat,0.9@DoubleFloat,1.0@DoubleFloat]

   (44)  [0.1,0.1,0.9,1.0]
                                                 Type: Point(DoubleFloat)
p26 := point[0.4@DoubleFloat,0.1@DoubleFloat,0.8@DoubleFloat,1.0@DoubleFloat]

   (45)  [0.4,0.1,0.8,1.0]
                                                 Type: Point(DoubleFloat)
p27 := point[0.7@DoubleFloat,0.1@DoubleFloat,0.7@DoubleFloat,1.0@DoubleFloat]

   (46)  [0.7000000000000001,0.1,0.7000000000000001,1.0]
                                                 Type: Point(DoubleFloat)
p28 := point[0.1@DoubleFloat,0.4@DoubleFloat,0.8@DoubleFloat,1.0@DoubleFloat]

   (47)  [0.1,0.4,0.8,1.0]
                                                 Type: Point(DoubleFloat)
p29 := point[0.4@DoubleFloat,0.4@DoubleFloat,0.8@DoubleFloat,1.0@DoubleFloat]

   (48)  [0.4,0.4,0.8,1.0]
                                                 Type: Point(DoubleFloat)
p30 := point[0.7@DoubleFloat,0.4@DoubleFloat,0.8@DoubleFloat,1.0@DoubleFloat]

   (49)  [0.7000000000000001,0.4,0.8,1.0]
                                                 Type: Point(DoubleFloat)
p31 := point[0.1@DoubleFloat,0.7@DoubleFloat,0.7@DoubleFloat,1.0@DoubleFloat]

   (50)  [0.1,0.7000000000000001,0.7000000000000001,1.0]
                                                 Type: Point(DoubleFloat)
p32 := point[0.4@DoubleFloat,0.7@DoubleFloat,0.8@DoubleFloat,1.0@DoubleFloat]

   (51)  [0.4,0.7000000000000001,0.8,1.0]
                                                 Type: Point(DoubleFloat)
p33 := point[0.7@DoubleFloat,0.7@DoubleFloat,0.9@DoubleFloat,1.0@DoubleFloat]

   (52)  [0.7000000000000001,0.7000000000000001,0.9,1.0]
                                                 Type: Point(DoubleFloat)
ts2 := point(p25)
   (53)  3-Space with 1 component
                                            Type: ThreeSpace(DoubleFloat)
vp:=makeViewport3D(ts2,[toScale(true)])

   Transmitting data...

   (55)  ThreeDimensionalViewport: "FriCAS3D"
                                           Type: ThreeDimensionalViewport
drawStyle(vp,"shade")

                                                               Type: Void

We can now see the mesh as a 'solid' surface:

snapshot 5

Displaying Functions and Parametric Equations Graphically.

Since axiom is a mathematics program its important to be able to create a mesh from equations, or a function, or parametrically.

ts3 := makeObject((x*x-y*y)/10,x=-10..10,y=-10..10)

   Compiling function %B with type (DoubleFloat,DoubleFloat) ->
      DoubleFloat

   (57)  3-Space with 1 component
                                             Type: ThreeSpace(DoubleFloat)
vp:=makeViewport3D(ts3,[toScale(true)])

   Transmitting data...

   (58)  ThreeDimensionalViewport: "FriCAS3D"
                                            Type: ThreeDimensionalViewport
drawStyle(vp,"shade")
                                                                Type: Void

This produces the output here:

The makeObject and makeViewport3D calls can be replaced by a single call to the 'draw' function. The draw function is well documented elsewhere. In many cases 'makeObject' is available with the same parameters as 'draw' so refer to the draw documentation for details.

snapshot 6

SubSpace

newpoint.spad

SubSpace stores geometry information so there is some overlap between SubSpace and ThreeSpace in that they are designed to hold the same kinds of geometry structures. SubSpace is a tree structure where the leaves are points, it does not hold different primitives like ThreeSpace (which has Points,Curves,Polygons and Meshes). In subSpace the primitive is implied by the number of dimensions.

We can covert out geometric structure between the two structures using:

The point data is indexed so if a given point is the vertex of several polygons (which will happen frequently because surfaces are drawn as joining polygons) then we only define the point once, in the root. The leaf nodes only need to specify the point using its index.

The points are read by calling dataList on the root.

susp2 := subspace(ts2)
   (61)  3-Space with depth of 3 and 2 components
                                           Type: SubSpace(3,DoubleFloat)
pointData(susp2)

   (62)
   [[0.1,0.1,0.9,1.0], [0.1,0.1,0.9,1.0], [0.4,0.1,0.8,1.0],
    [0.7000000000000001,0.1,0.7000000000000001,1.0], [0.1,0.4,0.8,1.0],
    [0.4,0.4,0.8,1.0], [0.7000000000000001,0.4,0.8,1.0],               
    [0.1,0.7000000000000001,0.7000000000000001,1.0],                   
    [0.4,0.7000000000000001,0.8,1.0],                                  
    [0.7000000000000001,0.7000000000000001,0.9,1.0]]                   
                                           Type: List(Point(DoubleFloat))
extractIndex(susp2)

   (63)  0
                                                     Type: NonNegativeInteger
extractProperty(susp2)                                                       
                                                                             

   (64)  Component is not closed, not solid
                                          Type: SubSpaceComponentProperty
numberOfChildren(susp2)

   (65)  2
                                                    Type: PositiveInteger
children(susp2)

   (66)
   [3-Space with depth of 2 and 1 component,
    3-Space with depth of 2 and 3 components]
                                      Type: List(SubSpace(3,DoubleFloat))
c1 := child(susp2,1)


   (67)  3-Space with depth of 2 and 1 component
                                            Type: SubSpace(3,DoubleFloat)
c2 := child(susp2,2)


   (68)  3-Space with depth of 2 and 3 components
                                            Type: SubSpace(3,DoubleFloat)
extractProperty(c1)


   (69)  Component is not closed, not solid
                                          Type: SubSpaceComponentProperty
extractIndex(c1)


   (70)  0
                                                 Type: NonNegativeInteger
extractProperty(c2)


   (71)  Component is closed, solid
                                          Type: SubSpaceComponentProperty
extractIndex(c2)


   (72)  0
                                                 Type: NonNegativeInteger
children(c1)


   (73)  [3-Space with depth of 1 and 1 component]
                                     Type: List(SubSpace(3,DoubleFloat))
children(c2)


   (74)
   [3-Space with depth of 1 and 3 components,
    3-Space with depth of 1 and 3 components,
    3-Space with depth of 1 and 3 components]
                                      Type: List(SubSpace(3,DoubleFloat))
c11 := child(c1,1)


   (75)  3-Space with depth of 1 and 1 component
                                            Type: SubSpace(3,DoubleFloat)
c111 := child(c11,1)


   (76)  3-Space with depth of 0 and 0 components
                                            Type: SubSpace(3,DoubleFloat)
extractIndex(c111)


   (77)  1
                                                    Type: PositiveInteger
(78) ->

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.