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];
closedFitState.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];
}.