<> <> <> <> 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] = { <> 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] = { <> 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] = { <> 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"]; }; <> <> <> <> <> <> <> <<];>> <<>> 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.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]; <> 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 ctx.log#NIL THEN IO.Close[ctx.log]; ctx.log _ stream; ctx.logActions _ TRUE; }; StopLog: PUBLIC PROC[ctx: Context, close: BOOLEAN _ TRUE] = { <> 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] }; }.