DIRECTORY Real USING [RoundLI], PixelGraphics ; PixelGraphicsImpl: CEDAR PROGRAM IMPORTS Real EXPORTS PixelGraphics = BEGIN OPEN PixelGraphics; FourByFour: TYPE ~ RECORD [ a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4: REAL ]; Line: PUBLIC PROC [p0, p1: Point] RETURNS [p: LIST OF Point] ~ { pTail: LIST OF Point; pTail _ p _ LIST [p0]; [] _ AddPointsForLineToTail[p0, p1, pTail]; }; Lines: PUBLIC PROC [vertices: LIST OF Point] RETURNS [p: LIST OF Point] ~ { pTail: LIST OF Point; IF vertices=NIL THEN RETURN [NIL]; pTail _ p _ LIST[vertices.first]; FOR each: LIST OF Point _ vertices, each.rest UNTIL each.rest=NIL DO pTail _ AddPointsForLineToTail[each.first, each.rest.first, pTail]; ENDLOOP; }; InterpolateLines: PUBLIC PROC [vertices: LIST OF Point, proc: PROC [p: Point]] ~ { IF vertices=NIL THEN RETURN; --Nothing more to do proc[vertices.first]; --Call for the first point FOR each: LIST OF Point _ vertices, each.rest UNTIL each.rest=NIL DO InterpolatePoints[each.first, each.rest.first, proc]; ENDLOOP; }; Spline: PUBLIC PROC [m: Cubic, segments: CARDINAL] RETURNS [p: LIST OF Point] ~ { h: REAL _ 1.0/segments; h2: REAL _ h*h; h3: REAL _ h2*h; pTail: LIST OF Point; x, y, dx, dy, d2x, d2y, d3x, d3y: REAL; x _ m.dx; y _ m.dy; dx _ m.ax*h3 + m.bx*h2 + m.cx*h; dy _ m.ay*h3 + m.by*h2 + m.cy*h; d2x _ 6*m.ax*h3 + 2*m.bx*h2; d2y _ 6*m.ay*h3 + 2*m.by*h2; d3x _ 6*m.ax*h3; d3y _ 6*m.ay*h3; pTail _ p _ LIST [[Real.RoundLI[x], Real.RoundLI[y]]]; THROUGH [1 .. segments ] DO x _ x + dx; dx _ dx + d2x; d2x _ d2x + d3x; y _ y + dy; dy _ dy + d2y; d2y _ d2y + d3y; pTail _ pTail.rest _ LIST [[Real.RoundLI[x], Real.RoundLI[y]]]; ENDLOOP; }; InterpolateSpline: PUBLIC PROC [m: Cubic, segments: CARDINAL, proc: PROC [p: Point]] ~ { InterpolateLines[Spline[m: m, segments: segments], proc]; }; Bezier: PUBLIC PROC [p1, p2, p3, p4: Point] RETURNS [m: Cubic] ~ { m _ Mul4x4By4x2 [p1, p2, p3, p4, 1, [-1, 3, -3, 1, 3, -6, 3, 0, -3, 3, 0, 0, 1, 0, 0, 0] ]; }; Simple: PUBLIC PROC [p1, p2, p3, p4: Point] RETURNS [m: Cubic] ~ { m _ Mul4x4By4x2 [p1, p2, p3, p4, 2, [-9, 27,-27, 9, 18,-45, 36, -9, -11, 18, -9, 2, 2, 0, 0, 0] ]; }; BSpline: PUBLIC PROC [p1, p2, p3, p4: Point] RETURNS [m: Cubic] ~ { m _ Mul4x4By4x2 [p1, p2, p3, p4, 6, [-1, 3, -3, 1, 3, -6, 3, 0, -3, 0, 3, 0, 1, 4, 1, 0] ]; }; CatmullRom: PUBLIC PROC [p1, p2, p3, p4: Point] RETURNS [m: Cubic] ~ { m _ Mul4x4By4x2 [p1, p2, p3, p4, 2, [-1, 3, -3, 1, 2, -5, 4, -1, -1, 0, 1, 0, 0, 2, 0, 0] ]; }; Hermite: PUBLIC PROC [p1, q1, p2, q2: Point] RETURNS [m: Cubic] ~ { m _ Mul4x4By4x2 [p1, p2, q1, q2, 1, [ 2, -2, 1, 1, -3, 3, -2, -1, 0, 0, 1, 0, 1, 0, 0, 0] ]; }; AddPointsForLineToTail: PROC [p0, p1: Point, inTail: LIST OF Point] RETURNS [tail: LIST OF Point] ~ INLINE { dx: INT ~ IF p0.x < p1.x THEN 1 ELSE -1; dy: INT ~ IF p0.y < p1.y THEN 1 ELSE -1; x: INT _ p0.x; y: INT _ p0.y; tail _ inTail; IF ABS[p0.x-p1.x] > ABS[p0.y-p1.y] THEN { dErrX: INT _ ABS[p1.y-p0.y]; dErrY: INT _ -ABS[p1.x-p0.x]; error: INT _ dErrY/2; THROUGH (0 .. -dErrY] DO x _ x+dx; error _ error + dErrX; IF error > 0 THEN {y _ y+dy; error _ error + dErrY}; tail _ tail.rest _ LIST[[x, y]]; ENDLOOP; } ELSE { dErrY: INT _ ABS[p1.x-p0.x]; dErrX: INT _ -ABS[p1.y-p0.y]; error: INT _ dErrX/2; THROUGH (0 .. -dErrX] DO y _ y+dy; error _ error + dErrY; IF error > 0 THEN {x _ x+dx; error _ error + dErrX}; tail _ tail.rest _ LIST[[x, y]]; ENDLOOP; }; }; InterpolatePoints: PUBLIC PROC [p0, p1: Point, proc: PROC [p: Point]] ~ { dx: INT ~ IF p0.x < p1.x THEN 1 ELSE -1; dy: INT ~ IF p0.y < p1.y THEN 1 ELSE -1; x: INT _ p0.x; y: INT _ p0.y; IF ABS[p0.x-p1.x] > ABS[p0.y-p1.y] THEN { dErrX: INT _ ABS[p1.y-p0.y]; dErrY: INT _ -ABS[p1.x-p0.x]; error: INT _ dErrY/2; THROUGH (0 .. -dErrY] DO x _ x+dx; error _ error + dErrX; IF error > 0 THEN {y _ y+dy; error _ error + dErrY}; proc[[x,y]]; ENDLOOP; } ELSE { dErrY: INT _ ABS[p1.x-p0.x]; dErrX: INT _ -ABS[p1.y-p0.y]; error: INT _ dErrX/2; THROUGH (0 .. -dErrX] DO y _ y+dy; error _ error + dErrY; IF error > 0 THEN {x _ x+dx; error _ error + dErrX}; proc[[x,y]]; ENDLOOP; }; }; Mul4x4By4x2: PROC [p1, p2, p3, p4: Point, divisor: REAL, m: FourByFour] RETURNS [cubic: Cubic] ~ INLINE { OPEN cubic, m; ax _ (a1*p1.x + a2*p2.x + a3*p3.x + a4*p4.x)/divisor; ay _ (a1*p1.y + a2*p2.y + a3*p3.y + a4*p4.y)/divisor; bx _ (b1*p1.x + b2*p2.x + b3*p3.x + b4*p4.x)/divisor; by _ (b1*p1.y + b2*p2.y + b3*p3.y + b4*p4.y)/divisor; cx _ (c1*p1.x + c2*p2.x + c3*p3.x + c4*p4.x)/divisor; cy _ (c1*p1.y + c2*p2.y + c3*p3.y + c4*p4.y)/divisor; dx _ (d1*p1.x + d2*p2.x + d3*p3.x + d4*p4.x)/divisor; dy _ (d1*p1.y + d2*p2.y + d3*p3.y + d4*p4.y)/divisor; }; END. ^PixelGraphicsImpl.mesa Contains utilities for doing various kinds of graphing, especially related to working on a raster, and drawing splines. Eric Nickell, April 25, 1985 7:54:24 am PST Returns the list of points which constitute the line between p0 and p1. The points returned will be in order, but no guarantee is made as to which endpoint is found at the beginning of the LIST and which is at the end. Returns the list of points which constitute the lines between successive points in p. The points returned will be in order, but no guarantee is made as to which endpoint is found at the beginning of the LIST and which is at the end. Finds the set of interpolation points for the spline, breaking the spline into segments parts. Generates the Cubic matrix for a Bezier spline given the four control points. Generates the Cubic matrix for a Cubic spline given the four control points. Generates the Cubic matrix for a B-Spline given the four control points. Generates the Cubic matrix for a Catmull-Rom spline given the four control points. Generates the Cubic matrix for a Hermite spline given the two control points and the tangent vectors at those points. Here, we always change in x, and sometimes in y. Here, we always change in y, and sometimes in x. Here, we always change in x, and sometimes in y. Here, we always change in y, and sometimes in x. Κέ˜code™K™wK™+K™—šΟk ˜ Jšœœ ˜Jšœ ˜ J˜—šœ ˜ Jšœ˜ Jšœ˜Jšœ˜Jšœ˜J˜šœ œœ˜J˜J˜J˜Jšœ˜Jšœ˜J˜—š Οnœœœœœœ ˜@JšœG™GJ™’Jšœœœ˜J˜Jšœ œ˜J˜+Jšœ˜J™—šžœœœ œœœœœ ˜KJšœU™UJ™’Jšœœœ˜Jš œ œœœœ˜"J˜Jšœ œ˜!š œœœœ œ˜DJ˜CJš˜—Jšœ˜J™—š žœœœ œœœ˜RKš œ œœœΟc˜1K˜KšœŸ˜1š œœœœ œ˜DK˜5Kš˜—K˜K˜—šžœœœœœœœ ˜QJ™^Jšœœ˜JšœΟuœœ˜Jšœ œœ œ˜Jšœœœ˜Jš œ œ œ œ œœ˜'J˜J˜ J˜ J˜Jšœ  œ  œ ˜ Jšœ  œ  œ ˜ J˜Jšœ œ  œ  œ˜Jšœ œ  œ  œ˜J˜Jšœ œ  œ˜Jšœ œ  œ˜J˜Jšœ œ&˜6šœ˜J˜ Jšœ  œ˜Jšœ œ œ œ˜J˜ Jšœ  œ˜Jšœ œ œ œ˜Jšœœ&˜?Jš˜—Jšœ˜J™—š žœœœœœ˜XK˜9K˜K˜—šžœœœœ˜BJ™M˜#KšΟf˜Kš‘˜Kš‘˜Kš‘˜K˜—Jšœ˜J™—šžœœœœ˜BJ™L˜#Kš‘˜Kš‘˜Kš‘˜Kš‘˜K˜—Jšœ˜J™—šžœœœœ˜CJ™H˜#Kš‘˜Kš‘˜Kš‘˜Kš‘˜K˜—Jšœ˜J™—šž œœœœ˜FJ™R˜#Kš‘˜Kš‘˜Kš‘˜Kš‘˜K˜—Jšœ˜J™—šžœœœœ˜CJšœu™ušœ#˜#Kš‘˜Kš‘˜Kš‘˜Kš‘˜K˜—Jšœ˜J™—šžœœœœœœœ œ˜lJš œœœ œœ˜(Jš œœœ œœ˜(Jšœœ˜Jšœœ˜J˜J˜J˜šœœœ œ˜)J™0Jšœœœ ˜Jšœœœ ˜Jšœœ ˜šœ˜J˜ J˜Jšœ œ#˜4Jšœœ ˜ Jš˜—Jšœ˜—šœ˜J™0Jšœœœ ˜Jšœœœ ˜Jšœœ ˜šœ˜J˜ J˜Jšœ œ#˜4Jšœœ ˜ Jš˜—Jšœ˜—J˜J˜—šžœœœœ˜IJš œœœ œœ˜(Jš œœœ œœ˜(Jšœœ˜Jšœœ˜J˜šœœœ œ˜)J™0Jšœœœ ˜Jšœœœ ˜Jšœœ ˜šœ˜J˜ J˜Jšœ œ#˜4J˜ Jš˜—Jšœ˜—šœ˜J™0Jšœœœ ˜Jšœœœ ˜Jšœœ ˜šœ˜J˜ J˜Idefaultšœ œ#˜4L˜ Jš˜—Jšœ˜—J˜J˜—š ž œœ"œœœ˜iJšœ ˜J˜5J˜5J˜5J˜5J˜5J˜5J˜5J˜5J˜—Jšœ˜——…—j₯