PolyHackA.Mesa
Mike Spreitzer July 30, 1986 11:31:01 pm PDT
DIRECTORY BiScrollers, Geom2D, Imager, ImagerBox, IO, Misp, PolyHackInsides, Process, Random, Real, RealFns, StructuredStreams, ViewerClasses, ViewerOps, ViewerSpecs;
PolyHackA: CEDAR MONITOR
IMPORTS Geom2D, Imager, ImagerBox, IO, Misp, PolyHackInsides, Process, Random, Reals: Real, RealFns, SS:StructuredStreams, ViewerOps
EXPORTS PolyHackInsides =
BEGIN OPEN PolyHackInsides;
Broken: ERROR = CODE;
rs: PUBLIC Random.RandomStream ← Random.Create[seed: -1];
whiteColoring: Coloring ← NEW [ColoringRep ← [color: Imager.white]];
PaintHack: PUBLIC PROC [self: Viewer, context: Imager.Context, whatChanged: REF ANY, clear: BOOL] RETURNS [quit: BOOLFALSE] --ViewerClasses.PaintProc-- =
BEGIN
vd: ViewerData ← ViewerDataOf[self];
IF self.column # vd.oldColumn THEN
{vd.color ← (vd.oldColumn ← self.column) = color};
IF whatChanged = NIL THEN
BEGIN
Imager.SetColor[context, Imager.black];
Imager.MaskBox[context, vd.bloatedBounds];
END
ELSE FOR lora: LORANARROW[whatChanged], lora.rest WHILE lora # NIL DO
WITH lora.first SELECT FROM
da: DrawAreas => BEGIN
FOR pl: DetailedPathList ← da.areaPaths, pl.rest WHILE pl # NIL DO
path: Imager.PathProc = {
p: Path ← pl.first.path;
IF p.length = 0 THEN RETURN;
moveTo[p[0]];
FOR i: INT IN (0 .. p.length) DO lineTo[p[i]] ENDLOOP;
};
Imager.SetColor[context, ColoringColor[pl.first.coloring]];
Imager.MaskFill[context: context, path: path, parity: TRUE]
ENDLOOP;
END;
ds: DrawStrokes => BEGIN
FOR pl: DetailedPathList ← ds.strokePaths, pl.rest WHILE pl # NIL DO
path: Imager.PathProc = {
p: Path ← pl.first.path;
IF p.length = 0 THEN RETURN;
moveTo[p[0]];
FOR i: INT IN (0 .. p.length) DO lineTo[p[i]] ENDLOOP;
};
Imager.SetColor[context, ColoringColor[pl.first.coloring]];
Imager.MaskStroke[context: context, path: path, closed: FALSE];
ENDLOOP;
END;
dt: DrawTriangles => BEGIN
FOR polyList: PolyList ← vd.polys, polyList.rest WHILE polyList # NIL DO
Imager.SetColor[context, ColoringColor[polyList.first.coloring]];
IF dt.strict THEN Trianglify[polyList.first, dt.trianglePath, vd, context]
ELSE Quadrify[polyList.first, dt.trianglePath, vd, context];
ENDLOOP;
END;
ENDCASE => Imager.MaskBox[context, [-100, -100, 100, 100]];
ENDLOOP;
END;
Quadrify: PROC [poly: Poly, path: Path, vd: ViewerData, context: Imager.Context] =
BEGIN
FOR vr: VertexRing ← poly.vertices.next, vr.next WHILE vr # poly.vertices DO
AddVertex: PROC [v: Vertex] = INLINE
BEGIN
p: Point ← v.curLoc;
IF vd.ctlPanel.round THEN p ← RoundPoint[p];
ExtendPath[path, p];
END;
EnumPath: Imager.PathProc = {
IF path.length = 0 THEN RETURN;
moveTo[path[0]];
FOR i: INT IN (0 .. path.length) DO lineTo[path[i]] ENDLOOP;
};
ResetPath[path];
IF vr.paintHalf THEN {StepVertex[vr.vertex, vd.ctlPanel.speed]; LOOP};
IF vr.prev # poly.vertices THEN AddVertex[vr.prev.vertex];
AddVertex[vr.vertex];
IF vr.next # poly.vertices THEN AddVertex[vr.next.vertex];
StepVertex[vr.vertex, vd.ctlPanel.speed];
AddVertex[vr.vertex];
Imager.MaskFill[context: context, path: EnumPath, parity: TRUE];
ENDLOOP;
END;
Trianglify: PROC [poly: Poly, path: Path, vd: ViewerData, context: Imager.Context] =
BEGIN
EnumPath: Imager.PathProc = {
IF path.length = 0 THEN RETURN;
moveTo[path[0]];
FOR i: INT IN (0 .. path.length) DO lineTo[path[i]] ENDLOOP;
};
FOR vr: VertexRing ← poly.vertices.next, vr.next WHILE vr # poly.vertices DO
first: BOOLEANTRUE;
old: Point;
DoUnroundedTriangle: PROC [v: Vertex] = INLINE
BEGIN
ResetPath[path];
ExtendPath[path, v.curLoc];
ExtendPath[path, vr.vertex.curLoc];
ExtendPath[path, old];
Imager.MaskFill[context: context, path: EnumPath, parity: TRUE];
END;
DoRoundedTriangle: PROC [v: Vertex] = INLINE
BEGIN
ResetPath[path];
ExtendPath[path, RoundPoint[v.curLoc]];
ExtendPath[path, RoundPoint[vr.vertex.curLoc]];
ExtendPath[path, RoundPoint[old]];
Imager.MaskFill[context: context, path: EnumPath, parity: TRUE];
END;
IF vr.paintHalf THEN {StepVertex[vr.vertex, vd.ctlPanel.speed]; LOOP};
old ← vr.vertex.curLoc;
StepVertex[vr.vertex, vd.ctlPanel.speed];
IF vd.ctlPanel.round THEN
BEGIN
IF vr.prev # poly.vertices THEN DoRoundedTriangle[vr.prev.vertex];
IF vr.next # poly.vertices THEN DoRoundedTriangle[vr.next.vertex];
END
ELSE BEGIN
IF vr.prev # poly.vertices THEN DoUnroundedTriangle[vr.prev.vertex];
IF vr.next # poly.vertices THEN DoUnroundedTriangle[vr.next.vertex];
END;
ENDLOOP;
END;
RoundPoint: PROC [p: Point] RETURNS [rp: Point] = INLINE {rp ← [
x: Reals.RoundLI[p.x],
y: Reals.RoundLI[p.y]]};
GetRunLock: PUBLIC ENTRY PROC [vd: ViewerData] RETURNS [run: BOOLEAN] =
{IF (run ← NOT vd.running) THEN {vd.running ← TRUE; vd.runner ← Process.GetCurrent[]}};
UnRun: PUBLIC ENTRY PROC [vd: ViewerData, unstop: BOOL] = {
vd.running ← FALSE;
vd.runner ← NIL;
IF unstop THEN vd.ctlPanel.stop ← FALSE};
AbortRunner: PUBLIC ENTRY PROC [vd: ViewerData] RETURNS [wasRunning: BOOL] = {
IF (wasRunning ← vd.runner # NIL) # vd.running THEN RETURN WITH ERROR Broken;
IF wasRunning THEN TRUSTED {Process.Abort[LOOPHOLE[vd.runner, UNSPECIFIED]]};
};
PrepareToRun: PUBLIC PROC [vd: ViewerData] RETURNS [lda: LORA, da: DrawAreas, ds: DrawStrokes] =
BEGIN
SELECT vd.ctlPanel.mode FROM
sweep => BEGIN
SELECT vd.ctlPanel.method FROM
polygons => lda ← LIST[da ← DAForPolys[vd.polys]];
triangles => lda ← LIST[NewDT[TRUE]];
quadrilaterals => lda ← LIST[NewDT[FALSE]];
ENDCASE => ERROR;
END;
trace => BEGIN
lda ← LIST[ds ← DSForTrace[vd.polys]];
END;
outline => BEGIN
lda ← LIST[ds ← DSForOutline[vd.polys]];
END;
fill => BEGIN
lda ← LIST[da ← DAForFill[vd.polys]];
END;
ENDCASE => ERROR;
END;
DAForPolys: PROC [polyList: PolyList] RETURNS [da: DrawAreas] =
BEGIN
da ← NEW [DrawAreasRep ← [PathsForPolys[polyList, 2]]];
END;
PathsForPolys: PROC [polyList: PolyList, mult: CARDINAL ← 1] RETURNS [paths: DetailedPathList] =
BEGIN
last: DetailedPathList ← paths ← NIL;
FOR polyList ← polyList, polyList.rest WHILE polyList # NIL DO
this: DetailedPathList ← LIST[[path: NewPath[size: 1 + 2*polyList.first.vertexCount], coloring: polyList.first.coloring]];
IF last = NIL THEN paths ← this ELSE last.rest ← this;
last ← this;
ENDLOOP;
END;
DAForFill: PROC [polyList: PolyList] RETURNS [da: DrawAreas] =
BEGIN
last: DetailedPathList ← NIL;
da ← NEW [DrawAreasRep ← [areaPaths: NIL]];
FOR polyList ← polyList, polyList.rest WHILE polyList # NIL DO
this: DetailedPathList ← LIST[[coloring: polyList.first.coloring, path: NewPath[polyList.first.vertexCount + 1]]];
IF last = NIL THEN da.areaPaths ← this ELSE last.rest ← this;
last ← this;
ENDLOOP;
END;
DSForOutline: PROC [polyList: PolyList] RETURNS [ds: DrawStrokes] =
BEGIN
last: DetailedPathList ← NIL;
ds ← NEW [DrawStrokesRep ← [strokePaths: NIL]];
FOR polyList ← polyList, polyList.rest WHILE polyList # NIL DO
this: DetailedPathList ← LIST[[coloring: polyList.first.coloring, path: NewPath[polyList.first.vertexCount + 1]]];
IF last = NIL THEN ds.strokePaths ← this ELSE last.rest ← this;
last ← this;
ENDLOOP;
END;
DSForTrace: PROC [polyList: PolyList] RETURNS [ds: DrawStrokes] =
BEGIN
last: DetailedPathList ← NIL;
ds ← NEW [DrawStrokesRep ← [strokePaths: NIL]];
FOR polyList ← polyList, polyList.rest WHILE polyList # NIL DO
THROUGH [1 .. polyList.first.vertexCount] DO
this: DetailedPathList ← LIST[[coloring: polyList.first.coloring, path: NewPath[2]]];
IF last = NIL THEN ds.strokePaths ← this ELSE last.rest ← this;
last ← this;
ENDLOOP;
ENDLOOP;
END;
StepCmd: PUBLIC PROC [vd: ViewerData] =
{IF NOT OKToRun[vd] THEN RETURN;
BEGIN ENABLE UNWIND => UnRun[vd, TRUE];
da: DrawAreas;
ds: DrawStrokes;
lda: LORA;
[lda, da, ds] ← PrepareToRun[vd];
StepHack[vd, lda, da, ds];
END;
UnRun[vd, TRUE];
};
NewDT: PROC [strict: BOOLEAN] RETURNS [DrawTriangles] =
{RETURN [NEW [DrawTrianglesRep ← [strict, NewPath[4]]]]};
StepHack: PUBLIC PROC [vd: ViewerData, lda: LORA, da: DrawAreas, ds: DrawStrokes] =
BEGIN
IF vd.ctlPanel.stop THEN ERROR ABORTED[];
Process.CheckForAbort[];
SELECT vd.ctlPanel.mode FROM
sweep => SweepHack[vd, da, lda];
outline => OutlineHack[vd, ds, lda];
fill => FillHack[vd, da, lda];
trace => TraceHack[vd, ds, lda];
ENDCASE => ERROR;
END;
OutlineHack: PROC [vd: ViewerData, ds: DrawStrokes, lda: LORA] =
BEGIN
paths: DetailedPathList ← ds.strokePaths;
FOR polyList: PolyList ← vd.polys, polyList.rest WHILE polyList # NIL DO
ResetPath[paths.first.path];
FOR vr: VertexRing ← polyList.first.vertices.next, vr.next WHILE vr # polyList.first.vertices DO
ExtendPath[paths.first.path, vr.vertex.curLoc];
StepVertex[vr.vertex, vd.ctlPanel.speed];
ENDLOOP;
StepPoly[polyList.first];
paths ← paths.rest;
ENDLOOP;
ViewerOps.PaintViewer[viewer: vd.viewer, hint: client, whatChanged: lda, clearClient: FALSE];
END;
FillHack: PROC [vd: ViewerData, da: DrawAreas, lda: LORA] =
BEGIN
paths: DetailedPathList ← da.areaPaths;
FOR polyList: PolyList ← vd.polys, polyList.rest WHILE polyList # NIL DO
ResetPath[paths.first.path];
FOR vr: VertexRing ← polyList.first.vertices.next, vr.next WHILE vr # polyList.first.vertices DO
ExtendPath[paths.first.path, vr.vertex.curLoc];
StepVertex[vr.vertex, vd.ctlPanel.speed];
ENDLOOP;
StepPoly[polyList.first];
paths ← paths.rest;
ENDLOOP;
ViewerOps.PaintViewer[viewer: vd.viewer, hint: client, whatChanged: lda, clearClient: FALSE];
END;
TraceHack: PROC [vd: ViewerData, ds: DrawStrokes, lds: LORA] =
BEGIN
paths: DetailedPathList ← ds.strokePaths;
FOR polyList: PolyList ← vd.polys, polyList.rest WHILE polyList # NIL DO
poly: Poly ← polyList.first;
last: VertexRing ← IF poly.closed THEN poly.vertices.prev ELSE poly.vertices;
FOR vr: VertexRing ← poly.vertices.next, vr.next WHILE vr # last DO
ResetPath[paths.first.path];
ExtendPath[paths.first.path, vr.vertex.curLoc];
StepVertex[vr.vertex, vd.ctlPanel.speed];
ExtendPath[paths.first.path, vr.vertex.curLoc];
paths ← paths.rest;
ENDLOOP;
IF poly.closed THEN StepVertex[last.vertex, vd.ctlPanel.speed];
StepPoly[polyList.first];
ENDLOOP;
ViewerOps.PaintViewer[viewer: vd.viewer, hint: client, whatChanged: lds, clearClient: FALSE];
END;
SweepHack: PROC [vd: ViewerData, da: DrawAreas, lda: LORA] =
BEGIN
SELECT vd.ctlPanel.method FROM
polygons => BEGIN
paths: DetailedPathList;
paths ← da.areaPaths;
FOR polyList: PolyList ← vd.polys, polyList.rest WHILE polyList # NIL DO
SweepPoly[polyList.first, vd, paths];
StepPoly[polyList.first];
paths ← paths.rest;
ENDLOOP;
END;
triangles, quadrilaterals => {
FOR polyList: PolyList ← vd.polys, polyList.rest WHILE polyList # NIL DO
StepPoly[polyList.first];
ENDLOOP;
};
ENDCASE => ERROR;
ViewerOps.PaintViewer[viewer: vd.viewer, hint: client, whatChanged: lda, clearClient: FALSE];
END;
SweepPoly: PROC [poly: Poly, vd: ViewerData, paths: DetailedPathList] =
BEGIN
AddVertex: PROC [v: Vertex] = INLINE
BEGIN
p: Point ← v.curLoc;
IF vd.ctlPanel.round THEN p ← RoundPoint[p];
ExtendPath[paths.first.path, p];
END;
firstLooked: BOOLEANTRUE;
ResetPath[paths.first.path];
FOR vr: VertexRing ← poly.vertices.next, vr.next WHILE vr # poly.vertices DO
IF firstLooked THEN
BEGIN
firstLooked ← FALSE;
IF NOT vr.paintHalf THEN AddVertex[vr.vertex];
END
ELSE AddVertex[vr.vertex];
StepVertex[vr.vertex, vd.ctlPanel.speed];
ENDLOOP;
firstLooked ← TRUE;
FOR vr: VertexRing ← poly.vertices.prev, vr.prev WHILE vr # poly.vertices DO
IF firstLooked THEN
BEGIN
firstLooked ← FALSE;
IF vr.paintHalf THEN LOOP;
END;
AddVertex[vr.vertex];
ENDLOOP;
END;
StepVertex: PROC [v: Vertex, speed: REAL] = INLINE
BEGIN
v.class.StepVertex[v, speed];
END;
bounceClass: PUBLIC VertexClass ← NEW [VertexClassRep ← [
name: "Bounce",
StepVertex: StepBounce,
Copy: CopyBounce,
WriteData: WriteBounce,
VertexBounds: BounceBounds]];
BounceBounds: PROC [v: Vertex] RETURNS [Box] =
BEGIN
b: Bounce ← NARROW[v.data];
RETURN [[xmin: b.xmin, ymin: b.ymin, xmax: b.xmax, ymax: b.ymax]];
END;
WriteBounce: PROC [to: IO.STREAM, data: VertexData] =
BEGIN
b: Bounce ← NARROW[data];
to.PutF[", dx:%g, dy:%g", IO.real[b.dx], IO.real[b.dy]];
to.PutF[", box: [%g, %g, %g, %g]", IO.real[b.xmin], IO.real[b.ymin], IO.real[b.xmax], IO.real[b.ymax]];
END;
CopyBounce: PROC [vd: VertexData] RETURNS [VertexData] =
BEGIN
b: Bounce ← NARROW[vd];
RETURN [NEW [BounceRep ← b^]];
END;
StepBounce: PROC [v: Vertex, s: REAL] =
BEGIN
AddAndBounce: PROC [zi, dzi, zmin, zmax: REAL] RETURNS [z, dz: REAL] = INLINE
BEGIN
z ← zi + s*dzi;
IF z <= zmin THEN {z ← 2*zmin-z; dz ← -dzi}
ELSE IF z >= zmax THEN {z ← 2*zmax-z; dz ← -dzi}
ELSE dz ← dzi;
END;
b: Bounce ← NARROW[v.data];
[v.curLoc.x, b.dx] ← AddAndBounce[v.curLoc.x, b.dx, b.xmin, b.xmax];
[v.curLoc.y, b.dy] ← AddAndBounce[v.curLoc.y, b.dy, b.ymin, b.ymax];
END;
MakeRandomBouncePoly: PUBLIC PROC [nVerts: CARDINAL, xmax, ymax: INT ← 400, dxmax, dymax: INT ← 10, close: BOOLEANTRUE] RETURNS [poly: Poly] =
BEGIN
poly ← NewPoly[close, whiteColoring];
FOR n: CARDINAL IN [1 .. nVerts] DO
v: Vertex ← RandomBounce[xmax, ymax, dxmax, dymax];
AddVertexToPoly[v, poly];
ENDLOOP;
Finish[poly];
END;
RandomBounce: PUBLIC PROC [xmax, ymax, dxmax, dymax: INT] RETURNS [v: Vertex] =
BEGIN
v ← NewBounce[
x: rs.ChooseInt[min: 0, max: xmax],
y: rs.ChooseInt[min: 0, max: ymax],
dx: PickVelocity[dxmax],
dy: PickVelocity[dymax],
xmin: 0, xmax: xmax, ymin: 0, ymax: ymax];
END;
NewBounce: PUBLIC PROC [x, y, dx, dy, xmin, ymin, xmax, ymax: REAL] RETURNS [v: Vertex] =
BEGIN
v ← NEW [VertexRep ← [
curLoc: [x: x, y: y],
class: bounceClass,
data: NEW [BounceRep ← [
dx: dx, dy: dy,
xmin: xmin, xmax: xmax, ymin: ymin, ymax: ymax]] ]];
END;
PickVelocity: PROC [max: INT] RETURNS [v: REAL --[-max .. max]--] =
BEGIN
v ← rs.ChooseInt[min: -max, max: max] * rs.ChooseInt[min: 1, max: max] / REAL[max];
END;
NewSum: PUBLIC PROC [a, b: Vertex, aOld: BOOLEAN] RETURNS [c: Vertex] =
BEGIN
s: Sum ← NEW [SumRep ← [a, b, aOld]];
c ← NEW [VertexRep ← [
curLoc: [x: a.curLoc.x + b.curLoc.x, y: a.curLoc.y + b.curLoc.y],
class: sumClass,
data: s]];
END;
Sum: TYPE = REF SumRep;
SumRep: TYPE = RECORD [
a, b: Vertex,
aOld: BOOLEAN];
sumClass: VertexClass ← NEW [VertexClassRep ← [
name: "Sum",
StepVertex: StepSum,
Copy: CopySum,
WriteData: WriteSum,
VertexBounds: SumBounds]];
SumBounds: PROC [v: Vertex] RETURNS [b: Box] =
BEGIN
s: Sum ← NARROW[v.data];
b ← ImagerBox.BoxFromRect[Geom2D.SweepRects[
ImagerBox.RectFromBox[VertexBounds[s.a]],
ImagerBox.RectFromBox[VertexBounds[s.b]]
]];
END;
StepSum: PROC [v: Vertex, speed: REAL] =
BEGIN
s: Sum ← NARROW[v.data];
IF NOT s.aOld THEN StepVertex[s.a, speed];
StepVertex[s.b, speed];
v.curLoc.x ← s.a.curLoc.x + s.b.curLoc.x;
v.curLoc.y ← s.a.curLoc.y + s.b.curLoc.y;
END;
CopySum: PROC [vd: VertexData] RETURNS [new: VertexData] =
{new ← NEW [SumRep ← NARROW[vd, Sum]^]};
WriteSum: PROC [to: IO.STREAM, data: VertexData] =
BEGIN
s: Sum ← NARROW[data];
to.PutRope[", "]; SS.Bp[ss: to, cond: lookLeft, offset: 4];
to.PutRope["a:"]; IF s.aOld THEN to.PutF["old(x:%g, y:%g)", IO.real[s.a.curLoc.x], IO.real[s.a.curLoc.y]] ELSE WriteVertex[to, s.a];
to.PutRope[", "]; SS.Bp[ss: to, cond: lookLeft, offset: 4];
to.PutRope["b:"]; WriteVertex[to, s.b];
END;
NewLisasjous: PUBLIC PROC [x, y: Sinusoid] RETURNS [v: Vertex] =
BEGIN
l: Lisasjous ← NEW [LisasjousRep ← [x: x, y: y]];
v ← NEW [VertexRep ← [curLoc: [x: 0, y: 0], class: lisasjousClass, data: l]];
SetLisasjousXY[v, l];
END;
Lisasjous: TYPE = REF LisasjousRep;
LisasjousRep: TYPE = RECORD [
x, y: Sinusoid];
lisasjousClass: VertexClass ← NEW [VertexClassRep ← [
name: "Lisasjous",
StepVertex: StepLisasjous,
Copy: CopyLisasjous,
WriteData: WriteLisasjous,
VertexBounds: LisasjousBounds]];
LisasjousBounds: PROC [v: Vertex] RETURNS [bounds: Box] =
BEGIN
l: Lisasjous ← NARROW[v.data];
[bounds.xmin, bounds.xmax] ← SinusoidBounds[l.x];
[bounds.ymin, bounds.ymax] ← SinusoidBounds[l.y];
END;
SinusoidBounds: PROC [s: Sinusoid] RETURNS [min, max: REAL] =
BEGIN
IF s.stepSize = 0 THEN min ← max ← s.base + s.amplitude*RealFns.SinDeg[s.theta] ELSE {min ← s.base-ABS[s.amplitude]; max ← s.base+ABS[s.amplitude]};
END;
WriteLisasjous: PROC [to: IO.STREAM, data: VertexData] =
BEGIN
l: Lisasjous ← NARROW[data];
to.PutRope[", "]; SS.Bp[ss: to, cond: united, offset: 4];
to.PutRope["x:"]; WriteSinusoid[to, l.x];
to.PutRope[", "]; SS.Bp[ss: to, cond: united, offset: 4];
to.PutRope["y:"]; WriteSinusoid[to, l.y];
END;
WriteSinusoid: PROC [to: IO.STREAM, s: Sinusoid] =
BEGIN
SS.Begin[to];
to.PutF["[base:%g, ampl:%g, step:%g, theta:%g]", IO.real[s.base], IO.real[s.amplitude], IO.real[s.stepSize], IO.real[s.theta]];
SS.End[to];
END;
CopyLisasjous: PROC [old: VertexData] RETURNS [new: VertexData] =
BEGIN
s: Lisasjous ← NARROW[old];
new ← NEW [LisasjousRep ← s^];
END;
StepLisasjous: PROC [v: Vertex, speed: REAL] =
BEGIN
l: Lisasjous ← NARROW[v.data];
l.x.theta ← RealMod[l.x.theta + l.x.stepSize*speed, 360.0];
l.y.theta ← RealMod[l.y.theta + l.y.stepSize*speed, 360.0];
SetLisasjousXY[v, l];
END;
RealMod: PROC [a, b: REAL] RETURNS [rem: REAL] = INLINE
BEGIN
n: INT ← Reals.RoundLI[a/b];
rem ← a - b*n;
END;
SetLisasjousXY: PROC [v: Vertex, l: Lisasjous] =
BEGIN
v.curLoc.x ← EvalSinusoid[l.x];
v.curLoc.y ← EvalSinusoid[l.y];
END;
EvalSinusoid: PROC [s: Sinusoid] RETURNS [z: REAL] = INLINE
{z ← s.base + s.amplitude*RealFns.SinDeg[s.theta]};
constantClass: PUBLIC VertexClass ← NEW [VertexClassRep ← [
name: "Constant",
StepVertex: StepConstant,
Copy: CopyConstant,
WriteData: WriteConstant,
VertexBounds: ConstantBounds]];
StepConstant: PROC [Vertex, REAL] = {};
CopyConstant: PROC [VertexData] RETURNS [VertexData] = {RETURN [NIL]};
WriteConstant: PROC [IO.STREAM, VertexData] = {};
ConstantBounds: PROC [v: Vertex] RETURNS [bounds: Box] =
{bounds.xmin ← bounds.xmax ← v.curLoc.x; bounds.ymin ← bounds.ymax ← v.curLoc.y};
NewPoly: PUBLIC PROC [close: BOOLEANTRUE, coloring: Coloring] RETURNS [p: Poly] =
BEGIN
p ← NEW [PolyRep ← [closed: close, coloring: coloring]];
p.vertices ← NEW [VertexRingRep ← []];
p.vertices.next ← p.vertices.prev ← p.vertices;
END;
ColoringColor: PUBLIC PROC [c: Coloring] RETURNS [color: Color] =
{color ← c.color};
StepPoly: PUBLIC PROC [p: Poly] = {
IF NOT p.coloring.constant THEN {
p.coloring.arg^ ← p.coloring.arg^ + 1.0;
UpdateColoring[p.coloring];
};
p ← p;
};
UpdateColoring: PUBLIC PROC [coloring: Coloring] = {
ra: REF ANY;
ra ← Misp.Eval[raw: coloring.form, environment: coloring.env, stack: coloring.stack];
WITH ra SELECT FROM
cr: Color => coloring.color ← cr;
ENDCASE => ERROR;
coloring ← coloring;
};
Finish: PUBLIC PROC [poly: Poly] =
BEGIN
IF poly.vertices.next # poly.vertices AND poly.closed THEN AddVertexToPoly[Copy[poly.vertices.next.vertex], poly];
END;
AddVertexToPoly: PUBLIC PROC [v: Vertex, p: Poly] =
BEGIN
vr: VertexRing ← NEW [VertexRingRep ← [next: p.vertices, prev: p.vertices.prev, vertex: v]];
vr.prev.next ← vr;
vr.next.prev ← vr;
p.vertexCount ← p.vertexCount + 1;
END;
NewPath: PUBLIC PROC [size: NAT] RETURNS [p: Path] = {
p ← NEW [PathRep[size]];
p.length ← 0;
};
ResetPath: PUBLIC PROC [p: Path] = {
p.length ← 0;
};
ExtendPath: PUBLIC PROC [path: Path, p: Point] = {
path[path.length] ← p;
path.length ← path.length + 1;
};
DefineHackAStuff: PUBLIC PROC [environment: Misp.Environment, vd: ViewerData] =
BEGIN
Misp.Bind[$sweep, NEW [Mode ← sweep], environment, TRUE];
Misp.Bind[$outline, NEW [Mode ← outline], environment, TRUE];
Misp.Bind[$fill, NEW [Mode ← fill], environment, TRUE];
Misp.Bind[$trace, NEW [Mode ← trace], environment, TRUE];
END;
Setup: PROC =
BEGIN
END;
Setup[];
END.