Axiom - Writing Geometry Structures

The page contains code to write the contents of a SubSpace(3,DoubleFloat) structure to a Wavefront .OBJ file. I have also included documentation below.

For documentation about related axiom domains and other structures like SubSpace see this page.

Overview

I would like to be able to output a draw 3D image to a standard 3D file format rather than the x-window. Axiom/Fricas does have the ability to write to 'pixmap','bitmap','postscript' and 'image' files, however most of these formats flattern the 3D geometry information to a 2D image or are quite out-of-date file formats.

I want a format which I can import into a 3D editor like blender. Also it must be able to output any geometry, either produced by draw/plot or makeObject or built from primitives. For instance so that a plot can be exported together with axes and grid.

I am looking at creating two graphics output writers (because they would have complimentary capabilities):

How to Use

We first create an .obj file as follows:

(1) -> )library EXP3D
   Export3D is now explicitly exposed in frame frame1
   Export3D will be automatically loaded when needed from
      /home/martin/EXP3D.NRLIB/EXP3D
(1) -> writeObj(subspace(makeObject(x*x-y*y,x=-1..1,y=-1..1)),"myfile.obj")
   Compiling function %B with type (DoubleFloat,DoubleFloat) ->
      DoubleFloat
                                                               Type: Void

For information about how to create other plots or geometry built from primitives see this tutorial.

This has created a file called myfile.obj in your active directory, we can now edit it using a 3D editor such as Blender.

blender graph

We can then start Blender (or your 3D editor of choice) and import the file (in this case myfile.obj).

We can then rotate, zoom, change its appearance, combine with other graphs, add scales or any other annotation required.

blender graph
blender graph

Write to .OBJ file

This code writes the contents of a SubSpace(3,DoubleFloat) structure to a Wavefront .OBJ file.

)abbrev package EXP3D Export3D
++ Author: Martin Baker
++ Date: June, 2010
++ Description:
++ This package provides support for exporting SubSpace and
++ ThreeSpace structures to files.

EF ==> Expression Float
SBF ==> SegmentBinding Float
DF ==> DoubleFloat
I    ==> Integer
PI   ==> PositiveInteger
NNI  ==> NonNegativeInteger
STR ==> String

