--DCubicsSub.mesa
--m.stone September 30, 1980 6:42 PM
DIRECTORY
PointDefs: FROM "PointDefs",
Real: FROM "Real",
InlineDefs: FROM "InlineDefs",
SplineDefs: FROM "SplineDefs";

DCubicsSub: PROGRAM IMPORTS Real,InlineDefs EXPORTS SplineDefs =
BEGIN OPEN SplineDefs,PointDefs;

Vals: TYPE=
RECORD[Fx: LONG INTEGER, Cx: LONG INTEGER, Fy: LONG INTEGER, Cy: LONG INTEGER];
PutPt: PROCEDURE[PointDefs.ScrPt];

scaler: LONG INTEGER ← 200000B;
tol: LONG INTEGER ← scaler/2;

DisplayCubic: PUBLIC PROCEDURE
[coeffs: POINTER TO Coeffs,
MoveTo: PROCEDURE[PointDefs.ScrPt],
DrawTo: PROCEDURE[PointDefs.ScrPt]] =
BEGIN
ONE: REAL ← 1; E2: REAL ← 100;
pt: ScrPt;
val0,val1: Vals;
--set initial values. assume t0=0, t1=1 deltaT**2=1
--F[0], F[1], C ← deltaT↑2*(6at+2b)/2
val0 ← Vals[Real.RoundLI[scaler*coeffs.t0[X]],
Real.RoundLI[scaler*coeffs.t2[X]],
Real.RoundLI[scaler*coeffs.t0[Y]],
Real.RoundLI[scaler*coeffs.t2[Y]]];
val1 ← Vals[Real.RoundLI[scaler*(coeffs.t3[X]+coeffs.t2[X]+coeffs.t1[X]+coeffs.t0[X])],
Real.RoundLI[scaler*(3*coeffs.t3[X]+coeffs.t2[X])],
Real.RoundLI[scaler*(coeffs.t3[Y]+coeffs.t2[Y]+coeffs.t1[Y]+coeffs.t0[Y])],
Real.RoundLI[scaler*(3*coeffs.t3[Y]+coeffs.t2[Y])]];
--do first MoveTo
pt[X] ← DoubleToInt[val0.Fx];
pt[Y] ← DoubleToInt[val0.Fy];
MoveTo[pt];
PutPt ← DrawTo;
DrawCurve[val0, val1];
pt[X] ← DoubleToInt[val1.Fx];
--seems to be necessary
pt[Y] ← DoubleToInt[val1.Fy];
DrawTo[pt];
END;

--recursive subdivision
DrawCurve: PROCEDURE[val1: Vals, val2: Vals ]=
BEGIN
x1,x2,y1,y2: INTEGER;
pt: ScrPt;
DO
x1 ← DoubleToInt[val1.Fx]; x2 ← DoubleToInt[val2.Fx];
y1 ← DoubleToInt[val1.Fy];
y2 ← DoubleToInt[val2.Fy];
SELECT TRUE FROM
(ABS[val1.Cx] < tol AND ABS[val1.Cy] < tol AND ABS[val2.Cx] < tol AND ABS[val2.Cy] < tol) => BEGIN
pt ← [x2,y2];--compiler error if use constuctor in arg list
PutPt[pt];
RETURN;
END;
(ABS[x1-x2] <=1 AND ABS[y1-y2] <=1) => BEGIN
pt ← [x2,y2];--compiler error if use constuctor in arg list
PutPt[pt];
RETURN;
END;
ENDCASE => BEGIN
valc: Vals;
val1.Cx ←DoubleHalve[DoubleHalve[ val1.Cx]]; val2.Cx ← DoubleHalve[DoubleHalve[val2.Cx]];
valc.Cx ← DoubleHalve[(val1.Cx+val2.Cx)];
valc.Fx ← DoubleHalve[val1.Fx+val2.Fx] - valc.Cx;
val1.Cy ←DoubleHalve[DoubleHalve[ val1.Cy]]; val2.Cy ← DoubleHalve[DoubleHalve[val2.Cy]];
valc.Cy ← DoubleHalve[(val1.Cy+val2.Cy)];
valc.Fy ← DoubleHalve[val1.Fy+val2.Fy] - valc.Cy;
DrawCurve[val1,valc];
val1 ←valc;--instead of a second call to DrawCurve
END;
ENDLOOP;
END;


--round a Double to an INTEGER
DoubleToInt: PROCEDURE[double: LONG INTEGER] RETURNS[i: INTEGER] =
INLINE BEGIN OPEN InlineDefs;
i ← HighHalf[double]+(IF CARDINAL[LowHalf[double]] > 77777B THEN 1 ELSE 0);
END;

DoubleHalve: PROCEDURE [dint: LONG INTEGER] RETURNS [dintover2: LONG INTEGER] =
INLINE BEGIN OPEN InlineDefs;
ln: LongNumber; ln.li ← dint;
ln.lowbits ← BITSHIFT[ln.lowbits,-1] + (IF ln.highbits MOD 2 = 1 THEN 100000B ELSE 0);
ln.highbits ← BITSHIFT[ln.highbits,-1] + (IF ln.highbits > 77777B THEN 100000B ELSE 0);
dintover2 ← ln.li;
END;


END.