--ContourMain.mesa --Written by M.Stone --Last changed by M.Stone July 14, 1982 12:14 pm --Last changed by M.Plass October 14, 1982 2:59 pm DIRECTORY Rope, Runtime, Graphics, GraphicsOps USING[NewAisImage], TJaMGraphics USING[Painter], AIS USING [OpenFile, FRef, WRef, OpenWindow,CloseFile, ReadSample, CloseWindow,Error], CurveDefs, Vector USING [Vec], ConvertUnsafe, Real, RealFns, Curve, JaMFnsDefs; ContourMain: PROGRAM IMPORTS CurveDefs, AIS, JaMFnsDefs, Graphics, TJaMGraphics, Real, Runtime, ConvertUnsafe, GraphicsOps, Curve EXPORTS CurveDefs = BEGIN OPEN JaMFnsDefs, CurveDefs; Vec: TYPE = Vector.Vec; ais: AIS.FRef _ NIL; window: AIS.WRef _ NIL; aisname: Rope.ROPE; allSLists,lastSList: SListHandle _ NIL; allContours,lastContour: ContourHandle _ NIL; OpenAIS: PROCEDURE = { ENABLE AIS.Error =>{JaMFnsDefs.JaMExec["(AIS file error) .print"]; CONTINUE}; s: LONG STRING_[64]; PopString[s]; ais_AIS.OpenFile[s, FALSE]; window _ AIS.OpenWindow[ais]; aisname _ ConvertUnsafe.ToRope[s]; }; SetTValue: PROCEDURE = {tValue _ PopReal[]}; DrawAIS:PROCEDURE= { Paint: PROC[dc: Graphics.Context] = { imageRef: Graphics.ImageRef _ GraphicsOps.NewAisImage[aisname]; lx,rx,ty,by: REAL; mark: Graphics.Mark _ Graphics.Save[dc]; [lx,by] _ AISToScreen[window.firstPixel,window.lastScan]; [rx,ty] _ AISToScreen[window.lastPixel,window.firstScan]; Graphics.Translate[dc,-lx,-by]; Graphics.ClipBox[dc,[lx,by,rx,ty]]; Graphics.DrawImage[dc,imageRef]; Graphics.Restore[dc,mark]; }; TJaMGraphics.Painter[Paint]; }; SetAISWindow:PROCEDURE= { by,rx,ty,lx,temp: REAL; crx,clx,cty,cby: CARDINAL; by _ GetReal[]; rx _ GetReal[]; ty _ GetReal[]; lx _ GetReal[]; IF ty < by THEN {temp _ by; by _ ty; ty _ temp}; IF rx < lx THEN {temp _ rx; rx _ lx; lx _ temp}; [lx,by] _ ScreenToAIS[lx,by]; [rx,ty] _ ScreenToAIS[rx,ty]; cby _ Real.FixC[by]; cty _ Real.FixC[ty]; crx _ Real.FixC[rx]; clx _ Real.FixC[lx]; AIS.CloseWindow[window]; window _ AIS.OpenWindow[f: ais, firstScan: cty,lastScan: cby, firstPixel: clx, lastPixel: crx]; }; AISToScreen: PROC [x,y: REAL] RETURNS[nx,ny: REAL] ={ nx _ x; ny _ window.lastScan-y; }; ScreenToAIS: PROC [x,y: REAL] RETURNS[nx,ny: REAL] ={ nx _ x; ny _ window.lastScan-y; }; AnalyzeContour: PROCEDURE = { count: INTEGER _ 0; contour:ContourHandle; cn: INTEGER _ PopInteger[]; countProc: PROC[c: ContourHandle] = {IF cn=count THEN contour _ c; count _ count+1}; ForAllContours[countProc]; IF contour#NIL THEN { CurveDefs.AnalyzeContour[contour]; PushInteger[cn]; SetSamples[]; }; }; SetSamples: PROCEDURE = { count: INTEGER _ 0; contour:ContourHandle; cn: INTEGER _ PopInteger[]; countProc: PROC[c: ContourHandle] = {IF cn=count THEN contour _ c; count _ count+1}; ForAllContours[countProc]; IF contour#NIL THEN { sa: SampleHandle _ contour.sLists.samples; Curve.StartSamples[Curve.defaultHandle, sa.xy.x,sa.xy.y]; FOR sa _ contour.sLists.samples.next, sa.next UNTIL sa=NIL DO Curve.AddSample[Curve.defaultHandle, sa.xy.x,sa.xy.y]; ENDLOOP; }; }; SetContours: PROCEDURE = { fullContour: BOOLEAN _ FALSE; SetContour: PROC[contour: ContourHandle] = { sa: SampleHandle _ contour.sLists.samples; IF fullContour THEN Curve.AddContour[Curve.defaultHandle]; Curve.StartSamples[Curve.defaultHandle, sa.xy.x,sa.xy.y]; FOR sa _ contour.sLists.samples.next, sa.next UNTIL sa=NIL DO Curve.AddSample[Curve.defaultHandle, sa.xy.x,sa.xy.y]; ENDLOOP; fullContour _ TRUE; }; Curve.ResetContours[Curve.defaultHandle]; ForAllContours[SetContour]; Curve.NextContour[Curve.defaultHandle]; }; FreeContours: PROC = { allContours _ NIL}; Free: PROCEDURE = { ENABLE AIS.Error =>{JaMFnsDefs.JaMExec["(AIS file error) .print"]; CONTINUE}; AIS.CloseWindow[window]; window _ NIL; AIS.CloseFile[ais]; ais _ NIL; }; LineCount: PROCEDURE = { PushInteger[lineCount]; }; ContourCount: PROCEDURE = { PushInteger[contourCount]; }; RMakeContours: PROCEDURE = { MakeContours[]; DrawContours[]; }; DrawContours: PROCEDURE = { Paint: PROC[dc: Graphics.Context] = { drawContour: PROCEDURE[c: ContourHandle] = { Graphics.MoveTo[path, 0, 0]; -- flush the old path. EnterContour[path, c]; Graphics.DrawStroke[dc, path]; }; ForAllContours[drawContour]; }; path: Graphics.Path _ Graphics.NewPath[]; TJaMGraphics.Painter[Paint]; }; FillContours: PROCEDURE = { Paint: PROC[dc: Graphics.Context] = { fillContour: PROCEDURE[c: ContourHandle] = { EnterContour[path, c]; }; ForAllContours[fillContour]; Graphics.DrawArea[dc, path]; }; path: Graphics.Path _ Graphics.NewPath[]; TJaMGraphics.Painter[Paint]; }; DrawSLists: PROCEDURE = { ForAllSLists[DrawSList]; }; DrawSList: PROCEDURE[sl: SListHandle] = { path: Graphics.Path _ Graphics.NewPath[]; Paint: PROC[dc: Graphics.Context] = {Graphics.DrawStroke[dc,path]}; Graphics.MoveTo[path, sl.samples.xy.x, sl.samples.xy.y]; LineToSamples[path,sl]; TJaMGraphics.Painter[Paint]; }; EnterContour: PROCEDURE[path: Graphics.Path, c: ContourHandle] = { sl: SListHandle _ c.sLists; Graphics.MoveTo[path, sl.samples.xy.x, sl.samples.xy.y, FALSE]; DO LineToSamples[path,sl]; IF sl=c.lastSList THEN EXIT ELSE sl _ sl.next; ENDLOOP; }; LineToSamples: PROCEDURE[path:Graphics.Path, sl: SListHandle] = { s: SampleHandle _ sl.samples.next; DO Graphics.LineTo[path, s.xy.x, s.xy.y]; IF s=sl.lastSample THEN EXIT ELSE s _ s.next; ENDLOOP; }; --the trajectory handling stuff trajList,lastTraj: TrajHandle _ NIL; AddTraj: PROC = { traj: TrajHandle _ NIL ;-- CurrentTraj went away (MFP) Curve.CurrentTraj[]; IF traj=NIL THEN RETURN; IF lastTraj=NIL THEN trajList _ lastTraj _ traj ELSE { lastTraj.next _ traj; traj.prev _ lastTraj; lastTraj _ lastTraj.next; }; }; FreeTrajList: PROC = {trajList _ lastTraj _ NIL}; lineCount: INTEGER _ 0; contourCount: INTEGER _ 0; Outline: PROC = { v1,v2,v3,v4,x,y: CARDINAL; lineCount _ 0; contourCount _ 0; InitContours[]; FOR y IN [window.firstScan..window.lastScan) DO IF JaMFnsDefs.GetJaMBreak[] THEN EXIT; --this assumes the rd scan direction for ais files FOR x IN [window.firstPixel..window.lastPixel) DO v1 _ AIS.ReadSample[window,y,x]; v2 _ AIS.ReadSample[window,y,x+1]; v3 _ AIS.ReadSample[window,y+1,x+1]; v4 _ AIS.ReadSample[window,y+1,x]; ContourCell[v1,v2,v3,v4,x,y]; ENDLOOP; ENDLOOP; }; Trans: TYPE = RECORD[x,y,d: REAL, dir:{nt,dl,ld}]; --aisX and aisY relative to current AIS window ContourCell: PROC[v1,v2,v3,v4:CARDINAL, aisX,aisY:REAL] = { edgePts: ARRAY [0..3] OF Trans; i,ldCount,dlCount,index,move: CARDINAL; FindLD: PROC [start: CARDINAL] RETURNS[CARDINAL] = { FOR k: CARDINAL IN [start..3] DO IF edgePts[k].dir=ld THEN RETURN[k]; ENDLOOP; ERROR; }; FindDL: PROC [start: CARDINAL] RETURNS[CARDINAL] = { FOR k: CARDINAL IN [start..3] DO IF edgePts[k].dir=dl THEN RETURN[k]; ENDLOOP; FOR k: CARDINAL IN [0..start) DO IF edgePts[k].dir=dl THEN RETURN[k]; ENDLOOP; ERROR; }; -- v1 v2 clockwise -- v4 v3 edgePts[0] _ ContourEdge[v1,v2]; edgePts[0].x _ aisX+edgePts[0].d; edgePts[0].y _ aisY; edgePts[1] _ ContourEdge[v2,v3]; edgePts[1].x _ aisX+1; edgePts[1].y _ aisY+edgePts[1].d; --switch the order here for numerical reasons. Must then invert the dir edgePts[2] _ ContourEdge[v4,v3]; edgePts[2].x _ aisX+edgePts[2].d; edgePts[2].y _ aisY+1; edgePts[2].dir _ (SELECT edgePts[2].dir FROM ld => dl, dl => ld, ENDCASE => nt); edgePts[3] _ ContourEdge[v1,v4]; edgePts[3].x _ aisX; edgePts[3].y _ aisY+edgePts[3].d; edgePts[3].dir _ (SELECT edgePts[3].dir FROM ld => dl, dl => ld, ENDCASE => nt); ldCount _ dlCount _ 0; FOR i IN [0..3] DO SELECT edgePts[i].dir FROM dl => dlCount _ dlCount+1; ld => ldCount _ ldCount+1; ENDCASE; ENDLOOP; IF dlCount#ldCount THEN Runtime.CallDebugger["odd transitions"]; IF dlCount>2 THEN Runtime.CallDebugger["too many transitions"]; IF dlCount=0 THEN RETURN; --no transitions --ok, now have transitions. Need to connect ld to dl --this prefers solid dark areas move _ index _ FindLD[0]; index _ FindDL[index]; NewSample[edgePts[move].x,edgePts[move].y,edgePts[index].x,edgePts[index].y]; lineCount _ lineCount+1; IF dlCount=2 THEN BEGIN move _ index _ FindLD[index]; index _ FindDL[index]; NewSample[edgePts[move].x,edgePts[move].y, edgePts[index].x,edgePts[index].y]; lineCount _ lineCount+1; END; }; tValue: REAL _ 128.5; nPoints: INTEGER _ 4; ContourEdge: PROC[v0,v1: REAL] RETURNS[trans: Trans] = { trans _ [x:0, y:0, d:0, dir:nt]; IF v0tValue AND v1>tValue THEN RETURN; trans.d _ (v0-tValue)/(v0-v1); IF v0 s THEN s _ maxX-minX; ForAllContours[write]; }; RWriteTrajs: PROC = { FOR traj: TrajHandle _ trajList, traj.next UNTIL traj=NIL DO CurveDefs.WriteTraj[traj,TRUE]; ENDLOOP; }; minX,maxX,minY,maxY: REAL _ 0; SetMinMax: PROC [c: ContourHandle] = { compare: PROC [sa: SampleHandle] = { IF sa.xy.x>maxX THEN maxX _ sa.xy.x; IF sa.xy.y>maxY THEN maxY _ sa.xy.y; IF sa.xy.x