<> <> 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: BOOL _ FALSE] --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: LORA _ NARROW[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: BOOLEAN _ TRUE; 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: BOOLEAN _ TRUE; 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: BOOLEAN _ TRUE] 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: BOOLEAN _ TRUE, 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.