FitIOImpl.mesa
Maureen Stone July 3, 1984 12:26:46 pm PDT
DIRECTORY
ImagerBasic,
Imager USING [Context, CurveTo, LineTo, MoveTo, MaskStroke, MaskStrokeClosed, MaskFill, Trajectory, MaskVector, SetColor, white],
FitIO,
FitStateUtils,
FitBasic USING[SampleHandle, SListHandle, Handle, LinkHandle, TrajHandle],
FitState USING [Handle],
Complex USING [Vec, Mul, Sub, Add],
Vector USING [Unit],
Rope USING [ROPE],
IO USING [STREAM, Close, Put, real, char, int, rope, SP, CR];
FitIOImpl: CEDAR PROGRAM
IMPORTS Imager, IO, Complex, Vector, FitStateUtils
EXPORTS FitIO = { OPEN FitIO;
Handle: TYPE = FitState.Handle;
current: Context;
GetContext: PUBLIC PROC RETURNS [Context] = {RETURN[current]};
SetContext: PUBLIC PROC[context: Context] = {current ← context};
SetFeedback: PUBLIC PROC[feedback: Feedback] = {
current.feedback ← feedback;
IF current.logActions THEN { --print feedback
SELECT feedback.color FROM
Imager.white => PrintRope["white "];
ENDCASE=> PrintRope["black"];
PrintLine["FB.color"];
PrintReal[feedback.sampleSize]; PrintLine["Fit.sampleSize"];
PrintReal[feedback.jointSize]; PrintLine["Fit.jointSize"];
PrintReal[feedback.nodeLength]; PrintLine["Fit.nodeLength"];
PrintReal[feedback.nodeLineWidth]; PrintLine["Fit.nodeLineWidth"];
PrintReal[feedback.lineWidth]; PrintLine["Fit.lineWidth"];
};
};
DrawSamples: PUBLIC PROC [handle: Handle, all: BOOLEANFALSE, fill: BOOLEANFALSE] = {
treat samples as vertices of a polygon or a broken line
list: LIST OF Imager.Trajectory;
traj: Imager.Trajectory ← PathFromSList[handle.slist];
IF traj=NIL THEN RETURN ELSE list ← CONS[traj,list];
Imager.SetColor[current.imager, current.feedback.color];
IF all THEN {
makeList: FitStateUtils.SListProc = {list ← CONS[PathFromSList[slist],list]};
FitStateUtils.ForAllOtherSLists[handle,makeList];
};
IF fill THEN MaskFill[list]
ELSE
IF handle.closed THEN MaskStrokeClosed[list]
ELSE MaskStroke[list];
IF current.logActions THEN PrintLine["\n"];
};
DrawContour: PUBLIC PROC [handle: Handle, all: BOOLEANFALSE, fill: BOOLEANFALSE] = {
traj: Imager.Trajectory ← PathFromTraj[handle.traj];
list: LIST OF Imager.Trajectory;
IF traj=NIL THEN RETURN ELSE list ← CONS[traj,list];
Imager.SetColor[current.imager, current.feedback.color];
IF all THEN {
makeList: FitStateUtils.TrajProc = {list ← CONS[PathFromTraj[traj],list]};
FitStateUtils.ForAllOtherTrajs[handle,makeList];
};
IF fill THEN MaskFill[list]
ELSE
IF handle.closed OR all THEN MaskStrokeClosed[list]
ELSE MaskStroke[NARROW[list]];
IF current.logActions THEN PrintLine["\n"];
};
PathFromSList: PROC [slist: FitBasic.SListHandle] RETURNS [path: Imager.Trajectory] = {
treat samples as vertices of a polygon or a broken line
first: BOOLEANTRUE;
do: FitStateUtils.SampleProc = {
IF first THEN {path ← MoveTo[s.xy]; first ← FALSE}
ELSE path← LineTo[path,s.xy];
};
FitStateUtils.ForAllSamples[slist, do];
IF current.logActions AND path#NIL THEN PrintLine["\n"];
RETURN[path];
};
PathFromTraj: PROC [traj: FitBasic.TrajHandle] RETURNS [path: Imager.Trajectory] = {
convert my trajectory to an imager.trajectory
first: BOOLEANTRUE;
do: FitStateUtils.LinkProc = {
IF first THEN {path ← MoveTo[l.cubic.b0]; first ← FALSE};
path ← CurveTo[path,l.cubic.b1,l.cubic.b2,l.cubic.b3];
};
FitStateUtils.ForAllLinks[traj, do];
IF current.logActions AND path#NIL THEN PrintLine["\n"];
};
MarkSamples: PUBLIC PROC [handle: Handle, all: BOOLEANFALSE] = {
markSamples: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[slist, MarkSample]};
[] ← markSamples[handle.slist];
IF all THEN FitStateUtils.ForAllOtherSLists[handle, markSamples];
IF current.logActions THEN PrintLine["\n"];
};
MarkNodes: PUBLIC PROC [handle: Handle, all: BOOLEANFALSE] = {
markNodes: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[slist, MarkNode]};
[] ← markNodes[handle.slist];
IF all THEN FitStateUtils.ForAllOtherSLists[handle, markNodes];
IF current.logActions THEN PrintLine["\n"];
};
MarkJoints: PUBLIC PROC [handle: Handle, all: BOOLEANFALSE] ={
--joints between the cubic pieces
[] ← MarkTrajJoints[handle.traj];
IF all THEN FitStateUtils.ForAllOtherTrajs[handle, MarkTrajJoints];
IF current.logActions THEN PrintLine["\n"];
};
MarkTrajJoints: FitStateUtils.TrajProc = {
first: BOOLEANTRUE;
do: FitStateUtils.LinkProc = {
IF first THEN {MarkJoint[l.cubic.b0]; first ← FALSE};
MarkJoint[l.cubic.b3];
};
FitStateUtils.ForAllLinks[traj, do];
IF current.logActions THEN PrintLine["\n"];
};
FeedbackRec: TYPE=RECORD [
color: Imager.Color ← black,
sampleSize: REAL ← 1,
jointSize: REAL ← 2,
nodeLength: REAL ← 2,
nodeLineWidth: REAL ← 0,
lineWidth: REAL ← 0--for DrawSamples and DrawContour
];
MarkNode: PUBLIC FitStateUtils.SampleProc = {
d:REAL ← current.feedback.nodeLength;
width: REAL ← current.feedback.nodeLineWidth;
pt: Complex.Vec ← MagnifyPoint[s.xy];
IF current.logActions THEN PrintPoint[pt];
IF s.isCusp THEN d ← 1.5*d;
IF s.tangent = [0,0] THEN {
x: REAL ← s.xy.x;
y: REAL ← s.xy.y;
Imager.MaskVector[current.imager, [x+d,y+d], [x-d,y-d], width];
Imager.MaskVector[current.imager, [x-d,y+d], [x+d,y-d], width];
}
ELSE {
t: Complex.Vec ← Complex.Mul[Vector.Unit[s.tangent],[0,2*d]];
mdt: Complex.Vec ← Complex.Sub[s.xy,t];
adt: Complex.Vec ← Complex.Add[s.xy,t];
Imager.MaskVector[current.imager, [mdt.x, mdt.y], [adt.x,adt.y], width];
IF s.isCusp THEN {
t ← Complex.Mul[Vector.Unit[s.tanOut],[0,2*d]];
mdt ← Complex.Sub[s.xy,t];
adt ← Complex.Add[s.xy,t];
Imager.MaskVector[current.imager, [mdt.x, mdt.y],[adt.x,adt.y],width];
IF current.logActions THEN PrintRope["Fit.cusp "];
}
ELSE {IF current.logActions THEN PrintRope["Fit.node "]};
};
};
MarkSample: PUBLIC FitStateUtils.SampleProc = {
size: REAL ← current.feedback.sampleSize;
pt: Complex.Vec ← MagnifyPoint[s.xy];
traj: Imager.Trajectory ← Imager.MoveTo[[pt.x, pt.y]];
traj ← Imager.LineTo[traj,[pt.x, pt.y]];
Imager.MaskStroke[current.imager,traj, size, round];
Imager.MaskRectangle[current.imager,pt.x,pt.y,size,size];
IF current.logActions THEN {PrintPoint[pt]; PrintRope["Fit.mark "]};
};
MarkJoint: PROC[pt: Complex.Vec] = {
size: REAL ← current.feedback.jointSize;
traj: Imager.Trajectory;
pt ← MagnifyPoint[pt];
traj ← Imager.MoveTo[[pt.x, pt.y]];
traj ← Imager.LineTo[traj,[pt.x, pt.y]];
Imager.MaskStroke[current.imager,traj, size, round];
Imager.MaskRectangle[current.imager,pt.x,pt.y,size,size];
IF current.logActions THEN {PrintPoint[pt]; PrintRope["Fit.joint "]};
};
MoveTo: PROC[p: Complex.Vec] RETURNS [path: Imager.Trajectory]= {
p ← MagnifyPoint[p];
path ← Imager.MoveTo[[p.x,p.y]];
IF current.logActions THEN {PrintPoint[p]; PrintRope["Fit.moveto"]};
RETURN[path];
};
LineTo: PROC[path: Imager.Trajectory, p: Complex.Vec] RETURNS [Imager.Trajectory]= {
p ← MagnifyPoint[p];
path ← Imager.LineTo[path, [p.x,p.y]];
IF current.logActions THEN {PrintPoint[p]; PrintRope["Fit.lineto "]};
RETURN[path];
};
CurveTo: PROC[path: Imager.Trajectory, p1,p2,p3: Complex.Vec] RETURNS [Imager.Trajectory] = {
p1 ← MagnifyPoint[p1];
p2 ← MagnifyPoint[p2];
p3 ← MagnifyPoint[p3];
path ← Imager.CurveTo[path,[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y]];
IF current.logActions THEN {
PrintPoint[p1];
PrintPoint[p2];
PrintPoint[p3];
PrintLine["Fit.curveto "];
};
RETURN[path];
};
MaskStroke: PROC[list: LIST OF Imager.Trajectory] = {
width: REAL ← current.feedback.lineWidth;
count: INT ← 0;
FOR l: LIST OF Imager.Trajectory ← list, list.rest UNTIL l=NIL DO
Imager.MaskStroke[current.imager,l.first,width];
count ← count+1;
ENDLOOP;
IF current.logActions THEN {PrintInt[count]; PrintLine["Fit.maskstroke"]};
};
MaskStrokeClosed: PROC[list: LIST OF Imager.Trajectory] = {
width: REAL ← current.feedback.lineWidth;
count: INT ← 0;
FOR l: LIST OF Imager.Trajectory ← list, list.rest UNTIL l=NIL DO
Imager.MaskStrokeClosed[current.imager,l.first,width];
count ← count+1;
ENDLOOP;
IF current.logActions THEN {PrintInt[count]; PrintLine["Fit.maskstrokeclosed"]};
};
MaskFill: PROC[list: LIST OF Imager.Trajectory] = {
Imager.MaskFill[current.imager,list];
IF current.logActions THEN {
count: INT ← 0;
FOR l: LIST OF Imager.Trajectory ← list, list.rest UNTIL l=NIL DO
count ← count+1;
ENDLOOP;
PrintInt[count];
PrintLine["Fit.maskfill"];
};
};
NoLog: PUBLIC SIGNAL = CODE;
StartLog: PUBLIC PROC [stream: IO.STREAMNIL] = {
IF stream=NIL uses previous stream. Otherwise, closes previous stream (if any) and sets current output stream to stream.
IF current.log#NIL THEN IO.Close[current.log];
current.log ← stream;
current.logActions ← TRUE;
};
StopLog: PUBLIC PROC[close: BOOLEANTRUE] = {
IF close=FALSE just disables logging.
IF close THEN IO.Close[current.log];
current.logActions ← FALSE;
};
PrintReal: PROC[r: REAL] = {OPEN IO; Put[current.log,real[r],char[SP]]};
PrintRope: PROC[s: Rope.ROPE] = {OPEN IO; Put[current.log,rope[s]]};
PrintLine: PROC[s: Rope.ROPE] = {OPEN IO; Put[current.log,rope[s],char[CR]]};
PrintInt: PROC[i: INT] = {OPEN IO; Put[current.log,int[i],char[SP]]};
PrintPoint: PROC[pt: Complex.Vec] = {PrintReal[pt.x]; PrintReal[pt.y]};
MagnifyData: PUBLIC PROC[scale: REAL] = {current.magnify ← scale};
scales the view of the data but not the marks, linewidth or distance from data to the origin
This is an absolute number with respect to the data. Reset the magnify by MagnifyData[1];
PositionData: PUBLIC PROC[trans: Complex.Vec]= {current.position ← trans};
Positions the data with respect to the origin of the context.
This is an absolute with respect to the Imager client coordinates.
Reset by PositionData[0,0];
MagnifyPoint: PUBLIC PROC [p: Complex.Vec] RETURNS[Complex.Vec] = {
--magnify and position
vt: Complex.Vec;
vt.x ← p.x*current.magnify+current.position.x;
vt.y ← p.y*current.magnify+current.position.y;
RETURN[vt]
};
UnMagnifyPoint: PUBLIC PROC [p: Complex.Vec] RETURNS[Complex.Vec] = {
--undo magnify and position
vt: Complex.Vec;
vt.x ← p.x*(p.x-current.position.x)/current.magnify;
vt.y ← p.y*(p.y+current.position.y)/current.magnify;
RETURN[vt]
};
}.