FitState.mesa
Maureen Stone July 2, 1984 3:34:58 pm PDT
Changes the state of the FitState.Handle
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;
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;
};
};
Closed: PUBLIC PROC [handle: Handle, closed: BOOLEANTRUE] 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: 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];
};
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: 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.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: 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.