<> <> <> 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]; closed _ FitJaM.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]; }.