FitStateImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Maureen Stone February 14, 1985 5:18:35 pm PST
Doug Wyatt, September 5, 1985 1:58:49 pm PDT
Changes the state of the FitState.Handle
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;
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
];
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.