MODULE MakeRawCube EXPORTS Main; (* Creates a ".top" file for a cube whose faces are triangulated grids of N by N cells, as created by Triang.MakeGrid. The vertex coordinates are integers ranging from "(0,0,0)" to "(2N,2N,2N)". Cell corners have three even coordinates; cell centers have one even and two odd coordinates. *) IMPORT Oct, Map, LR3, Triang, Fmt, ParseParams, Process, Wr, Stdio, Thread; FROM Triang IMPORT Topology, Coords, OrgV; FROM Map IMPORT Arc; FROM Oct IMPORT Oprev, Flip; FROM Stdio IMPORT stderr; TYPE Options = RECORD gridOrder: CARDINAL; END; PROCEDURE Main() = BEGIN WITH o = GetOptions(), diag = MakeCubeTriang(o.gridOrder), top = Triang.MakeTopology(diag[0]), c = ComputeCoordinates(top, diag, o.gridOrder)^ DO Triang.Write("cube-" & Fmt.Int(o.gridOrder), top, c); END; END Main; PROCEDURE MakeCubeTriang(N: CARDINAL): ARRAY [0..5] OF Arc = (* Builds a cube from six triangulated grids. Returns a diagonal arc out of one corner from each face, on the outside of the cube. Face 0 is the bottom, faces 1..4 are the sides, face 5 is the top, as shown below. | +------+ | | | | | | | |5 | | +------+------+------+------+ | | | | | | | | | | | | | |1 |2 |3 |4 | | +------+------+------+------+ | | | | | | | |0 | | +------+ *) VAR face: ARRAY [0..5] OF ARRAY [0..7] OF Arc; diag: ARRAY [0..5] OF Arc; BEGIN FOR i := 0 TO 5 DO face[i] := Triang.MakeGrid(N, N); diag[i] := Oprev(face[i][0]); END; (* Glue faces: *) EVAL Triang.Glue(face[5][2], Flip(face[1][5]), N); EVAL Triang.Glue(face[5][4], Flip(face[2][5]), N); EVAL Triang.Glue(face[5][6], Flip(face[3][5]), N); EVAL Triang.Glue(face[5][0], Flip(face[4][5]), N); EVAL Triang.Glue(face[1][0], Flip(face[4][3]), N); EVAL Triang.Glue(face[2][0], Flip(face[1][3]), N); EVAL Triang.Glue(face[3][0], Flip(face[2][3]), N); EVAL Triang.Glue(face[4][0], Flip(face[3][3]), N); EVAL Triang.Glue(face[0][6], Flip(face[1][1]), N); EVAL Triang.Glue(face[0][4], Flip(face[2][1]), N); EVAL Triang.Glue(face[0][2], Flip(face[3][1]), N); EVAL Triang.Glue(face[0][0], Flip(face[4][1]), N); RETURN diag END MakeCubeTriang; PROCEDURE ComputeCoordinates( READONLY top: Topology; READONLY diag: ARRAY [0..5] OF Arc; N: CARDINAL; ): REF Coords = (* Computes the vertex coordinates, assuming "diag[i]" is a diagonal arc out of a corner of face "i", numbered and placed as shown above. The coordinates will range from 0 to "2*N". *) TYPE Z3 = ARRAY [0..2] OF INTEGER; BEGIN WITH r = NEW(REF Coords, top.NV), c = r^, sz = 2*N DO PROCEDURE SetFaceCoords( a: Arc; READONLY o, dx, dy: Z3; ) = (* Sets the vertex coordinates in a grid, given a northeast pointing arc "a" out of its southwest corner. Assumes the origin of "a" is at the point "o", and the side vectors of the grid are "2*N*dx" and "2*N*dy". *) PROCEDURE SetVertexCoords(e: Arc; x, y: CARDINAL) = BEGIN c[OrgV(e).num] := LR3.T{ FLOAT(o[0] + dx[0]*x + dy[0]*y, LONGREAL), FLOAT(o[1] + dx[1]*x + dy[1]*y, LONGREAL), FLOAT(o[2] + dx[2]*x + dy[2]*y, LONGREAL) }; END SetVertexCoords; BEGIN Triang.EnumGridVertices(Oprev(a), N, N, SetVertexCoords) END SetFaceCoords; BEGIN SetFaceCoords(diag[0], Z3{00, 00, 00}, Z3{00, +1, 00}, Z3{+1, 00, 00}); SetFaceCoords(diag[1], Z3{sz, 00, 00}, Z3{00, +1, 00}, Z3{00, 00, +1}); SetFaceCoords(diag[2], Z3{sz, sz, 00}, Z3{-1, 00, 00}, Z3{00, 00, +1}); SetFaceCoords(diag[3], Z3{00, sz, 00}, Z3{00, -1, 00}, Z3{00, 00, +1}); SetFaceCoords(diag[4], Z3{00, 00, 00}, Z3{+1, 00, 00}, Z3{00, 00, +1}); SetFaceCoords(diag[5], Z3{sz, 00, sz}, Z3{00, +1, 00}, Z3{-1, 00, 00}); END; RETURN r END END ComputeCoordinates; PROCEDURE GetOptions (): Options = <* FATAL Thread.Alerted, Wr.Failure *> VAR o: Options; BEGIN WITH pp = NEW(ParseParams.T).init(stderr) DO TRY pp.getKeyword("-gridOrder"); o.gridOrder := pp.getNextInt(1, 100); pp.finish(); EXCEPT | ParseParams.Error => Wr.PutText(stderr, "Usage: MakeRawCube -gridOrder \n"); Process.Exit (1); END END; RETURN o END GetOptions; BEGIN Main(); END MakeRawCube.