NodesAndFiltersJaM.mesa
JaM interfaces for Filters, Nodes and Tangents
Maureen Stone July 3, 1984 6:12:53 pm PDT
DIRECTORY
Seq,
Cubic USING [Bezier],
Complex USING [Vec],
Nodes,
Filters,
FitState USING [StartSamples, AddSample, CurrentSamples, Closed, CurrentNodes, AddNode, ResetData],
FitJaM USING [RegisterInit, InitProc, defaultFitState, ShowBezierInverted],
JaM;
NodesAndFiltersJaM: CEDAR PROGRAM
IMPORTS JaM, FitState, Filters, FitJaM, Nodes = {
SetSamples: PROC [samples: Seq.ComplexSequence, closed: BOOLEAN] = {
FitState.StartSamples[FitJaM.defaultFitState, samples[0].x,samples[0].y];
FOR i: NAT IN [1..samples.length) DO
FitState.AddSample[FitJaM.defaultFitState, samples[i].x,samples[i].y];
ENDLOOP;
[] ← FitState.Closed[FitJaM.defaultFitState, closed];
};
GetSamples: PROC RETURNS [samples: Seq.ComplexSequence, closed: BOOLEAN] = {
samples ← FitState.CurrentSamples[FitJaM.defaultFitState];
closedFitJaM.defaultFitState.closed;
RETURN[samples, closed];
};
GetCorners: PROC RETURNS [corners: Seq.NatSequence] = {
tangent: Seq.ComplexSequence;
node: Seq.NatSequence;
nCorners, nextCorner: NAT ← 0;
[node, tangent] ← FitState.CurrentNodes[FitJaM.defaultFitState];
FOR i: NAT IN [0..tangent.length) DO
IF tangent[i] = [0,0] THEN nCorners ← nCorners+1;
ENDLOOP;
corners ← NEW[Seq.NatSequenceRec[nCorners]];
FOR i: NAT IN [0..tangent.length) DO
IF tangent[i] = [0,0] THEN {
corners[nextCorner] ← node[i];
nextCorner ← nextCorner+1;
};
ENDLOOP;
};
SetNodes: PROC [nodes: Seq.NatSequence, tangents: Seq.ComplexSequence] = {
FitState.ResetData[FitJaM.defaultFitState, nodes];
FitState.AddNode[FitJaM.defaultFitState, 0];
IF tangents#NIL THEN FOR i:NAT IN [0..nodes.length) DO
FitState.AddNode[FitJaM.defaultFitState, nodes[i], tangents[i]];
ENDLOOP
ELSE FOR i:NAT IN [0..nodes.length) DO
FitState.AddNode[FitJaM.defaultFitState, nodes[i], [0,0]];
ENDLOOP;
};
Dynfilter: PROC [state: JaM.State] = {
samples: Seq.ComplexSequence;
closed: BOOLEAN;
tolerance: REAL ← JaM.PopReal[state];
badness: REAL;
[samples,closed] ← GetSamples[];
IF samples=NIL THEN RETURN;
[samples, badness] ← Filters.Dynfilter[samples, closed, tolerance];
SetSamples[samples, closed];
JaM.PushReal[state, badness];
};
AveFilter: PROC [state: JaM.State] = {
samples: Seq.ComplexSequence;
closed: BOOLEAN;
[samples,closed] ← GetSamples[];
IF samples=NIL THEN RETURN;
samples ← Filters.AveFilter[samples, closed];
SetSamples[samples, closed];
};
AveFilterLeavingCorners: PROC [state: JaM.State] = {
samples: Seq.ComplexSequence;
corners: Seq.NatSequence;
closed: BOOLEAN;
[samples,closed] ← GetSamples[];
IF samples=NIL THEN RETURN;
corners ← GetCorners[];
samples ← Filters.AveFilterLeavingCorners[samples: samples, closed: closed, corners: corners];
SetSamples[samples, closed];
};
DynNodes: PROC [state: JaM.State] = {-- penalty => . Finds nodes using DynFit
nodes: Seq.NatSequence;
closed: BOOLEAN;
samples: Seq.ComplexSequence;
[samples,closed] ← GetSamples[];
nodes ← Nodes.DynNodes[samples: samples, closed: closed, penalty: JaM.PopReal[state]];
SetNodes[nodes, NIL];
};
CubicTangents: PROC[state: JaM.State] = {-- range err maxit => . Sets tangents at nodes by locally fitting a cubic between neighboring nodes
maxit: NAT ← JaM.PopInt[state];
err: REAL ← JaM.PopReal[state];
nodes: Seq.NatSequence;
samples, tangents: Seq.ComplexSequence;
closed: BOOLEAN;
nodeIndex, nextNode: NAT ← 0;
lastCubic: Cubic.Bezier ← [[-1,-1],[-1,-1],[-1,-1],[-1,-1]];
newTangent: Nodes.Progress = {
FitJaM.ShowBezierInverted[state, lastCubic];
FitJaM.ShowBezierInverted[state, cubic];
FitState.AddNode[FitJaM.defaultFitState, nextNode, tangent];
nextNode ← nodes[nodeIndex];
nodeIndex ← nodeIndex+1;
RETURN[JaM.GetAbort[state]];
};
[samples,closed] ← GetSamples[];
[nodes,] ← FitState.CurrentNodes[FitJaM.defaultFitState];
nodeIndex ← 0;
nextNode ← nodes[nodeIndex];
tangents ← NEW[Seq.ComplexSequenceRec[nodes.length]];
Nodes.ICubicTangents[newTangent, samples, closed, err, maxit, nodes]; --calls newTangent in a loop
FitJaM.ShowBezierInverted[state, lastCubic];
};
QuickTangents: PROC[state: JaM.State] = {-- maxAngle => . computes tangents by differencing neighbors
maxAngle: REAL ← JaM.PopReal[state];
nodes: Seq.NatSequence;
samples, tangents: Seq.ComplexSequence;
closed: BOOLEAN;
[samples,closed] ← GetSamples[];
[nodes,] ← FitState.CurrentNodes[FitJaM.defaultFitState];
tangents ← Nodes.QuickTangents[samples, closed, maxAngle, nodes];
SetNodes[nodes,tangents];
};
SquareTangents: PROC[state: JaM.State] = {-- maxAngle => . computes tangents, weighting the longer edges more
maxAngle: REAL ← JaM.PopReal[state];
nodes: Seq.NatSequence;
samples, tangents: Seq.ComplexSequence;
closed: BOOLEAN;
[samples,closed] ← GetSamples[];
[nodes,] ← FitState.CurrentNodes[FitJaM.defaultFitState];
tangents ← Nodes.SquareTangents[samples, closed, maxAngle, nodes];
SetNodes[nodes,tangents];
};
Init: FitJaM.InitProc = {
JaM.Register[state, ".dfsa",Dynfilter];
JaM.Register[state, ".afsa",AveFilter];
JaM.Register[state, ".filterbetweencorners",AveFilterLeavingCorners];
JaM.Register[state, ".dynnodes",DynNodes]; -- penalty => . Finds nodes using DynFit
JaM.Register[state, ".cubictangents",CubicTangents]; -- err maxit => . Sets tangents at nodes by fitting between neighboring nodes.
JaM.Register[state, ".quicktangents",QuickTangents]; -- maxangle => . computes tangents by differencing neighbors.
JaM.Register[state, ".squaretangents",SquareTangents]; -- maxangle => . computes tangents, weighting the longer edges more.
};
FitJaM.RegisterInit[id: $NodesAndFiltersJaM, proc: Init];
}.