LSSplineImpl.mesa
last edited by Michael Plass August 4, 1982 10:19 am
DIRECTORY Complex, Cubic, LSPiece, Seq, Vector, LSSpline;
LSSplineImpl: CEDAR PROGRAM IMPORTS LSPiece EXPORTS LSSpline =
BEGIN
Handle: TYPE = LSSpline.Handle;
Rec: TYPE = LSSpline.Rec;
Create: PUBLIC PROCEDURE [lengthHint: NAT ← 10] RETURNS [handle: Handle] = {
handle ← NEW[Rec];
handle.z ← NEW[Seq.ComplexSequenceRec[lengthHint]];
handle.tan ← NEW[Seq.ComplexSequenceRec[lengthHint]];
handle.t ← NEW[Seq.RealSequenceRec[lengthHint]];
handle.length ← 0;
};
Reset: PUBLIC PROCEDURE [handle: Handle] = {handle.length ← 0};
Sample: PUBLIC PROCEDURE [handle: Handle, samplePoint, tangent: Complex.Vec ← [0,0]] = {
WHILE handle.length >= handle.z.length DO
temp: Handle ← Create[handle.length + handle.length/2 + 1];
FOR i:NAT IN [0..handle.length) DO
Sample[temp, handle.z[i], handle.tan[i]];
ENDLOOP;
handle^ ← temp^;
ENDLOOP;
handle.z[handle.length] ← samplePoint;
handle.tan[handle.length] ← tangent;
handle.length ← handle.length + 1;
};
CubicProc: TYPE = PROCEDURE [Cubic.Bezier];
Subdivide: PUBLIC PROCEDURE [handle: Handle, cubicProc: CubicProc, tolerance: REAL, from: NAT ← 0, thru: NATLAST[NAT]] = {
b: Cubic.Bezier;
err: REAL;
iterations: NAT;
maxDev: REAL;
IF handle.length = 0 THEN RETURN;
thru ← MIN[thru, handle.length - 1];
IF from >= thru THEN RETURN;
IF thru = from+1 THEN {
b0: Vector.Vec ← handle.z[from];
b3: Vector.Vec ← handle.z[thru];
cubicProc[[b0, b0, b3, b3]];
RETURN;
};
[b, err, iterations, maxDev] ← LSPiece.FitPiece[
z: handle.z,
t: handle.t,
from: from,
thru: thru,
maxd: tolerance,
maxit: firstTryIterationLimit,
initTangent: handle.tan[from],
finalTangent: handle.tan[thru]
];
stats.firstTryCount ← stats.firstTryCount + 1;
stats.firstTryIterations ← stats.firstTryIterations + iterations;
IF maxDev <= tolerance*firstTryToleranceFactor THEN {
[b, err, iterations, maxDev] ← LSPiece.FitPiece[
z: handle.z,
t: handle.t,
from: from,
thru: thru,
maxd: tolerance/secondTryOptimistFactor,
maxit: secondTryIterationLimit,
initTangent: handle.tan[from],
finalTangent: handle.tan[thru],
useOldTValues: TRUE
];
stats.secondTryCount ← stats.secondTryCount + 1;
stats.secondTryIterations ← stats.secondTryIterations + iterations;
};
IF maxDev <= tolerance THEN cubicProc[b]
ELSE {
mid: NAT ← (from+thru)/2;
Subdivide[handle, cubicProc, tolerance, from, mid];
Subdivide[handle, cubicProc, tolerance, mid, thru];
};
};
firstTryIterationLimit: NAT ← 3;
firstTryToleranceFactor: REAL ← 3.0;
secondTryIterationLimit: NAT ← 20;
secondTryOptimistFactor: REAL ← 2.0;
stats: RECORD [
firstTryCount: INT ← 0,
firstTryIterations: INT ← 0,
secondTryCount: INT ← 0,
secondTryIterations: INT ← 0
];
END.