DIRECTORY Cubic USING [Bezier], Complex USING [Vec, Sub, Abs, Mul, Add], Seq USING [ComplexSequence,NatSequence, NatSequenceRec, ComplexSequenceRec], 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; }; }; Closed: PUBLIC PROC [handle: Handle, closed: BOOLEAN _ TRUE] RETURNS [was: BOOLEAN] = { was _ handle.closed; handle.closed _ closed; RETURN[was]; }; MinDist: PUBLIC PROC [handle: Handle, minDist: REAL _ 0] RETURNS [was: REAL] = { was _ handle.minDist; handle.minDist _ minDist; RETURN[was]; }; 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]; }; nodes => { reset: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[handle.slist, ResetNode]}; [] _ reset[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,reset]; }; cusps => { reset: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[handle.slist, ResetCusp]}; [] _ reset[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,reset]; }; contour => { 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.tangent; s.tangent _ 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]; }; nodes => { xform: FitStateUtils.SampleProc = {IF s.isNode THEN [] _ xformSample[s]}; do: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[handle.slist,xform]}; [] _ do[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,do]; }; cusps => { xform: FitStateUtils.SampleProc = {IF s.isCusp THEN [] _ xformSample[s]}; do: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[handle.slist,xform]}; [] _ do[handle.slist]; IF all THEN FitStateUtils.ForAllOtherSLists[handle,do]; }; contour => { XFormData[handle, scale, trans, samples, all]; XFormData[handle, scale, trans, links, all]; }; ENDCASE => ERROR; }; AddSample: PUBLIC PROC[handle: Handle, x,y: REAL] = { IF Complex.Abs[Complex.Sub[[x,y],handle.slist.header.prev.xy]]>handle.minDist THEN { handle.slist.selectedSample _ handle.slist.header; InsertBeforeSample[handle, x,y]; }; }; 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] = { IF handle.slist#NIL THEN { s: SampleHandle _ handle.slist.selectedSample; new: SampleHandle _ NEW[FitBasic.Sample]; new.xy _ [x,y]; new.prev _ s.prev; new.next _ s; s.prev _ new; new.prev.next _ new; handle.slist.selectedSample _ new; }; }; StartSamples: PUBLIC PROC[handle: Handle, x,y: REAL] = { ResetData[handle, samples]; InsertBeforeSample[handle, x,y]; }; 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; }; }; AddNode: PUBLIC PROC[handle: Handle, index: NAT, tan: Vec _ [0,0]] = {OPEN handle^; i:NAT _ 0; FOR s: SampleHandle _ slist.header.next, s.next UNTIL s=slist.header DO IF i=index THEN {s.isNode _ TRUE; s.tangent _ tan; RETURN}; i_i+1; ENDLOOP; }; DeleteNode: PUBLIC PROC[handle: Handle, index: NAT] = {OPEN handle^; i:NAT _ 0; FOR s: SampleHandle _ slist.header.next, s.next UNTIL s=slist.header DO IF i=index THEN {[] _ ResetNode[s]; EXIT}; i_i+1; ENDLOOP; }; ResetNode: FitStateUtils.SampleProc = { s.isNode _ s.isCusp _ FALSE; s.tangent _ [0,0]; }; AddCusp: PUBLIC PROC[handle: Handle, index: NAT, tanIn,tanOut: Vec _ [0,0]] = {OPEN handle^; i:NAT _ 0; FOR s: SampleHandle _ slist.header.next, s.next UNTIL s=slist.header DO IF i=index THEN { s.isCusp _ s.isNode _ TRUE; s.tangent _ tanIn; s.tanOut _ tanOut; RETURN}; i_i+1; ENDLOOP; }; DeleteCusp: PUBLIC PROC[handle: Handle, index: NAT] = {OPEN handle^; i:NAT _ 0; FOR s: SampleHandle _ slist.header.next, s.next UNTIL s=slist.header DO IF i=index THEN {[] _ ResetCusp[s]; EXIT}; i_i+1; ENDLOOP; }; ResetCusp: FitStateUtils.SampleProc = { s.isCusp _ s.isNode _ FALSE; s.tangent _ 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; } }; CurrentNodes: PUBLIC PROC [handle: Handle] RETURNS[nodes: Seq.NatSequence, tangents: Seq.ComplexSequence] = { i,n:NAT _ 0; count: FitStateUtils.SampleProc = {IF s.isNode THEN n_n+1}; copy: FitStateUtils.SampleProc = { IF s.isNode THEN {nodes[n] _ i; tangents[n] _ s.tangent; n_n+1}; i_i+1; }; FitStateUtils.ForAllSamples[handle.slist,count]; nodes _ NEW[Seq.NatSequenceRec[n]]; tangents _ NEW[Seq.ComplexSequenceRec[n]]; 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]; }; CurrentCusps: PUBLIC PROC[handle: Handle] RETURNS[cusps: Seq.NatSequence, tangents: Seq.ComplexSequence] = {OPEN handle^; i,n:NAT _ 0; count: FitStateUtils.SampleProc = {IF s.isCusp THEN n_n+1}; copy: FitStateUtils.SampleProc = { IF s.isCusp THEN { cusps[n] _ i; tangents[2*n] _ s.tangent; tangents[2*n+1] _ s.tanOut; n_n+1; }; i_i+1; }; FitStateUtils.ForAllSamples[handle.slist,count]; cusps _ NEW[Seq.NatSequenceRec[n]]; tangents _ NEW[Seq.ComplexSequenceRec[2*n]]; i _ n _ 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. 2FitState.mesa Maureen Stone July 2, 1984 3:34:58 pm PDT Changes the state of the FitState.Handle Rec: PUBLIC TYPE = RECORD [ traj: TrajHandle, slist: SListHandle, closed: BOOLEAN, minDist: REAL, --affects AddSample. Won't add a new sample inside of this distance otherContours: LIST OF Contour ]; Ê T˜Jšœ ™ Jšœ)™)J™(šÏk ˜ Jšœœ ˜Jšœœ˜(JšœœC˜LJšœ ˜ J˜Jšœ ˜ J˜—šœœ˜Jšœ˜Jšœ ˜—Jš˜J˜šœœ˜šœœœœ™J™J™Jšœœ™Jšœ œÏcD™SJšœœœ™J™J™——Jšœœ˜+Jšœ œ˜)Jšœ œ˜'Jšœ œ˜'Jšœ œ˜!Jšœ œ˜#Jšœœ˜J™J˜šÏnœœœœ˜0šœ œ˜Jšœœ˜Jšœ œ˜(Jšœœ˜J˜ Jšœœ˜Jšœ˜ J˜—J˜J˜—šŸœœœ˜.Jšœ œ˜ J˜˜>J˜—šŸ œœNœœ˜qšœ)˜)Jšœ˜J˜J˜J˜!J˜J˜—šœ˜˜ JšœY˜YJšœ˜Jšœœ/˜:J˜—šœ ˜ šœ!˜!J˜Jšœ=˜=Jšœ=˜=Jšœ=˜=Jšœ=˜=Jšœ˜—JšœL˜LJ˜Jšœœ+˜6J˜—šœ ˜ Jšœ#œ œ˜IJšœP˜PJ˜Jšœœ,˜7J˜—šœ ˜ Jšœ#œ œ˜IJšœP˜PJ˜Jšœœ,˜7J˜—šœ ˜ J˜.J˜,J˜—Jšœœ˜—J˜J˜—šŸ œœœœ˜5šœL˜TJšœ3˜3Jšœ ˜ J˜—J˜J˜—šŸ œœœ˜-šœœœ3œ˜PJšœ3˜3Jšœ*˜*Jšœœ"˜CJšœœ!˜AJ˜J˜Jšœœ˜ J˜—J˜J˜—šŸœ œœ˜>šœœœ˜Jšœ.˜.Jšœœ˜)J˜J˜J˜ J˜ J˜Jšœ"˜"J˜—J˜J˜—šŸ œœœœ˜8Jšœ˜Jšœ ˜ Jšœ˜—J˜šŸœœœ%˜9Jšœœ˜%J˜šœœœ˜J˜J˜J˜—šœ˜J˜ J˜ J˜J˜—J˜J˜—J˜š Ÿœœœœœ ˜SJšœœ˜ šœ-œ˜GJšœ œ œœ˜;J˜Jšœ˜—J˜J˜—š Ÿ œœœœœ ˜DJšœœ˜ šœ-œ˜GJšœ œœ˜*J˜Jšœ˜—J˜J˜—J˜šÏb œ˜'Jšœœ˜Jšœ˜J˜J˜—š Ÿœœœœ œ ˜\Jšœœ˜ šœ-œ˜Gšœ œ˜Jšœœ˜J˜J˜Jšœ˜—J˜Jšœ˜—J˜J˜—š Ÿ œœœœœ ˜DJšœœ˜ šœ-œ˜GJšœ œœ˜*J˜Jšœ˜—J˜J˜—š  œ˜'Jšœœ˜J˜J˜J˜—šŸ œœœ˜+Jšœœœœ˜[šœ˜Jšœœœ ˜*Jšœ œœ œ˜)Jšœ œ˜+J˜—Jšœ œ˜0Jšœœ˜!J˜J˜—šŸ œœœ˜,šœœœ˜$Jšœœœ ˜*J˜)J˜9J˜!Jšœ œœ œ˜)Jšœž*˜IJ˜ J˜Jšœ œ˜ J˜—J˜J˜—šŸ œœœ˜*Jšœ;˜BJšœœ˜ Jšœ#œ œ˜;šœ"˜"Jšœ œ0˜@J˜Jšœ˜—J˜0Jšœœ˜#Jšœ œ˜*J˜ J˜/J˜J˜—J˜šŸœœœœ˜PJšœœ˜ Jšœ*˜*šœ"˜"J˜ J˜Jšœ˜—J˜0Jšœœ˜#J˜J˜/J˜J˜—J˜š Ÿ œœœœ;œ ˜yJšœœ˜ Jšœ#œ œ˜;šœ"˜"šœ œ˜J˜ J˜J˜J˜J˜—J˜Jšœ˜—J˜0Jšœœ˜#Jšœ œ˜,J˜ J˜/J˜J˜—š Ÿœœœœœ œ˜m˜$J˜9J˜*J˜—Jšœ9ž#˜\J˜,J˜J˜—š Ÿœ œœœœœ˜jJšœœœ˜˜&Jšœœ˜ Jšœ1˜1J˜—šœ+˜+Jšœœ&œ˜9Jšœ˜Jšœ˜—J˜.J˜—J˜š Ÿ œœœœœ˜