FitIOImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Maureen Stone March 14, 1985 6:25:19 pm PST
Doug Wyatt, September 5, 1985 2:24:33 pm PDT
DIRECTORY
Complex USING [Mul, VEC],
Cubic USING [Bezier],
FitBasic USING [Handle, LinkHandle, SampleHandle, SListHandle, TrajHandle],
FitIO USING [Context, Feedback],
FitState USING [GetClosed, Handle],
FitStateUtils USING [ForAllLinks, ForAllOtherSLists, ForAllOtherTrajs, ForAllSamples, LinkProc, SampleProc, SListProc, TrajProc],
Imager USING [Context, DoSave, MaskFill, MaskStroke, MaskStrokeTrajectory, MaskVector, SetColor, SetStrokeEnd, SetStrokeWidth, SetXY, Trans, white],
ImagerPath USING [CurveTo, LineTo, MapTrajectoryList, MoveTo, PathProc, Trajectory],
IO USING [char, Close, CR, int, Put, real, rope, SP, STREAM],
RealFns USING [],
Rope USING [ROPE],
Vector USING [Unit];
FitIOImpl: CEDAR PROGRAM
IMPORTS Imager, ImagerPath, IO, Complex, Vector, FitStateUtils, FitState
EXPORTS FitIO = { OPEN FitIO;
Trajectory: TYPE ~ ImagerPath.Trajectory;
Handle: TYPE = FitState.Handle;
SetFeedback:
PUBLIC
PROC[ctx: Context, feedback: Feedback] = {
ctx.feedback ← feedback;
IF ctx.logActions
THEN {
--print feedback
SELECT feedback.color
FROM
Imager.white => PrintRope[ctx, "white "];
ENDCASE=> PrintRope[ctx, "black"];
PrintLine[ctx, "FB.color"];
PrintReal[ctx, feedback.sampleSize]; PrintLine[ctx, "Fit.sampleSize"];
PrintReal[ctx, feedback.jointSize]; PrintLine[ctx, "Fit.jointSize"];
PrintReal[ctx, feedback.nodeLength]; PrintLine[ctx, "Fit.nodeLength"];
PrintReal[ctx, feedback.nodeLineWidth]; PrintLine[ctx, "Fit.nodeLineWidth"];
PrintReal[ctx, feedback.lineWidth]; PrintLine[ctx, "Fit.lineWidth"];
};
};
DrawSamples:
PUBLIC PROC [ctx: Context, handle: Handle, all:
BOOLEAN ←
FALSE, fill:
BOOLEAN ←
FALSE] = {
treat samples as vertices of a polygon or a broken line
list: LIST OF Trajectory;
traj: Trajectory ← PathFromSList[ctx, handle.slist];
IF traj=NIL THEN RETURN ELSE list ← CONS[traj,list];
Imager.SetColor[ctx.imager, ctx.feedback.color];
IF all
THEN {
makeList: FitStateUtils.SListProc = {list ← CONS[PathFromSList[ctx, slist],list]};
FitStateUtils.ForAllOtherSLists[handle,makeList];
};
IF fill THEN MaskFill[ctx,list]
ELSE
IF FitState.GetClosed[handle] THEN MaskStrokeClosed[ctx,list]
ELSE MaskStroke[ctx,list];
IF ctx.logActions THEN PrintLine[ctx, "\n"];
};
DrawContour:
PUBLIC PROC [ctx: Context, handle: Handle, all:
BOOLEAN ←
FALSE, fill:
BOOLEAN ←
FALSE] = {
traj: Trajectory ← PathFromTraj[ctx, handle.traj];
list: LIST OF Trajectory;
IF traj=NIL THEN RETURN ELSE list ← CONS[traj,list];
Imager.SetColor[ctx.imager, ctx.feedback.color];
IF all
THEN {
makeList: FitStateUtils.TrajProc = {list ← CONS[PathFromTraj[ctx, traj, fill],list]};
FitStateUtils.ForAllOtherTrajs[handle,makeList];
};
IF fill THEN MaskFill[ctx, list]
ELSE
IF FitState.GetClosed[handle] OR all THEN MaskStrokeClosed[ctx, list]
ELSE MaskStroke[ctx, list];
IF ctx.logActions THEN PrintLine[ctx, "\n"];
};
DrawCubic:
PUBLIC PROC[ctx: Context, cubic: Cubic.Bezier] = {
list: LIST OF Trajectory;
traj: Trajectory ← MoveTo[ctx, cubic.b0];
traj ← CurveTo[ctx, traj,cubic.b1,cubic.b2,cubic.b3];
MaskStroke[ctx, CONS[traj,list]];
};
PathFromSList:
PROC [ctx: Context, slist: FitBasic.SListHandle]
RETURNS [path: Trajectory] = {
treat samples as vertices of a polygon or a broken line
first: BOOLEAN ← TRUE;
do: FitStateUtils.SampleProc = {
IF first THEN {path ← MoveTo[ctx, s.xy]; first ← FALSE}
ELSE path← LineTo[ctx, path,s.xy];
};
FitStateUtils.ForAllSamples[slist, do];
IF ctx.logActions AND path#NIL THEN PrintLine[ctx, "\n"];
RETURN[path];
};
PathFromTraj:
PROC [ctx: Context, traj: FitBasic.TrajHandle, moveToNext:
BOOLEAN ←
FALSE]
RETURNS [path: Trajectory] = {
convert my trajectory to an imager.trajectory
first: BOOLEAN ← TRUE;
do: FitStateUtils.LinkProc = {
IF first THEN {path ← MoveTo[ctx, l.cubic.b0, moveToNext]; first ← FALSE};
path ← CurveTo[ctx, path,l.cubic.b1,l.cubic.b2,l.cubic.b3];
};
FitStateUtils.ForAllLinks[traj, do];
IF ctx.logActions AND path#NIL THEN PrintLine[ctx, "\n"];
};
MarkSamples:
PUBLIC PROC [ctx: Context, handle: Handle, all:
BOOLEAN ←
FALSE] = {
markSample: FitStateUtils.SampleProc = {MarkSample[ctx, s]};
markSamples: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[slist, markSample]};
[] ← markSamples[handle.slist];
IF all THEN FitStateUtils.ForAllOtherSLists[handle, markSamples];
IF ctx.logActions THEN PrintLine[ctx, "\n"];
};
MarkNodes:
PUBLIC PROC [ctx: Context, handle: Handle, all:
BOOLEAN ←
FALSE] = {
markNode: FitStateUtils.SampleProc = {MarkNode[ctx, s]};
markNodes: FitStateUtils.SListProc = {FitStateUtils.ForAllSamples[slist, markNode]};
[] ← markNodes[handle.slist];
IF all THEN FitStateUtils.ForAllOtherSLists[handle, markNodes];
IF ctx.logActions THEN PrintLine[ctx, "\n"];
};
MarkJoints:
PUBLIC PROC [ctx: Context, handle: Handle, all:
BOOLEAN ←
FALSE] ={
--joints between the cubic pieces
do: FitStateUtils.TrajProc = {MarkTrajJoints[ctx, traj]};
[] ← MarkTrajJoints[ctx, handle.traj];
IF all THEN FitStateUtils.ForAllOtherTrajs[handle, do];
IF ctx.logActions THEN PrintLine[ctx, "\n"];
};
MarkTrajJoints:
PROC[ctx: Context, traj: FitBasic.TrajHandle] = {
first: BOOLEAN ← TRUE;
do: FitStateUtils.LinkProc = {
IF first THEN {MarkJoint[ctx, l.cubic.b0]; first ← FALSE};
MarkJoint[ctx, l.cubic.b3];
};
FitStateUtils.ForAllLinks[traj, do];
IF ctx.logActions THEN PrintLine[ctx, "\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 PROC [ctx: Context, s: FitBasic.SampleHandle] = {
pt: Complex.VEC ← MagnifyPoint[ctx, s.xy];
drawProc:
PROC = {
drawTan:
PROC[t: Complex.
VEC, d:
REAL] = {
t ← Complex.Mul[Vector.Unit[t],[0,d]];
IF t = [0,0]
THEN {
--draw a box
w: REAL ← d/2.0;
path: ImagerPath.PathProc ~ {
moveTo[[-w,-w]]; lineTo[[-w,+w]]; lineTo[[+w,+w]]; lineTo[[+w,-w]];
};
Imager.MaskStroke[context: ctx.imager, path: path, closed: TRUE];
}
ELSE {
--draw a line
Imager.MaskVector[ctx.imager, [-t.x,-t.y], [t.x,t.y]];
};
};
Imager.SetXY[ctx.imager, pt];
Imager.Trans[ctx.imager];
Imager.SetStrokeWidth[ctx.imager, ctx.feedback.nodeLineWidth];
drawTan[t: s.tanIn, d: ctx.feedback.nodeLength];
drawTan[t: s.tanOut, d: ctx.feedback.nodeLength*1.5];
IF s.jointType=forced
THEN {
--draw diamond dot
w: REAL ← ctx.feedback.nodeLength/2.0;
path: ImagerPath.PathProc ~ {
moveTo[[-w, 0]]; lineTo[[0,w]]; lineTo[[w,0]]; lineTo[[0,-w]];
};
Imager.MaskStroke[context: ctx.imager, path: path, closed: TRUE];
Imager.MaskFill[context: ctx.imager, path: path];
};
};
IF s.jointType=none THEN RETURN;
Imager.DoSave[ctx.imager, drawProc];
IF ctx.logActions
THEN {
PrintPoint[ctx, pt];
PrintPoint[ctx, s.tanIn];
PrintPoint[ctx, s.tanOut];
IF s.jointType=forced THEN PrintRope[ctx, "Fit.forcedJoint "] ELSE PrintRope[ctx, "Fit.joint "];
};
MarkSample:
PUBLIC PROC [ctx: Context, s: FitBasic.SampleHandle] = {
size: REAL ← ctx.feedback.sampleSize;
pt: Complex.VEC ← MagnifyPoint[ctx, s.xy];
draw:
PROC = {
dot: ImagerPath.PathProc ~ { moveTo[[0, 0]] };
Imager.SetXY[ctx.imager, pt];
Imager.Trans[ctx.imager];
Imager.SetStrokeWidth[ctx.imager, size];
Imager.SetStrokeEnd[ctx.imager, round];
Imager.MaskStroke[ctx.imager, dot];
Imager.MaskRectangle[ctx.imager,pt.x-size/2,pt.y-size/2,size,size];
};
Imager.DoSave[ctx.imager, draw];
IF ctx.logActions THEN {PrintPoint[ctx, pt]; PrintRope[ctx, "Fit.mark "]};
};
MarkJoint:
PUBLIC PROC[ctx: Context, pt: Complex.
VEC] = {
size: REAL ← ctx.feedback.jointSize;
dot: ImagerPath.PathProc ~ { moveTo[pt] };
pt ← MagnifyPoint[ctx, pt];
Imager.SetStrokeWidth[ctx.imager, size];
Imager.SetStrokeEnd[ctx.imager, round];
Imager.MaskStroke[ctx.imager, dot];
Imager.MaskRectangle[ctx.imager,pt.x,pt.y,size,size];
IF ctx.logActions THEN {PrintPoint[ctx, pt]; PrintRope[ctx, "Fit.joint "]};
};
MoveTo:
PROC[ctx: Context, p: Complex.
VEC, moveToNext:
BOOLEAN ←
FALSE]
RETURNS [path: Trajectory]= {
p ← MagnifyPoint[ctx, p];
path ← ImagerPath.MoveTo[[p.x,p.y]];
IF ctx.logActions
THEN {
PrintPoint[ctx, p];
IF moveToNext THEN PrintRope[ctx, "Fit.movetonext "]
ELSE PrintRope[ctx, "Fit.moveto "]};
RETURN[path];
};
LineTo:
PROC[ctx: Context, path: Trajectory, p: Complex.
VEC]
RETURNS [Trajectory]= {
p ← MagnifyPoint[ctx, p];
path ← ImagerPath.LineTo[path, [p.x,p.y]];
IF ctx.logActions THEN {PrintPoint[ctx, p]; PrintRope[ctx, "Fit.lineto "]};
RETURN[path];
};
CurveTo:
PROC[ctx: Context, path: Trajectory, p1,p2,p3: Complex.
VEC]
RETURNS [Trajectory] = {
p1 ← MagnifyPoint[ctx, p1];
p2 ← MagnifyPoint[ctx, p2];
p3 ← MagnifyPoint[ctx, p3];
path ← ImagerPath.CurveTo[path,[p1.x,p1.y],[p2.x,p2.y],[p3.x,p3.y]];
IF ctx.logActions
THEN {
PrintPoint[ctx, p1];
PrintPoint[ctx, p2];
PrintPoint[ctx, p3];
PrintLine[ctx, "Fit.curveto "];
};
RETURN[path];
};
MaskStroke:
PROC[ctx: Context, list:
LIST
OF Trajectory] = {
width: REAL ← ctx.feedback.lineWidth;
count: INT ← 0;
Imager.SetStrokeWidth[ctx.imager, width];
FOR l:
LIST
OF Trajectory ← list, l.rest
UNTIL l=
NIL
DO
Imager.MaskStrokeTrajectory[ctx.imager,l.first];
count ← count+1;
ENDLOOP;
IF ctx.logActions THEN {PrintInt[ctx, count]; PrintLine[ctx, "Fit.maskstroke"]};
};
MaskStrokeClosed:
PROC[ctx: Context, list:
LIST
OF Trajectory] = {
width: REAL ← ctx.feedback.lineWidth;
count: INT ← 0;
Imager.SetStrokeWidth[ctx.imager, width];
FOR l:
LIST
OF Trajectory ← list, l.rest
UNTIL l=
NIL
DO
Imager.MaskStrokeTrajectory[ctx.imager,l.first, TRUE];
count ← count+1;
ENDLOOP;
IF ctx.logActions THEN {PrintInt[ctx, count]; PrintLine[ctx, "Fit.maskstrokeclosed"]};
};
MaskFill:
PROC[ctx: Context, list:
LIST
OF Trajectory] = {
path: ImagerPath.PathProc ~ {
ImagerPath.MapTrajectoryList[list, moveTo, lineTo, curveTo, conicTo, arcTo];
};
Imager.MaskFill[ctx.imager, path];
IF ctx.logActions
THEN {
count: INT ← 0;
FOR l:
LIST
OF Trajectory ← list, l.rest
UNTIL l=
NIL
DO
count ← count+1;
ENDLOOP;
PrintInt[ctx, count];
PrintLine[ctx, "Fit.maskfill"];
};
};
NoLog:
PUBLIC SIGNAL = CODE;
StartLog:
PUBLIC PROC [ctx: Context, stream:
IO.
STREAM ←
NIL] = {
IF stream=NIL uses previous stream. Otherwise, closes previous stream (if any) and sets current output stream to stream.
IF ctx.log#NIL THEN IO.Close[ctx.log];
ctx.log ← stream;
ctx.logActions ← TRUE;
};
StopLog:
PUBLIC
PROC[ctx: Context,
close:
BOOLEAN ←
TRUE] = {
IF close=FALSE just disables logging.
IF close THEN IO.Close[ctx.log];
ctx.logActions ← FALSE;
};
PrintReal: PROC[ctx: Context, r: REAL] = {OPEN IO; Put[ctx.log,real[r],char[SP]]};
PrintRope: PROC[ctx: Context, s: Rope.ROPE] = {OPEN IO; Put[ctx.log,rope[s]]};
PrintLine: PROC[ctx: Context, s: Rope.ROPE] = {OPEN IO; Put[ctx.log,rope[s],char[CR]]};
PrintInt: PROC[ctx: Context, i: INT] = {OPEN IO; Put[ctx.log,int[i],char[SP]]};
PrintPoint: PROC[ctx: Context, pt: Complex.VEC] = {PrintReal[ctx, pt.x]; PrintReal[ctx, pt.y]};
MagnifyPoint:
PUBLIC PROC [ctx: Context, p: Complex.
VEC]
RETURNS[Complex.
VEC] = {
--magnify and position
vt: Complex.VEC;
vt.x ← p.x*ctx.magnify+ctx.position.x;
vt.y ← p.y*ctx.magnify+ctx.position.y;
RETURN[vt]
};
UnMagnifyPoint:
PUBLIC PROC [ctx: Context, p: Complex.
VEC]
RETURNS[Complex.
VEC] = {
--undo magnify and position
vt: Complex.VEC;
vt.x ← (p.x-ctx.position.x)/ctx.magnify;
vt.y ← (p.y-ctx.position.y)/ctx.magnify;
RETURN[vt]
};
}.