MODULE SPMakeTriang EXPORTS Main; (* Creates a triangulation and writes it to disk *) IMPORT SPTriang; IMPORT ParseParams, LR3, Random; IMPORT FileWr, OSError, Thread, Wr, Process; FROM SPTriang IMPORT BuildInc; FROM Stdio IMPORT stderr; (* Creates a triangulation for testing purposes. The trangulation can be a standard one (a regular tetrahedron, a regular icosahedron, and a deformed octahedron), or the Delaunay triangulation of N random sites on the sphere. *) <* FATAL Thread.Alerted, Wr.Failure, OSError.E *> TYPE Options = RECORD outName: TEXT; nSites: CARDINAL; tetrahedron: BOOLEAN; octahedron: BOOLEAN; icosahedron: BOOLEAN; END; TYPE Site = SPTriang.Site; PROCEDURE Main() = BEGIN WITH o = GetOptions(), s = MakeSites(o.nSites, o.tetrahedron, o.octahedron, o.icosahedron)^, e = BuildInc(s), tri = SPTriang.BuildTables(e), wr = FileWr.Open(o.outName & ".tri") DO SPTriang.Write(wr, tri); Wr.Close(wr) END END Main; PROCEDURE MakeSites( n: CARDINAL; tetrahedron: BOOLEAN; octahedron: BOOLEAN; icosahedron: BOOLEAN; ): REF ARRAY OF REF Site = (* Creates an array of sites *) CONST IcoA = 1.6180339887498948482d0; IcoB = 1.0d0; BEGIN WITH rs = NEW(REF ARRAY OF REF Site, n), s = rs^, rand = NEW(Random.Default).init(fixed := TRUE) DO FOR i := 0 TO LAST(s) DO s[i] := NEW(REF Site); s[i].num := i; WITH c = s[i].c DO IF tetrahedron THEN CASE i OF | 00 => c[0] := +1.0d0; c[1] := +1.0d0; c[2] := +1.0d0; | 01 => c[0] := -1.0d0; c[1] := -1.0d0; c[2] := +1.0d0; | 02 => c[0] := +1.0d0; c[1] := -1.0d0; c[2] := -1.0d0; | 03 => c[0] := -1.0d0; c[1] := +1.0d0; c[2] := -1.0d0; ELSE <* ASSERT FALSE *> END ELSIF octahedron THEN CASE i OF | 00 => c[0] := +1.0d0; c[1] := +0.2d0; c[2] := -0.2d0; | 01 => c[0] := -1.0d0; c[1] := +0.2d0; c[2] := -0.2d0; | 02 => c[0] := -0.2d0; c[1] := +1.0d0; c[2] := +0.2d0; | 03 => c[0] := -0.2d0; c[1] := -1.0d0; c[2] := +0.2d0; | 04 => c[0] := +0.2d0; c[1] := -0.2d0; c[2] := +1.0d0; | 05 => c[0] := +0.2d0; c[1] := -0.2d0; c[2] := -1.0d0; ELSE <* ASSERT FALSE *> END ELSIF icosahedron THEN CASE i OF | 00 => c[0] := 0.0d0; c[1] := +IcoA; c[2] := +IcoB; | 01 => c[0] := 0.0d0; c[1] := +IcoA; c[2] := -IcoB; | 02 => c[0] := +IcoA; c[1] := -IcoB; c[2] := 0.0d0; | 03 => c[0] := -IcoA; c[1] := -IcoB; c[2] := 0.0d0; | 04 => c[0] := +IcoB; c[1] := 0.0d0; c[2] := +IcoA; | 05 => c[0] := +IcoB; c[1] := 0.0d0; c[2] := -IcoA; | 06 => c[0] := 0.0d0; c[1] := -IcoA; c[2] := +IcoB; | 07 => c[0] := 0.0d0; c[1] := -IcoA; c[2] := -IcoB; | 08 => c[0] := -IcoB; c[1] := 0.0d0; c[2] := +IcoA; | 09 => c[0] := -IcoB; c[1] := 0.0d0; c[2] := -IcoA; | 10 => c[0] := +IcoA; c[1] := +IcoB; c[2] := 0.0d0; | 11 => c[0] := -IcoA; c[1] := +IcoB; c[2] := 0.0d0; ELSE <* ASSERT FALSE *> END ELSE REPEAT c[0] := 2.0d0*rand.longreal() - 1.0d0; c[1] := 2.0d0*rand.longreal() - 1.0d0; c[2] := 2.0d0*rand.longreal() - 1.0d0; UNTIL c[0]*c[0] + c[1]*c[1] + c[2]*c[2] <= 1.0d0; (* c[0]:= (c[0] + 1.0d0)*(c[0] + 1.0d0)*(c[0] + 1.0d0)/4.0d0 - 1.0d0; *) END; c := LR3.Dir(c) END; END; RETURN rs END END MakeSites; PROCEDURE GetOptions (): Options = VAR o: Options; <* FATAL Wr.Failure, Thread.Alerted *> BEGIN TRY WITH pp = NEW(ParseParams.T).init(stderr) DO pp.getKeyword("-outName"); o.outName := pp.getNext(); IF pp.keywordPresent("-tetrahedron") THEN o.nSites := 4; o.tetrahedron := TRUE; o.octahedron := FALSE; o.icosahedron := FALSE; ELSIF pp.keywordPresent("-octahedron") THEN o.nSites := 6; o.tetrahedron := FALSE; o.octahedron := TRUE; o.icosahedron := FALSE; ELSIF pp.keywordPresent("-icosahedron") THEN o.nSites := 12; o.tetrahedron := FALSE; o.octahedron := FALSE; o.icosahedron := TRUE; ELSE pp.getKeyword("-nSites"); o.nSites := pp.getNextInt(4, 100000); o.tetrahedron := FALSE; o.octahedron := FALSE; o.icosahedron := FALSE; END; pp.finish(); END EXCEPT | ParseParams.Error => Wr.PutText(stderr, "Usage: SPMakeTriang \\\n"); Wr.PutText(stderr, " -outName NAME \\\n"); Wr.PutText(stderr, " [ -icosahedron | -octahedron | -nSites NUM ] \n"); Process.Exit (1); END; RETURN o END GetOptions; BEGIN Main() END SPMakeTriang.