NodesAndFiltersJaM.mesa
JaM interfaces for Filters, Nodes and Tangents
Maureen Stone October 30, 1984 7:10:11 pm PST
DIRECTORY
Seq,
Cubic USING [Bezier],
Complex USING [Vec],
LSPiece USING [Metrics, MetricsRec],
Nodes,
Filters,
FitState USING [StartSamples, AddSample, CurrentSamples, SetClosed, GetClosed, CurrentNodes, CurrentCorners, AddCorner, AddNode, ResetData],
FitJaM USING [RegisterInit, InitProc, defaultFitState, defaultHighlight],
Highlight USING [ShowBezier, CleanUp],
JaM;
NodesAndFiltersJaM:
CEDAR
PROGRAM
IMPORTS JaM, FitState, Filters, FitJaM, Nodes, Highlight = {
GetSamples:
PROC RETURNS [samples: Seq.ComplexSequence, closed:
BOOLEAN] = {
samples ← FitState.CurrentSamples[FitJaM.defaultFitState];
closed ← FitState.GetClosed[FitJaM.defaultFitState];
RETURN[samples, closed];
};
SetSamples:
PROC [samples: Seq.ComplexSequence, closed:
BOOLEAN] = {
tangents, ctangents: Seq.ComplexSequence;
nodes, corners: Seq.NatSequence;
[corners, ctangents] ← GetCorners[];
[nodes, tangents] ← GetNodes[];
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.SetClosed[FitJaM.defaultFitState, closed];
SetNodes[nodes, tangents];
SetCorners[corners, ctangents];
};
GetCorners:
PROC
RETURNS[corners: Seq.NatSequence, tangents: Seq.ComplexSequence] = {
[corners, tangents] ← FitState.CurrentCorners[FitJaM.defaultFitState];
};
SetCorners:
PROC[corners: Seq.NatSequence, tangents: Seq.ComplexSequence] = {
FitState.ResetData[FitJaM.defaultFitState, corners];
FOR i:
NAT
IN [0..corners.length)
DO
FitState.AddCorner[FitJaM.defaultFitState, corners[i], [tangents[i].x, tangents[i].y], [tangents[i+1].x, tangents[i+1].y]];
ENDLOOP;
};
GetNodes:
PROC
RETURNS[nodes: Seq.NatSequence, tangents: Seq.ComplexSequence] = {
[nodes, tangents] ← FitState.CurrentNodes[FitJaM.defaultFitState];
};
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]];
IF tangents[i]=[0,0] THEN FitState.AddCorner[FitJaM.defaultFitState, nodes[i], [0,0], [0,0]];
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];
};
metrics: LSPiece.Metrics ← NEW[LSPiece.MetricsRec];
CubicTangents:
PROC[state: JaM.State] = {
-- range err maxit => . Sets tangents at nodes by locally fitting a cubic between neighboring nodes
nodes: Seq.NatSequence;
samples, tangents: Seq.ComplexSequence;
closed: BOOLEAN;
nodeIndex: NAT ← 0;
newTangent: Nodes.Progress = {
Highlight.ShowBezier[FitJaM.defaultHighlight, cubic];
FitState.AddNode[FitJaM.defaultFitState, nodes[nodeIndex], tangent];
nodeIndex ← nodeIndex+1;
RETURN[JaM.GetAbort[state]];
};
metrics.maxItr ← JaM.PopInt[state];
metrics.sumErr ← JaM.PopReal[state];
[samples,closed] ← GetSamples[];
[nodes,] ← FitState.CurrentNodes[FitJaM.defaultFitState];
nodeIndex ← 0;
tangents ← NEW[Seq.ComplexSequenceRec[nodes.length]];
Nodes.ICubicTangents[newTangent, samples, closed, metrics, nodes]; --calls newTangent in a loop
Highlight.CleanUp[FitJaM.defaultHighlight];
SetNodes[nodes,tangents];
};
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];
}.