-- File: PredefSweepsImpl.mesa
-- Last edited by Bier on December 18, 1982 1:35 am
-- Author: Eric Bier on July 1, 1982 10:13 pm
-- Contents: A cube, a cylinder, a cone, a sphere and a torus are created at load time and made available

DIRECTORY
 PredefSweeps,
 RealFns,
 SV2d,
 SVPolygon2d,
 SweepGeometry;

PredefSweepsImpl: PROGRAM
IMPORTS RealFns, SVPolygon2d, SweepGeometry
EXPORTS PredefSweeps =

BEGIN

RevoluteMesh: TYPE = REF RevoluteMeshRecord;
RevoluteMeshRecord: TYPE = SweepGeometry.RevoluteMeshRecord;
LinearMesh: TYPE = REF LinearMeshRecord;
LinearMeshRecord: TYPE = SweepGeometry.LinearMeshRecord;
ToroidalMesh: TYPE = REF ToroidalMeshRecord;
ToroidalMeshRecord: TYPE = SweepGeometry.ToroidalMeshRecord;
Polygon: TYPE = REF PolygonObj;
PolygonObj: TYPE = SV2d.PolygonObj;
Path: TYPE = REF PathObj;
PathObj: TYPE = SV2d.PathObj;
linesOfLatitude: NAT ← 8;
linesOfLongitude: NAT ← 8;

CreateSphere: PUBLIC PROC [r: REAL] RETURNS [RevoluteMesh] = {
-- generate a semi-circle in the x-y plane with 10 points where the end two points are on the y axis
 x, y: REAL;
 path: Path ← SVPolygon2d.CreatePath[linesOfLatitude];
 theta, deltaTheta: REAL;
 SVPolygon2d.PutPathPoint[path, 0, [0,r]];
 theta ← 90.0;
 deltaTheta ← 180.0/(linesOfLatitude - 1); -- Nat to float?
FOR i: NAT IN [2..linesOfLatitude-1] DO
  theta ← theta - deltaTheta;
  x ← r*RealFns.CosDeg[theta];
  y ← r*RealFns.SinDeg[theta];
  SVPolygon2d.PutPathPoint[path, i-1, [x,y]];
ENDLOOP;
 SVPolygon2d.PutPathPoint[path, linesOfLatitude-1, [0,-r]];
RETURN[SweepGeometry.RevoluteSweep[path, linesOfLongitude]];
};

CreateCube: PUBLIC PROC [side: REAL] RETURNS [LinearMesh] = {
 pos, neg: REAL;
 poly: Polygon ← SVPolygon2d.CreatePoly[4];
 pos ← side*(0.5);
 neg ← side*(-0.5);
 poly ← SVPolygon2d.PutPolyPoint[poly, 0, [neg,pos]];
 poly ← SVPolygon2d.PutPolyPoint[poly, 1, [pos,pos]];
 poly ← SVPolygon2d.PutPolyPoint[poly, 2, [pos,neg]];
 poly ← SVPolygon2d.PutPolyPoint[poly, 3, [neg,neg]];
RETURN[SweepGeometry.LinearSweep[poly, pos, neg]];
 };

CreateFullCylinder: PUBLIC PROC [r, h: REAL] RETURNS [RevoluteMesh] = {
 path: Path ← SVPolygon2d.CreatePath[linesOfLatitude];
 height, deltaH: REAL;
 height ← h/2.0;
 deltaH ← h/(linesOfLatitude - 1);
 SVPolygon2d.PutPathPoint[path, 0, [r,height]];
  -- make sure the endpoints are as accurate as possible
 SVPolygon2d.PutPathPoint[path, linesOfLatitude-1, [r,-height]];
FOR i: NAT IN [2..linesOfLatitude-1] DO
  height ← height - deltaH;
  SVPolygon2d.PutPathPoint[path, i-1, [r,height]];
ENDLOOP;
RETURN[SweepGeometry.RevoluteSweep[path, linesOfLongitude]];
 };

CreateCylinder: PUBLIC PROC [r, h: REAL] RETURNS [RevoluteMesh] = {
 path: Path ← SVPolygon2d.CreatePath[2];
 height: REAL ← h/2.0;
 SVPolygon2d.PutPathPoint[path, 0, [r,height]];
 SVPolygon2d.PutPathPoint[path, 1, [r,-height]];
RETURN[SweepGeometry.RevoluteSweep[path, linesOfLongitude]];
 };

CreateCone: PUBLIC PROC [r, h: REAL] RETURNS [RevoluteMesh] = {
 path: Path ← SVPolygon2d.CreatePath[linesOfLatitude];
 height, deltaH, x, deltaX: REAL;
 height ← h;
 deltaH ← h/(linesOfLatitude - 1);
 x ← 0;
 deltaX ← r/(linesOfLatitude - 1);
-- generate a cone pointing up with the center of its circular base at the origin of the local cs
 SVPolygon2d.PutPathPoint[path, 0, [0,h]]; -- top is on the y axis;
 SVPolygon2d.PutPathPoint[path, linesOfLatitude-1, [r,0]]; -- base is on the xz plane
FOR i: NAT IN [2..linesOfLatitude-1] DO
  height ← height - deltaH;
  x ← x + deltaX;
  SVPolygon2d.PutPathPoint[path, i-1, [x,height]];
ENDLOOP;
RETURN[SweepGeometry.RevoluteSweep[path, linesOfLongitude]];
 };


CreateTorus: PUBLIC PROC [rBig, rCross: REAL] RETURNS [ToroidalMesh] = {
 poly: Polygon ← SVPolygon2d.CreatePoly[linesOfLatitude];
-- just define the translated circle which is the torus's cross section (see full cylinder for help)
 alpha, deltaAlpha, sin, cos, x, y: REAL; -- the cross section circle
 alpha ← 0;
 deltaAlpha ← -360/linesOfLatitude; -- negative because ToroidalSweep assumes clockwise
 poly ← SVPolygon2d.PutPolyPoint[poly, 0, [rBig+rCross,0]];
FOR i: NAT IN[2..linesOfLatitude] DO
  alpha ← alpha + deltaAlpha;
  sin ← RealFns.SinDeg[alpha];
  cos ← RealFns.CosDeg[alpha];
  x ← rBig + rCross*cos;
  y ← rCross*sin;
  poly ← SVPolygon2d.PutPolyPoint[poly, i-1, [x,y]];
ENDLOOP;
RETURN[SweepGeometry.ToroidalSweep[poly, linesOfLongitude]];
 };


GetUnitSphere: PUBLIC PROC RETURNS [RevoluteMesh] = {
RETURN[CreateSphere[1.0]]
 };
GetUnitCube: PUBLIC PROC RETURNS [LinearMesh] = {
RETURN[CreateCube[2.0]]
 };
GetUnitCylinder: PUBLIC PROC RETURNS [RevoluteMesh] = {
RETURN[CreateFullCylinder[1.0, 2.0]]
 };
GetUnitCone: PUBLIC PROC RETURNS [RevoluteMesh] = {
RETURN[CreateCone[1.0, 1.0]]
 }; 

END.