\documentclass{article}
\usepackage{axiom}
\begin{document}
\title{\$SPAD/src/algebra/export3D}
\author{Martin Baker}
\maketitle
\begin{abstract}
\end{abstract}
\eject
\tableofcontents
\eject
\section{package GCDBAS GcdBasis}
<<package EXP3D Export3D>>=

)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)

  toString(d : DoubleFloat) : String ==
      unparse(convert(d)@InputForm)

  -- 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 ", toString(v.1), " ",_
                 toString(v.2), " ", toString(v.3)])$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

@
\end{document}
