DIRECTORY ColorTrixBasics, Commander, Controls, Contours, Draw2d, ImagerPixelMap, IO, Real; ContoursTestImpl: CEDAR PROGRAM IMPORTS ~ BEGIN OPEN Contours; PixelMap: TYPE ~ ImagerPixelMap.PixelMap; Spot: TYPE ~ RECORD [x, y: INTEGER]; SpotSequence: TYPE ~ REF SpotSequenceRec; SpotSequenceRec: TYPE ~ RECORD [ length: NAT _ 0, elememnt: SEQUENCE maxLength: NAT OF Spot ]; ProgramData: TYPE ~ REF ProgramDataRec; ProgramDataRec: TYPE ~ RECORD [ outer: Viewer _ NIL, -- the outer (parent, top level) viewer contour: Control _ NIL, -- the contour control color: CARDINAL _ 200, cd: Context _ NIL, out: STREAM _ NIL ]; END. .. ΊContoursTestImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, September 17, 1986 4:25:55 pm PDT Types Commands ContoursFill: Commander.CommandProc ~ { p: ProgramData _ NEW[ProgramDataRec]; p.contour _ Controls.NewControl[type: contour, w: 160, proc: Negate, data: p]; p.outer _ Controls.OuterViewer[ name: "Contours Fill", controls: LIST[p.contour], buttons: LIST[["Clear", Clear]], data: p]; p.cd _ ColorTrixBasics.InitCd[gray]; p.out _ cmd.out; }; Clear: Controls.ClickProc ~ { p: ProgramData _ NARROW[NARROW[clientData, Controls.OuterData].data]; Controls.Reset[p.contour]; }; Commander.Register["///Commands/ContoursFill", ContoursFill, "Fill a contour\n"]; NegateSegment: PROC [pm: PixelMap, s0, s1: Spot] ~ { x: REAL _ s0.x; xMax: INTEGER _ pm.fMin+pm.fSize; dx: REAL _ IF s0.y # s1.y THEN (s1.x-s0.x)/(s1.y-s0.y) ELSE 1.0; color: CARDINAL _ IF dx < 0 THEN 100 ELSE p.color; FOR y: INTEGER IN [s0.y..s1.y) DO xx: INTEGER _ Real.RoundI[x]; dest: PixelMap _ ImagerPixelMap.SetWindow[p.pm, [y, xx, 1, xMax-xx]]; ImagerPixelMap.Transfer[dest, p.pm, [null, complement]]; x _ x+dx; ENDLOOP; }; Fill: Controls.ControlProc ~ { Presumes contour is clockwise and its coordinates are B [-1..1]. p: ProgramData _ NARROW[control.data]; contour: Contour _ Contours.FromControl[p.contour]; SpotsStart: PROC [spots: SpotSequence] RETURNS [INTEGER] ~ { start, ymin: INTEGER _ 10000; FOR n: NAT IN [0..spots.length) DO IF spots[n].y < ymin THEN {ymin _ spots[n].y; start _ n}; ENDLOOP; RETURN[start]; }; FloodSegment: PROC [pm: PixelMap, s0, s1: Spot] ~ { x: REAL _ s0.x; xMax: INTEGER _ pm.fMin+pm.fSize; dx: REAL _ IF s0.y # s1.y THEN (s1.x-s0.x)/(s1.y-s0.y) ELSE 1.0; color: CARDINAL _ IF dx < 0 THEN 100 ELSE p.color; FOR y: INTEGER IN [s0.y..s1.y] DO xx: INTEGER _ Real.RoundI[x]; ImagerPixelMap.Fill[pm, [y, xx, 1, xMax-xx], color]; x _ x+dx; ENDLOOP; }; IF contour.closed THEN { spots: SpotSequence _ PmSpotsFromContour[contour, p.pm]; n, start: INTEGER _ SpotsStart[spots]; s0, s1: Spot _ spots[start]; ImagerPixelMap.Fill[p.pm, [p.pm.sMin, p.pm.fMin, p.pm.sSize, p.pm.fSize], 60]; DO s0 _ s1; s1 _ spots[n _ (n+1) MOD spots.length]; FloodSegment[p.pm, s0, s1]; IF n = start THEN EXIT; ENDLOOP; }; }; PmSpotsFromContour: PROC [contour: Contour, pm: PixelMap, invert: BOOL _ TRUE] RETURNS [SpotSequence] ~ { spots: SpotSequence _ NEW[SpotSequenceRec[contour.pairs.length]]; scale: REAL _ (MIN[pm.sSize, pm.fSize]-1)/2.0; xOffset: REAL _ pm.fMin+scale-1.0; yOffset: REAL _ pm.sMin+scale-1.0; xMin: INTEGER _ 10000; spots.length _ spots.maxLength; FOR n: NAT IN [0..spots.length) DO spots[n] _ [ Real.RoundI[xOffset+scale*contour.pairs[n].x], Real.RoundI[yOffset+scale*contour.pairs[n].y]]; ENDLOOP; IF invert THEN FOR n: NAT IN [0..spots.length) DO spots[n].y _ pm.sMin+pm.sSize-spots[n].y; ENDLOOP; RETURN[spots]; }; Negate: Controls.ControlProc ~ { Presumes contour is clockwise and its coordinates are B [-1..1]. p: ProgramData _ NARROW[control.data]; yLast: INTEGER _ -1; xMax: INTEGER _ p.pm.fMin+p.pm.fSize; contour: Contour _ Contours.FromControl[p.contour]; NegateSegment: PROC [pm: PixelMap, s0, s1: Spot] ~ { NegateToEnd: PROC [x, y: INTEGER] ~ { IF y # yLast THEN { dest: PixelMap _ ImagerPixelMap.SetWindow[pm, [y, x, 1, xMax-x]]; ImagerPixelMap.Transfer[dest, pm, [null, complement]]; yLast _ y; }; }; IF s0.y = s1.y THEN NegateToEnd[s0.x, s0.y] ELSE { Dot: Draw2d.PixelProc ~ {NegateToEnd[x, y]}; Draw2d.DoWithLine[s0.x, s0.y, s1.x, s1.y, Dot]; }; }; IF contour.closed THEN { spots: SpotSequence _ PmSpotsFromContour[contour, p.pm]; s0, s1: Spot _ spots[spots.length-1]; ColorTrixBasics.FillPm[p.pm, 100]; FOR n: NAT IN [0..spots.length) DO s0 _ s1; s1 _ spots[n]; ColorTrixBasics.PutLine[p.pm, s0.x, s0.y, s1.x, s1.y, 200]; NegateSegment[p.pm, s0, s1]; ENDLOOP; }; }; Negate: Controls.ControlProc ~ { Presumes contour is clockwise and its coordinates are B [-1..1]. p: ProgramData _ NARROW[control.data]; yLast: INTEGER _ -1; xMax: INTEGER _ p.pm.fMin+p.pm.fSize; contour: Contour _ Contours.FromControl[p.contour]; NegateSegment: PROC [pm: PixelMap, s0, s1: Spot] ~ { NegateToEnd: PROC [x, y: INTEGER] ~ { IF y # yLast THEN { dest: PixelMap _ ImagerPixelMap.SetWindow[pm, [y, x, 1, xMax-x]]; ImagerPixelMap.Transfer[dest, pm, [null, complement]]; yLast _ y; }; }; IF s0.y = s1.y THEN NegateToEnd[s0.x, s0.y] ELSE { Dot: Draw2d.PixelProc ~ {NegateToEnd[x, y]}; Draw2d.DoWithLine[s0.x, s0.y, s1.x, s1.y, Dot]; }; }; IF contour.closed THEN { spots: SpotSequence _ PmSpotsFromContour[contour, p.pm]; s0, s1: Spot _ spots[spots.length-1]; ColorTrixBasics.FillPm[p.pm, 100]; FOR n: NAT IN [0..spots.length) DO s0 _ s1; s1 _ spots[n]; ColorTrixBasics.PutLine[p.pm, s0.x, s0.y, s1.x, s1.y, 200]; NegateSegment[p.pm, s0, s1]; ENDLOOP; }; }; ΚŸ˜šœ™Jšœ Οmœ1™