Export3D(): with

  writeObj:(SubSpace(3,DoubleFloat),String) -> Void
    ++ writes 3D SubSpace to a file in Wavefront (.OBJ) format

 == add

  -- return list of indexes
  -- assumes subnodes are leaves containing index
  faceIndex(subSp: SubSpace(3,DoubleFloat)):List NNI ==
    faceIndexList:List NNI := []
    for poly in children(subSp) repeat
      faceIndexList := cons(extractIndex(poly),faceIndexList)
    reverse faceIndexList

  -- called if this component contains a single polygon
  -- write out face information for Wavefront (.OBJ) 3D file format
  -- one face per line, represented by list of vertex indexes
  writePolygon(f1:TextFile,curves: List SubSpace(3,DoubleFloat)):Void ==
    faceIndexList:List NNI := []
    for curve in curves repeat
      faceIndexList := append(faceIndexList,faceIndex(curve))
    -- write out face information for Wavefront (.OBJ) 3D file format
    -- one face per line, represented by list of vertex indexes
    s:String := "f "
    for i in faceIndexList repeat
      s:=concat(s,string(i))$String
      s:=concat(s," ")$String
    writeLine!(f1,s)

  -- called if this component contains a mesh, the mesh will be rendered
  -- as quad polygons.
  -- write out face information for Wavefront (.OBJ) 3D file format
  -- one face per line, represented by list of vertex indexes
  writeMesh(f1:TextFile,curves: List SubSpace(3,DoubleFloat)):Void ==
    meshIndexArray:List List NNI := []
    for curve in curves repeat
      -- write out face information for Wavefront (.OBJ) 3D file format
      -- one face per line, represented by list of vertex indexes
      meshIndexArray := cons(faceIndex(curve),meshIndexArray)
    meshIndexArray := reverse meshIndexArray
    rowLength := #meshIndexArray
    colLength := #(meshIndexArray.1)
    for i in 1..(rowLength-1) repeat
      for j in 1..(colLength-1) repeat
        --s1:String := concat["row ",string(i)," col ",string(j)]
        --writeLine!(f1,s1)
        s:String := concat["f ",string((meshIndexArray.i).j)," ",_
          string((meshIndexArray.(i+1)).j)," ",_
            string((meshIndexArray.(i+1)).(j+1))," ",_
              string((meshIndexArray.i).(j+1))]
        writeLine!(f1,s)

  -- this writes SubSpace geometry to Wavefront (.OBJ) 3D file format
  -- reqires SubSpace to contain 3 or 4 dimensional points over DoubleFloat
  -- to export a function plot try:
  -- writeObj(subspace(makeObject(x*x-y*y,x=-1..1,y=-1..1)),"myfile.obj")
  -- colour dimension is ignored
  -- no normals or texture data is generated
  writeObj(subSp: SubSpace(3,DoubleFloat), filename:String):Void ==
    f1:TextFile:=open(filename::FileName,"output")
    writeLine!(f1,"# mesh generated by axiom")
    -- write vertex data
    verts := pointData(subSp)
    for v in verts repeat
      #v < 3  => error "Can't write OBJ file from 2D points"
      writeLine!(f1,concat(["v ",unparse(convert(v.1)@InputForm)," ",_
                unparse(convert(v.2)@InputForm)," ",_
                   unparse(convert(v.3)@InputForm)])$String)
    for component in children(subSp) repeat
      curves := children(component)
      if #curves < 2 then
        sayTeX$Lisp "Can't write point or curve to OBJ file"
      --writeLine!(f1,"new component")
      if #curves > 1 then 
        if numberOfChildren(curves.1) = 1 then writePolygon(f1,curves)
        if numberOfChildren(curves.1) > 1 then writeMesh(f1,curves)
    close! f1

Acknowledgement: I have borrowed elements from gnuDraw here as suggested by Bill Page.

Write to X3D

There seem to be many structures in axiom to implement Open Inventor (IVNodeCategory, RenderTools, IVSimpleInnerNode, IVSeparator, IVGroup, IVCoordinate3, IVQuadMesh, IVIndexedLineSet, IVUtilities).

I can't find any documentation about using Open Inventor structures from Axiom, apart from the discussion on this thread:
http://lists.gnu.org/archive/html/axiom-developer/2002-11/msg00151.html

Other Options

I would like to do this because there are limitations in what can be done with the built-in 3D viewer and dedicated 3D editors (such as 'blender') are much more powerful (does it make sense that a computer algebra program also tries to be a 3D editor?). An additional advantage is that it would work on computers without x-window.

However I can't work out exactly how to do this. The options I am considering are:

 

Axiom/Fricas does have the ability to write to 'pixmap','bitmap','postscript' and 'image' files as follows:

(1) -> viewWriteAvailable()

   (1)  ["PIXMAP","BITMAP","POSTSCRIPT","IMAGE"]
                                                       Type: List(String)
(2) -> viewWriteDefault()

   (2)  []
                                                       Type: List(String)
(3) -> v := draw(x*x-y*y,x = -1..1,y= -1..1)
   Compiling function %B with type (DoubleFloat,DoubleFloat) ->
      DoubleFloat
   Transmitting data...

   (3)  ThreeDimensionalViewport: "-1*y^2+x^2"
                                           Type: ThreeDimensionalViewport
(4) -> write(v,"testDraw","image")

   (4)  "testDraw"
                                                             Type: String

This creates a directory 'testDraw.VIEW' containing 3 files:

data
image.bm
image.xpm

But I want a format which I can inport into blender.

Discussion

See these threads on FriCAS forum


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.