FitStateImpl.mesa
Copyright © 1985 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: BOOLEANFALSE] = {
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: BOOLEANFALSE] = {
XFormData[handle: handle, scale: [scale,scale], type: type, all: all];
};
TranslateData: PUBLIC PROC[handle: Handle, trans: VEC, type: DataType, all: BOOLEANFALSE] = {
XFormData[handle: handle, trans: trans, type: type, all: all];
};
XFormData: PROC[handle: Handle, scale: VEC ← [1,1], trans: VEC ← [0,0], type: DataType, all: BOOLEANFALSE] = {
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: BOOLEANTRUE;
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.