<<>> <> <> <> <> <<>> <> DIRECTORY Cubic USING [Bezier], Complex USING [VEC, Sub, Abs, Mul, Add], Seq USING [ComplexSequence, ComplexSequenceRec,JointSequence, JointSequenceRec], FitBasic, FitStateUtils, FitState; FitStateImpl: CEDAR PROGRAM IMPORTS Complex, FitStateUtils EXPORTS FitState = BEGIN Handle: TYPE = FitBasic.Handle; <> <> <> <> <> <> <<];>> <<>> SampleHandle: TYPE = FitBasic.SampleHandle; SListHandle: TYPE = FitBasic.SListHandle; LinkHandle: TYPE = FitBasic.LinkHandle; TrajHandle: TYPE = FitBasic.TrajHandle; Contour: TYPE = FitBasic.Contour; DataType: TYPE = FitState.DataType; VEC: TYPE = Complex.VEC; <<>> Create: PUBLIC PROC RETURNS [handle: Handle] = { handle ¬ NEW[FitBasic.Rec ¬ [ traj: NEW[FitBasic.Traj], slist: NEW[FitBasic.SList ¬ NewSList[]], closed: FALSE, minDist: 0, otherContours: NIL, undo: NIL ]]; }; NewSList: PROC RETURNS [s: FitBasic.SList] = { s.header ¬ NEW[FitBasic.Sample]; s.selectedSample ¬ s.header.next ¬ s.header.prev ¬ s.header; s.first ¬ NIL; s.last ¬ NIL; }; UnlinkSamples: PROC[slist: SListHandle] = { IF slist#NIL AND slist.header#NIL THEN { s,t: SampleHandle; s ¬ slist.header.next; UNTIL s = slist.header DO t ¬ s.next; s.next ¬ s.prev ¬ NIL; s ¬ t; ENDLOOP; slist.header.next ¬ slist.header.prev ¬ NIL; }; }; UnlinkLinks: PROC[traj: TrajHandle] = { IF traj #NIL THEN { l,t: LinkHandle; l ¬ traj.links; UNTIL l=NIL DO t ¬ l.next; l.next ¬l.prev ¬ NIL; l ¬ t; ENDLOOP; }; }; ResetData: PUBLIC PROC[handle: Handle, type: DataType, all: BOOLEAN ¬ FALSE] = { SELECT type FROM samples => { reset: FitStateUtils.SListProc = { UnlinkSamples[slist]; slist­ ¬ NewSList[]; }; [] ¬ reset[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,reset]; }; links => { reset: FitStateUtils.TrajProc = { UnlinkLinks[traj]; traj.links ¬ NIL; traj.lastLink ¬ NIL; }; [] ¬ reset[handle.traj]; IF all THEN FitStateUtils.ForAllOtherTrajs[handle,reset]; }; joints => { reset: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[handle.slist, ResetJoint]}; [] ¬ reset[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,reset]; }; contours => { ResetData[handle, samples, all]; ResetData[handle, links, all]; IF all THEN handle.otherContours ¬ NIL; }; ENDCASE => ERROR; }; ScaleData: PUBLIC PROC[handle: Handle, scale: REAL, type: DataType, all: BOOLEAN ¬ FALSE] = { XFormData[handle: handle, scale: [scale,scale], type: type, all: all]; }; TranslateData: PUBLIC PROC[handle: Handle, trans: VEC, type: DataType, all: BOOLEAN ¬ FALSE] = { XFormData[handle: handle, trans: trans, type: type, all: all]; }; XFormData: PROC[handle: Handle, scale: VEC ¬ [1,1], trans: VEC ¬ [0,0], type: DataType, all: BOOLEAN ¬ FALSE] = { xformSample: FitStateUtils.SampleProc = { p: VEC ¬ s.xy; s.xy ¬ Complex.Mul[p,scale]; p ¬ s.tanIn; s.tanIn ¬ Complex.Mul[p,scale]; p ¬ s.tanOut; s.tanOut ¬ Complex.Mul[p,scale]; }; SELECT type FROM samples => { xform: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[handle.slist,xformSample]}; [] ¬ xform[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,xform]; }; links => { xform: FitStateUtils.LinkProc = { cubic: Cubic.Bezier ¬ l.cubic; l.cubic.b0 ¬ Complex.Add[Complex.Mul[scale,cubic.b0], trans]; l.cubic.b1 ¬ Complex.Add[Complex.Mul[scale,cubic.b1], trans]; l.cubic.b2 ¬ Complex.Add[Complex.Mul[scale,cubic.b2], trans]; l.cubic.b3 ¬ Complex.Add[Complex.Mul[scale,cubic.b3], trans]; }; do: FitStateUtils.TrajProc = {FitStateUtils.ForAllLinks[handle.traj,xform]}; [] ¬ do[handle.traj]; IF all THEN FitStateUtils.ForAllOtherTrajs[handle,do]; }; joints => { xform: FitStateUtils.SampleProc = {IF s.jointType#none THEN [] ¬ xformSample[s]}; do: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[handle.slist,xform]}; [] ¬ do[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,do]; }; contours => { XFormData[handle, scale, trans, samples, all]; XFormData[handle, scale, trans, links, all]; }; ENDCASE => ERROR; }; AddSample: PUBLIC PROC[handle: Handle, x,y: REAL, joint: FitBasic.JointType ¬ none, tanIn,tanOut: Complex.VEC ¬ [0,0]] = { IF Complex.Abs[Complex.Sub[[x,y],handle.slist.header.prev.xy]]>handle.minDist THEN { update: BOOLEAN ¬ handle.slist.last=handle.slist.header.prev OR handle.slist.last=NIL; handle.slist.selectedSample ¬ handle.slist.header; InsertBeforeSample[handle, x,y, joint, tanIn, tanOut]; IF handle.slist.first=NIL THEN handle.slist.first ¬ handle.slist.header.next; IF update THEN handle.slist.last ¬ handle.slist.header.prev; }; }; RemoveSample: PUBLIC PROC[handle: Handle] = { IF handle.slist#NIL AND handle.slist.selectedSample # handle.slist.header THEN { sample: SampleHandle ¬ handle.slist.selectedSample; handle.slist.selectedSample ¬ sample.next; IF handle.slist.first=sample THEN handle.slist.first ¬ sample.next; IF handle.slist.last=sample THEN handle.slist.last ¬ sample.next; sample.prev.next ¬ sample.next; sample.next.prev ¬ sample.prev; sample.next ¬ sample.prev ¬ NIL; }; }; InsertBeforeSample: PUBLIC PROC[handle: Handle, x,y: REAL, joint: FitBasic.JointType ¬ none, tanIn,tanOut: Complex.VEC ¬ [0,0]] = { IF handle.slist#NIL THEN { s: SampleHandle ¬ handle.slist.selectedSample; new: SampleHandle ¬ NEW[FitBasic.Sample ¬ [ next: s, prev: s.prev, xy: [x,y], jointType: joint, tanIn: tanIn, tanOut: tanOut]]; s.prev ¬ new; new.prev.next ¬ new; handle.slist.selectedSample ¬ new; }; }; AddLink: PUBLIC PROC[handle: Handle, b: Cubic.Bezier] = { new: LinkHandle ¬ NEW[FitBasic.Link]; new.cubic ¬ b; IF handle.traj.links=NIL THEN { handle.traj.links ¬ new; handle.traj.lastLink ¬ new; } ELSE { handle.traj.lastLink.next ¬ new; new.prev ¬ handle.traj.lastLink; handle.traj.lastLink ¬ new; }; }; SetJoint: PUBLIC PROC[handle: Handle, index: NAT, joint: FitBasic.JointType ¬ potential, tanIn,tanOut: Complex.VEC ¬ [0,0]] = { i:NAT ¬ 0; FOR s: SampleHandle ¬ handle.slist.header.next, s.next UNTIL s=handle.slist.header DO IF i=index THEN {s.jointType ¬ joint; s.tanIn ¬ tanIn; s.tanOut ¬ tanOut; EXIT}; i¬i+1; ENDLOOP; }; ResetJoint: FitStateUtils.SampleProc = { s.jointType ¬ none; s.tanIn ¬ s.tanOut ¬ [0,0]; }; NewContour: PUBLIC PROC[handle: Handle] = { IF handle.otherContours = NIL THEN handle.otherContours ¬ LIST[[handle.traj, handle.slist]] ELSE { p: LIST OF Contour ¬ handle.otherContours; UNTIL p.rest = NIL DO p ¬ p.rest ENDLOOP; p.rest ¬ LIST[[handle.traj, handle.slist]]; }; handle.slist ¬ NEW[FitBasic.SList ¬ NewSList[]]; handle.traj ¬ NEW[FitBasic.Traj]; }; NextContour: PUBLIC PROC[handle: Handle] = { IF handle.otherContours # NIL THEN { p: LIST OF Contour ¬ handle.otherContours; ts: Contour ¬ handle.otherContours.first; handle.otherContours.first ¬ [handle.traj, handle.slist]; [handle.traj, handle.slist] ¬ ts; UNTIL p.rest = NIL DO p ¬ p.rest ENDLOOP; p.rest ¬ handle.otherContours; -- make it circular for a few microseconds p ¬ p.rest; handle.otherContours ¬ p.rest; p.rest ¬ NIL; } }; CurrentJoints: PUBLIC PROC [handle: Handle] RETURNS[joints: Seq.JointSequence, tangents: Seq.ComplexSequence] = { i,n:NAT ¬ 0; count: FitStateUtils.SampleProc = {IF s.jointType#none THEN n¬n+1}; copy: FitStateUtils.SampleProc = { IF s.jointType#none THEN { joints[n] ¬[index: i, forced: s.jointType=forced]; tangents[2*n] ¬ s.tanIn; tangents[2*n+1] ¬ s.tanOut; n¬n+1; }; i¬i+1; }; FitStateUtils.ForAllSamples[handle.slist,count]; joints ¬ IF n>0 THEN NEW[Seq.JointSequenceRec[n]] ELSE NIL; tangents ¬ IF n>0 THEN NEW[Seq.ComplexSequenceRec[2*n]] ELSE NIL; i ¬ n ¬ 0; FitStateUtils.ForAllSamples[handle.slist,copy]; }; CurrentSamples: PUBLIC PROC[handle: Handle] RETURNS [z: Seq.ComplexSequence] = { i,n:NAT ¬ 0; count: FitStateUtils.SampleProc = {n¬n+1}; copy: FitStateUtils.SampleProc = { z[i] ¬ s.xy; i¬i+1; }; FitStateUtils.ForAllSamples[handle.slist,count]; z ¬ NEW[Seq.ComplexSequenceRec[n]]; i ¬ 0; FitStateUtils.ForAllSamples[handle.slist,copy]; }; EnumerateLinks: PUBLIC PROC[handle: Handle, newContour: PROC[x,y: REAL], newCubic: PROC[c: Cubic.Bezier]] = { trajProc: FitStateUtils.TrajProc = { newContour[traj.links.cubic.b0.x, traj.links.cubic.b0.y]; FitStateUtils.ForAllLinks[traj,callCubic]; }; callCubic: FitStateUtils.LinkProc = {newCubic[l.cubic]}; --there's a defaulted return[false] FitStateUtils.ForAllTrajs[handle, trajProc]; }; EnumerateSamples: PUBLIC PROC[handle: Handle, newContour: PROC[x,y: REAL], newSample: PROC[x,y: REAL]] = { first: BOOLEAN ¬ TRUE; slistProc: FitStateUtils.SListProc = { first ¬ TRUE; FitStateUtils.ForAllSamples[slist,callNewSample]; }; callNewSample: FitStateUtils.SampleProc = { IF first THEN {newContour[s.xy.x, s.xy.y]; first ¬ FALSE} ELSE newSample[s.xy.x, s.xy.y]; }; FitStateUtils.ForAllSLists[handle, slistProc]; }; CountContours: PUBLIC PROC[handle: Handle] RETURNS [INT] = { i: INT ¬ 1; FOR p: LIST OF Contour ¬ handle.otherContours, p.rest UNTIL p=NIL DO i¬i+1 ENDLOOP; RETURN[i] }; END.