G2dSpirographCmdImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, July 20, 1992 1:09 pm PDT
Glassner, May 30, 1986 12:32:04 pm PDT
DIRECTORY Draw2d, Commander, Controls, G2dTool, Imager, IO, Process, RealFns, Vector2, ViewerOps;
G2dSpirographCmdImpl: CEDAR PROGRAM
IMPORTS Draw2d, Controls, G2dTool, Process, RealFns, ViewerOps
~ BEGIN
ProgramData:  TYPE ~ REF ProgramDataRep;
ProgramDataRep: TYPE ~ RECORD [
outer:      Controls.Viewer ¬ NIL,      -- main outer viewer
graphics:     Controls.Viewer ¬ NIL,      -- viewer for graphics
smallAngle, bigAngle: REAL ¬ 0.0,
centerPt:     Imager.VEC ¬ [150.0, 150.0],
oldPt, newPt:    Imager.VEC,
bigAngleDelta:   REAL,
smallAngleDelta:   REAL,
smallSpeed:     REAL ¬ 37.0,   -- speed increase for the small wheel
smallR:      REAL ¬ 30.0,   -- small wheel radius
bigR:       REAL ¬ 90.0,   -- big wheel radius
modR:      REAL ¬ .4,   -- percent of small wheel radius modulation
modF:      REAL ¬ 5.0,   -- small wheel radius modulation frequency
cycles:      REAL ¬ 1.2,   -- # of small wheel rotations around the big one
numSteps:     INTEGER ¬ 5000, -- # of steps to take once around the big wheel
loops:      INTEGER ¬ 5,  -- # of times to go around the big wheel
bigPt:      Imager.VEC,
tmpR:      REAL,
smallPt:     Imager.VEC,
dset:       INTEGER ¬ 2,  -- which prebuilt data set to use
start:      BOOL ¬ TRUE,
newViewer:    BOOL ¬ TRUE
];
G2dSpirograph: Commander.CommandProc ~ {
p: ProgramData ¬ NEW[ProgramDataRep];
p.outer ¬ Controls.OuterViewer[
name: "Spirograph",
graphicsHeight: 300,
drawProc: DrawProc,
clientData: p].parent;
p.graphics ¬ NARROW[p.outer.data, Controls.OuterData].graphics;
SELECT p.dset FROM
4 => {
p.smallSpeed ¬ 15.0; p.smallR ¬ 30.0; p.bigR ¬ 50.0; p.modR ¬ 1.4; p.modF ¬ 7.0;
p.cycles ¬ 1.4; p.numSteps ¬ 5000; p.loops ¬ 5;
};
3 => {
p.smallSpeed ¬ 15.0; p.smallR ¬ 30.0; p.bigR ¬ 90.0; p.modR ¬ .4; p.modF ¬ 7.0;
p.cycles ¬ 1.4; p.numSteps ¬ 5000; p.loops ¬ 5;
};
2 => {
p.smallSpeed ¬ 37.0; p.smallR ¬ 30.0; p.bigR ¬ 90.0; p.modR ¬ .4; p.modF ¬ 5.0;
p.cycles ¬ 1.2; p.numSteps ¬ 5000; p.loops ¬ 5;
};
ENDCASE => {
p.smallSpeed ¬ 13.0; p.smallR ¬ 30.0; p.bigR ¬ 90.0; p.modR ¬ .4; p.modF ¬ 5.0;
p.cycles ¬ 1.0; p.numSteps ¬ 5000; p.loops ¬ 1;
};
p.bigAngleDelta ¬ (2.0*3.1415926535*p.cycles)/p.numSteps;
p.smallAngleDelta ¬ (2.0*3.1415926535*p.smallSpeed)/p.numSteps;
Process.Pause[Process.MsecToTicks[100]];
FOR n: NAT IN [0..p.loops) DO
ViewerOps.PaintViewer[p.graphics, client, FALSE, p.graphics];
Process.CheckForAbort[];
ENDLOOP;
};
DrawProc: Controls.DrawProc ~ {
p: ProgramData ¬ NARROW[clientData];
IF p.newViewer THEN {
p.newViewer ¬ FALSE;
Draw2d.Clear[context];
RETURN;
};
FOR n: NAT IN [0..p.numSteps) DO
p.bigPt ¬ [p.bigR*RealFns.Cos[p.bigAngle], p.bigR*RealFns.Sin[p.bigAngle]];
p.tmpR ¬ p.smallR + ((p.smallR * p.modR) * RealFns.Sin[p.bigAngle * p.modF]);
p.smallPt ¬ [p.tmpR*RealFns.Cos[p.smallAngle], p.tmpR*RealFns.Sin[p.smallAngle]];
p.newPt.x ¬ p.centerPt.x + p.bigPt.x + p.smallPt.x;
p.newPt.y ¬ p.centerPt.y + p.bigPt.y + p.smallPt.y;
IF p.start
THEN p.start ¬ FALSE
ELSE Draw2d.Line[context, p.oldPt, p.newPt];
p.oldPt ¬ p.newPt;
p.bigAngle ¬ p.bigAngle + p.bigAngleDelta;
p.smallAngle ¬ p.smallAngle + p.smallAngleDelta;
ENDLOOP;
};
G2dTool.Register["Spirograph", G2dSpirograph, "\nDraw a spirograph."];
END.