FitEditJaM.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Last Edited by Maureen Stone July 3, 1984 11:33:19 am PDT
Last Edited by Michael Plass December 7, 1982 10:25 am
Last Edited by: Stone, December 13, 1984 3:40:14 pm PST
Doug Wyatt, September 5, 1985 3:34:55 pm PDT
The point and link editing JaM commands
Display commands are in FitIOJaM
DIRECTORY
Cubic,
Complex,
FitState,
SafeStorage USING [ReclaimCollectibleObjects],
JaM,
FitJaM,
FitBasic,
FitStateUtils,
FitIO,
Real,
Rope,
Seq,
Vector;
FitEditJaM: CEDAR PROGRAM
IMPORTS Complex, JaM, Real, Vector, FitState, FitJaM, FitIO, FitStateUtils, SafeStorage
= {
State: TYPE = JaM.State;
GetVec: PROC [state: JaM.State] RETURNS [z:Complex.VEC] = {
z.y ← JaM.PopReal[state];
z.x ← JaM.PopReal[state];
};
ResetSa: PROC[state: State] = {FitState.ResetData[FitJaM.defaultFitState, samples, FALSE]};
ResetAllSa: PROC[state: State] = {FitState.ResetData[FitJaM.defaultFitState, samples, TRUE]};
AddSa: PROC[state: State] = {
y: REAL ← JaM.PopReal[state];
x: REAL ← JaM.PopReal[state];
FitState.AddSample[FitJaM.defaultFitState, x,y];
};
CountSa: PROC[state: State] = {
n: INT ← 0;
count: FitStateUtils.SampleProc = {n ← n+1};
FitStateUtils.ForAllSamples[FitJaM.defaultFitState.slist,count];
JaM.PushInt[state,n];
};
SelectSa: PROC [state: JaM.State] = {
closest: FitBasic.SampleHandle;
z: Complex.VEC;
z.y ← JaM.PopReal[state];
z.x ← JaM.PopReal[state];
[closest,] ← FindSa[z];
IF closest#NIL THEN FitJaM.defaultFitState.slist.selectedSample ← closest;
};
TheSa: PROC [state: JaM.State] = {
JaM.PushReal[state,FitJaM.defaultFitState.slist.selectedSample.xy.x];
JaM.PushReal[state,FitJaM.defaultFitState.slist.selectedSample.xy.y];
};
FindSa: PROC [z: Complex.VEC] RETURNS[found: FitBasic.SampleHandle, index: NAT] = {
closest,d: REAL ← 10.0E+30;
i: NAT ← 0;
do: FitStateUtils.SampleProc = {
p: Complex.VEC ← FitIO.MagnifyPoint[FitJaM.defaultFitIO, s.xy];
IF ABS[p.x-z.x]<closest AND ABS[p.y-z.y]<closest
AND (d ← Vector.Mag[Vector.Sub[z,p]]) < closest THEN {
closest ← d; found ← s; index ← i;
};
i ← i+1;
};
found ← NIL;
FitStateUtils.ForAllSamples[FitJaM.defaultFitState.slist,do];
};
TheTanIn: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState.slist.selectedSample;
JaM.PushReal[state,tanIn.x];
JaM.PushReal[state,tanIn.y];
JaM.PushBool[state,jointType#none];
};
TheTanOut: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState.slist.selectedSample;
JaM.PushReal[state,tanOut.x];
JaM.PushReal[state,tanOut.y];
JaM.PushBool[state,jointType#none];
};
DeleteSa: PROC [state: JaM.State] = {
FitState.RemoveSample[FitJaM.defaultFitState];
};
InsertSa: PROC [state: JaM.State] = {
x,y: REAL;
y ← JaM.PopReal[state];
x ← JaM.PopReal[state];
FitState.InsertBeforeSample[FitJaM.defaultFitState, x,y];
};
InsertBetween: PROC [state: JaM.State] = {
z: Complex.VEC;
insertBefore: BOOLEAN;
samp: FitBasic.SampleHandle ← FitJaM.defaultFitState.slist.selectedSample;
z.y ← JaM.PopReal[state];
z.x ← JaM.PopReal[state];
insertBefore ←
(Vector.Mag[Vector.Sub[z, samp.prev.xy]] < Vector.Mag[Vector.Sub[z, samp.next.xy]]);
IF insertBefore THEN FitState.InsertBeforeSample[FitJaM.defaultFitState, z.x, z.y]
ELSE {
FitJaM.defaultFitState.slist.selectedSample ← FitJaM.defaultFitState.slist.selectedSample.next;
FitState.InsertBeforeSample[FitJaM.defaultFitState, z.x, z.y];
FitJaM.defaultFitState.slist.selectedSample ← samp;
};
};
JointSa: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState;
slist.selectedSample.jointType ← SELECT JaM.PopInt[state] FROM 0 => none, 1 => potential, 2 => forced, ENDCASE => none;
};
TanIn: PROC [state: JaM.State] = {
FitJaM.defaultFitState.slist.selectedSample.tanIn ← GetVec[state]};
TanOut: PROC [state: JaM.State] = {
FitJaM.defaultFitState.slist.selectedSample.tanOut ← GetVec[state]};
ForceJoint: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState;
IF slist.selectedSample.jointType#none THEN
slist.selectedSample.jointType ← IF JaM.PopBool[state] THEN forced ELSE potential;
};
Closed: PROC [state: JaM.State] = {
FitJaM.defaultFitState.closed ← JaM.PopBool[state]};
HomeSa: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState;
slist.selectedSample ← slist.header;
};
MakeFirstSa: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState;
IF slist.selectedSample # NIL THEN {
slist.first ← slist.selectedSample;
slist.last ← slist.first.prev;
IF slist.last=slist.header THEN slist.last ← slist.last.prev;
};
};
NextSa: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState;
slist.selectedSample ← slist.selectedSample.next;
IF slist.selectedSample = slist.header THEN slist.selectedSample ← slist.selectedSample.next
};
PrevSa: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState;
slist.selectedSample ← slist.selectedSample.prev;
IF slist.selectedSample = slist.header THEN slist.selectedSample ← slist.selectedSample.prev
};
ScaleSa: PROC [state: JaM.State] = {
FitState.ScaleData[FitJaM.defaultFitState,JaM.PopReal[state], samples];
};
TranSa: PROC [state: JaM.State] = {
z: Complex.VEC ← GetVec[state];
FitState.TranslateData[FitJaM.defaultFitState, z, samples];
};
InterpolateSa: PROC[state: State] = { OPEN FitJaM.defaultFitState;
mindelta: REALMAX[JaM.PopReal[state], 0.00001];
selected: FitBasic.SampleHandle ← slist.selectedSample;
first: BOOLEANTRUE;
from: FitBasic.SampleHandle ← slist.header.next;
do: FitStateUtils.SampleProc = {
IF first THEN {from ← s; first ← FALSE}
ELSE {
to: FitBasic.SampleHandle ← s;
delta: Complex.VEC ← Complex.Sub[to.xy, from.xy];
k: REAL ← Real.RoundLI[Complex.Abs[delta]/mindelta];
slist.selectedSample ← to;
FOR i: REAL ← 1, i+1 UNTIL i>k DO
v: Complex.VEC ← Complex.Add[s.xy, Vector.Mul[delta, i/(k+1)]];
FitState.InsertBeforeSample[FitJaM.defaultFitState, v.x,v.y];
ENDLOOP;
from ← to;
};
};
FitStateUtils.ForAllSamples[slist, do];
IF closed THEN [] ← do[slist.header.next];
slist.selectedSample ← selected;
};
Subrange: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState;
first,last: FitBasic.SampleHandle;
p0,p1: Complex.VEC;
i0,i1: NAT;
p1.y ← JaM.PopReal[state];
p1.x ← JaM.PopReal[state];
[last,i1] ← FindSa[p1];
p0.y ← JaM.PopReal[state];
p0.x ← JaM.PopReal[state];
[first,i0] ← FindSa[p0];
IF i0<i1 THEN {slist.first ← first; slist.last ← last} ELSE {slist.first ← last; slist.last ← first};
};
NoSubrange: PROC [state: JaM.State] = {OPEN FitJaM.defaultFitState; slist.first ← slist.last ← NIL};
ResetJoints: PROC [state: JaM.State] = {FitState.ResetData[FitJaM.defaultFitState, joints]};
ResetForcedJoints: PROC [state: JaM.State] = {
reset: FitStateUtils.SampleProc = {IF s.jointType=forced THEN s.jointType ← potential};
FitStateUtils.ForAllSamples[FitJaM.defaultFitState.slist, reset];
};
ResetTangents: PROC [state: JaM.State] = {
type: INT ← JaM.PopInt[state];
reset: FitStateUtils.SampleProc = {
SELECT s.jointType FROM
potential => IF type=1 THEN {s.tanIn ← s.tanOut ← [0,0]};
forced => IF type=2 THEN {s.tanIn ← s.tanOut ← [0,0]};
ENDCASE => IF type=0 THEN {s.tanIn ← s.tanOut ← [0,0]}
};
FitStateUtils.ForAllSamples[FitJaM.defaultFitState.slist, reset];
};
ForAllLinks: PROC[state: State] = {
body: JaM.Any ← JaM.Pop[state];
do: FitStateUtils.LinkProc = {
JaM.PushReal[state,l.cubic.b0.x];
JaM.PushReal[state,l.cubic.b0.y];
JaM.PushReal[state,l.cubic.b1.x];
JaM.PushReal[state,l.cubic.b1.y];
JaM.PushReal[state,l.cubic.b2.x];
JaM.PushReal[state,l.cubic.b2.y];
JaM.PushReal[state,l.cubic.b3.x];
JaM.PushReal[state,l.cubic.b3.y];
JaM.Execute[state, body ! JaM.Stop => CONTINUE];
};
FitStateUtils.ForAllLinks[FitJaM.defaultFitState.traj,do];
};
ResetCon: PROC[state: State] = {FitState.ResetData[FitJaM.defaultFitState, contours, FALSE]};
ResetAllCon: PROC[state: State] = {FitState.ResetData[FitJaM.defaultFitState, contours, TRUE]};
CountCon: PROC[state: State] = {
JaM.PushInt[state, FitState.CountContours[FitJaM.defaultFitState]]};
AddCon: PROC[state: State] = {FitState.NewContour[FitJaM.defaultFitState]};
NextCon: PROC[state: State] = {FitState.NextContour[FitJaM.defaultFitState]};
SetSLen: PROC[state: State] = {FitState.SetMinDist[FitJaM.defaultFitState,JaM.PopReal[state]]};
CollectGarbage: PROC[state: State] = {
SafeStorage.ReclaimCollectibleObjects[suspendMe: TRUE, traceAndSweep: TRUE];
};
Init: FitJaM.InitProc = {
Sample Editing Commands
JaM.Register[state,".resetsa", ResetSa];
JaM.Register[state,".resetallsa", ResetAllSa];
JaM.Register[state,".addsa", AddSa];
JaM.Register[state,".countsa", CountSa];
JaM.Register[state,".selectsa", SelectSa]; -- x y => . Selects a sample point for editing
JaM.Register[state,".interpolatesa", InterpolateSa]; -- d => . Interpolates samples to make deltas no larger than about d
JaM.Register[state,".thesa", TheSa]; -- => x y . Returns the current sample
JaM.Register[state,".thetanin", TheTanIn]; -- => x y boolean . Returns the tanIn of the current sample, and whether it is a node
JaM.Register[state,".thetanout", TheTanOut]; -- => x y boolean . Returns the tanOut of the current sample, and whether it is a node
JaM.Register[state,".deletesa", DeleteSa]; -- => . Deletes the current sample
JaM.Register[state,".insertsa", InsertSa]; -- x y => . Inserts before the current sample
JaM.Register[state,".insertbetween", InsertBetween]; -- x y => . Inserts between the current sample and the neighbor nearest the new point
JaM.Register[state,".jointsa", JointSa]; -- type => . sets joint type: 0 (.false) = none, 1 (.true) = potential, 2 = forced
JaM.Register[state,".tanIn", TanIn]; -- deltax deltay => . Sets the tanIn at selected sample
JaM.Register[state,".tanOut", TanOut]; -- deltax deltay => . Sets the tanIn at selected sample
JaM.Register[state,".forcejoint", ForceJoint]; -- boolean => . flips between potential and forced
JaM.Register[state,".closed", Closed]; -- boolean => . Sets the closed bit on the samples
JaM.Register[state,".homesa", HomeSa]; -- => . Selects the header
JaM.Register[state,".makefirstsa", MakeFirstSa]; -- => . Selects the header
JaM.Register[state,".nextsa", NextSa]; -- => x y . Moves selection to the next sample
JaM.Register[state,".prevsa", PrevSa]; -- => x y . Moves selection to the previous sample
JaM.Register[state,".scalesa", ScaleSa]; -- x y => . Scales/rotates all samples by multiplying by x+iy
JaM.Register[state,".transa", TranSa]; -- x y => . Translates all samples by adding x+iy
JaM.Register[state,".subrange", Subrange]; -- change CurrentSamples so it returns a subrange
JaM.Register[state,".allsa", NoSubrange]; -- remove the subrange
JaM.Register[state,".resetjoints", ResetJoints]; -- remove the nodes
JaM.Register[state,".resetforcedjoints", ResetForcedJoints]; -- remove the corners
JaM.Register[state,".resettangents", ResetTangents]; -- type => remove the tangents type: 0 = all, 1 = potential only, 2 = forced only
JaM.Register[state,".foralllinks", ForAllLinks];
JaM.Register[state,".nextcon", NextCon];
JaM.Register[state,".resetcon", ResetCon];
JaM.Register[state,".resetallcon", ResetAllCon];
JaM.Register[state,".addcon", AddCon];
JaM.Register[state,".countcon", CountCon];
JaM.Register[state,".setslen", SetSLen];
JaM.Register[state,".collectgarbage", CollectGarbage];
};
FitJaM.RegisterInit[$FitEditJaM, Init];
}.
ScaleSa: PROC [state: JaM.State] = {
z: Complex.VEC ← GetVec[state];
FOR s: FitBasic.SampleHandle ← slist.header.next, s.next UNTIL s=slist.header DO
p:Complex.VEC ← s.xy;
s.xy ← Complex.Mul[p,z];
p ← s.tangent;
s.tangent ← Complex.Mul[p,z];
ENDLOOP;
};
JaM.Register[state,".cornersa", CornerSa]; -- => . moves the selected sample so it is colinear with its two left neightbors and with its two right neighbors
CornerSa: PROC = {OPEN Vector;
samp: SampleHandle ← IF FitJaM.defaultFitState.slist.selectedSample =
IF FitJaM.defaultFitState.slist.header THEN FitJaM.defaultFitState.slist.selectedSample.next
ELSE FitJaM.defaultFitState.slist.selectedSample;
p: SampleHandle ← IF samp.prev = FitJaM.defaultFitState.slist.header THEN samp.prev.prev ELSE samp.prev;
pp: SampleHandle ← IF p.prev = FitJaM.defaultFitState.slist.header THEN p.prev.prev ELSE p.prev;
n: SampleHandle ← IF samp.next = FitJaM.defaultFitState.slist.header THEN samp.next.next ELSE samp.next;
nn: SampleHandle ← IF n.next = FitJaM.defaultFitState.slist.header THEN n.next.next ELSE n.next;
a: VEC ← pp.xy;
b: VEC ← p.xy;
c: VEC ← nn.xy;
d: VEC ← n.xy;
coeffMat: Matrix ← [a.y-b.y, b.x-a.x, c.y-d.y, d.x-c.x];
r: VEC ← [Det[[b.x, b.y, a.x, a.y]], Det[[d.x, d.y, c.x, c.y]]];
denom: REAL ← Det[coeffMat];
xTimesDenom: REAL ← Det[[r.x, coeffMat.a12, r.y, coeffMat.a22]];
yTimesDenom: REAL ← Det[[coeffMat.a11, r.x, coeffMat.a21, r.y]];
IF denom=0 THEN RETURN;
samp.xy.x ← xTimesDenom/denom;
samp.xy.y ← yTimesDenom/denom;
};