<> <> <> <> DIRECTORY AIS, ConvertUnsafe, Directory, Graphics, GraphicsColor, GraphicsOps, Matrix3d, MessageWindow, PadGraphics, Real, Rope, SV2d, SVArtwork, SVCoordSys2d, SVFiles, SVImage, SVMappings, SVMatrix2d, SVPolygon2d, SVVector2d, SVVector3d; SVArtworkImpl: PROGRAM IMPORTS AIS, ConvertUnsafe, Directory, GraphicsColor, Graphics, GraphicsOps, MessageWindow, PadGraphics, Real, Rope, SVCoordSys2d, SVFiles, SVImage, SVMappings, SVMatrix2d, SVVector2d EXPORTS SVArtwork = BEGIN Color: TYPE = GraphicsColor.Color; Artwork: TYPE = REF ArtworkObj; ArtworkObj: TYPE = SVArtwork.ArtworkObj; CoordSystem2d: TYPE = SVCoordSys2d.CoordSystem2d; ImageRef: TYPE = GraphicsOps.ImageRef; Matrix3by3: TYPE = SVMatrix2d.Matrix3by3; OMap: TYPE = SVArtwork.OMap; SMap: TYPE = SVArtwork.SMap; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = Matrix3d.Point3d; Polygon: TYPE = SVPolygon2d.Polygon; Vector: TYPE = SVVector3d.Vector; Material: TYPE = SVArtwork.Material; Box: TYPE = SVMappings.Box; Tube: TYPE = SVMappings.Tube; CreateFileArtwork: PUBLIC PROC [material: Material, surface: REF ANY, oMap: OMap, sMap: SMap, filename: Rope.ROPE, isColor: BOOL, background: Color, resolution: REAL _ 72.0, mat: Matrix3by3 _ SVMatrix2d.Identity[]] RETURNS [artwork: Artwork] = { centerWRTLowerLeft: Point2d; artWRTPad: CoordSystem2d; imageXmin, imageYmin, imageXmax, imageYmax: REAL; halfWidth, halfHeight: REAL; halfWidthDots, halfHeightDots: REAL; image: ImageRef; fileFound: BOOL _ TRUE; IF isColor THEN image _ GraphicsOps.NewAisImage[Rope.Concat[SVFiles.FilenameMinusExtension[filename], "-red.ais"] !Directory.Error => {IF type = fileNotFound THEN {fileFound _ FALSE; CONTINUE} ELSE REJECT}] ELSE image _ GraphicsOps.NewAisImage[filename !Directory.Error => {IF type = fileNotFound THEN {fileFound _ FALSE; CONTINUE} ELSE REJECT}]; IF NOT fileFound THEN ERROR FileNotFound; [imageXmin, imageYmin, imageXmax, imageYmax] _ GraphicsOps.ImageBox[image]; halfWidthDots _ (imageXmax-imageXmin)/2.0;-- in dots halfWidth _ halfWidthDots/resolution;-- convert to inches halfHeightDots _ (imageYmax-imageYmin)/2.0;-- in dots halfHeight _ halfHeightDots/resolution;-- convert to inches centerWRTLowerLeft _ [halfWidth*72.0, halfHeight*72.0];-- in screen dots artWRTPad _ SVCoordSys2d.CreateCoordSys[mat, NIL]; artwork _ NEW[ArtworkObj _ [material: material, surface: surface, oMap: oMap, sMap: sMap, source: filename, color: background, isColorFile: isColor, resolution: resolution, halfWidth: halfWidth, halfHeight: halfHeight, halfWidthDots: halfWidthDots, halfHeightDots: halfHeightDots, centerWRTLowerLeft: centerWRTLowerLeft, artWRTPad: artWRTPad, redfile: NIL, greenfile: NIL, bluefile: NIL, blackfile: NIL, redWindow: NIL, greenWindow: NIL, blueWindow: NIL, blackWindow: NIL, open: FALSE]]; }; FileNotFound: PUBLIC ERROR = CODE; CreateColorArtwork: PUBLIC PROC [color: Color, material: Material] RETURNS [artwork: Artwork] = { centerWRTLowerLeft: Point2d; artWRTPad: CoordSystem2d; centerWRTLowerLeft _ [0,0]; artWRTPad _ SVCoordSys2d.CreateCoordSys[SVMatrix2d.Identity[], NIL]; artwork _ NEW[ArtworkObj _ [material: material, surface: NIL, oMap: orthogonal, sMap: unfoldedBox, source: NIL, color: color, isColorFile: FALSE, resolution: 0.0, halfWidth: 0.0, halfHeight: 0.0, halfWidthDots: 0, halfHeightDots: 0, centerWRTLowerLeft: centerWRTLowerLeft, artWRTPad: artWRTPad, redfile: NIL, greenfile: NIL, bluefile: NIL, blackfile: NIL, redWindow: NIL, greenWindow: NIL, blueWindow: NIL, blackWindow: NIL, open: FALSE]]; }; Copy: PUBLIC PROC [artwork: Artwork] RETURNS [copy: Artwork] = { copy _ NEW[ArtworkObj]; copy.material _ artwork.material; copy.surface _ artwork.surface; copy.source _ artwork.source; copy.color _ artwork.color; copy.isColorFile _ artwork.isColorFile; copy.resolution _ artwork.resolution; copy.halfWidth _ artwork.halfWidth; copy.halfWidthDots _ artwork.halfWidthDots; copy.centerWRTLowerLeft _ artwork.centerWRTLowerLeft; copy.artWRTPad _ artwork.artWRTPad; copy.redfile _ artwork.redfile; copy.greenfile _ artwork.greenfile; copy.bluefile _ artwork.bluefile; copy.blackfile _ artwork.blackfile; copy.redWindow _ artwork.redWindow; copy.greenWindow _ artwork.greenWindow; copy.blueWindow _ artwork.blueWindow; copy.blackWindow _ artwork.blackWindow; copy.open _ artwork.open; }; OpenArtwork: PUBLIC PROC [artwork: Artwork] = { IF artwork = NIL THEN RETURN; IF artwork.source = NIL THEN RETURN; IF artwork.isColorFile THEN {-- open the three separations redRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[artwork.source], "-red.ais"]; greenRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[artwork.source], "-green.ais"]; blueRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[artwork.source], "-blue.ais"]; redString: LONG STRING _ [30]; greenString: LONG STRING _ [30]; blueString: LONG STRING _ [30]; ConvertUnsafe.AppendRope[redString, redRope]; ConvertUnsafe.AppendRope[greenString, greenRope]; ConvertUnsafe.AppendRope[blueString, blueRope]; artwork.open _ TRUE; artwork.redfile _ AIS.OpenFile[redString, FALSE]; artwork.greenfile _ AIS.OpenFile[greenString, FALSE]; artwork.bluefile _ AIS.OpenFile[blueString, FALSE]; IF artwork.open = FALSE THEN MessageWindow.Append["Open Artwork failed"] ELSE { artwork.redWindow _ AIS.OpenWindow[artwork.redfile]; artwork.greenWindow _ AIS.OpenWindow[artwork.greenfile]; artwork.blueWindow _ AIS.OpenWindow[artwork.bluefile]; }; } ELSE { -- open the single grey-level ais file blackString: LONG STRING _ [30]; ConvertUnsafe.AppendRope[blackString, artwork.source]; artwork.open _ TRUE; artwork.blackfile _ AIS.OpenFile[blackString, FALSE]; IF artwork.open = FALSE THEN MessageWindow.Append["Open Artwork failed"] ELSE artwork.blackWindow _ AIS.OpenWindow[artwork.blackfile]; }; }; CloseArtwork: PUBLIC PROC [artwork: Artwork] = { IF artwork.isColorFile THEN {-- close the three separations AIS.CloseWindow[artwork.redWindow]; AIS.CloseFile[artwork.redfile]; artwork.redWindow _ NIL; artwork.redfile _ NIL; AIS.CloseWindow[artwork.greenWindow]; AIS.CloseFile[artwork.greenfile]; artwork.greenWindow _ NIL; artwork.greenfile _ NIL; AIS.CloseWindow[artwork.blueWindow]; AIS.CloseFile[artwork.bluefile]; artwork.blueWindow _ NIL; artwork.bluefile _ NIL; artwork.open _ FALSE; } ELSE { -- close the single black and white file artwork.blackWindow _ NIL; artwork.blackfile _ NIL; artwork.open _ FALSE; }; }; FindImageColorAtPoint: PUBLIC PROC [artwork: Artwork, imagePoint: Point2d] RETURNS [color: Color] = { <> <> <> artworkPoint: Point2d; IF artwork.source = NIL THEN RETURN[artwork.color]; BEGIN uAIS, vAIS: REAL; -- u and v in AIS dots at this ais file's resolution uInch, vInch: REAL; -- u and v in inches artworkPoint _ SVMatrix2d.Update[artwork.artWRTPad.padWRTLocal, imagePoint]; -- in screen dots uInch _ artworkPoint[1]/72.0; vInch _ artworkPoint[2]/72.0; uAIS _ uInch*artwork.resolution; vAIS _ vInch*artwork.resolution; IF artwork.isColorFile THEN { redValue, greenValue, blueValue: CARDINAL; realRedValue, realGreenValue, realBlueValue: REAL; <> IF uInch <= - artwork.halfWidth OR uInch >= artwork.halfWidth OR vInch <= -artwork.halfHeight OR vInch >= artwork.halfHeight THEN RETURN[artwork.color]; redValue _ AIS.ReadSample[artwork.redWindow, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; realRedValue _ redValue; realRedValue _ realRedValue/255.0; -- scale to the 0..1 range greenValue _ AIS.ReadSample[artwork.greenWindow, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; realGreenValue _ greenValue; realGreenValue _ realGreenValue/255.0; -- scale to the 0..1 range blueValue _ AIS.ReadSample[artwork.blueWindow, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; realBlueValue _ blueValue; realBlueValue _ realBlueValue/255.0; -- scale to the 0..1 range color _ GraphicsColor.RGBToColor[realRedValue, realGreenValue, realBlueValue]; } ELSE {-- artwork is a black and white file blackValue: CARDINAL; realBlackValue: REAL; IF uInch <= - artwork.halfWidth OR uInch >= artwork.halfWidth OR vInch <= -artwork.halfHeight OR vInch >= artwork.halfHeight THEN RETURN[artwork.color]; blackValue _ AIS.ReadSample[artwork.blackWindow, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; realBlackValue _ blackValue; realBlackValue _ realBlackValue/255.0; -- scale to the 0..1 range color _ GraphicsColor.IntensityToColor[realBlackValue]; }; END; }; -- end of FindImageColorAtPoint FindColorAtSurfacePoint: PUBLIC PROC [artwork: Artwork, point3d: Point3d, normal: Vector] RETURNS [color: Color] = { <> <> <> <> surfacePoint, imagePoint: Point2d; IF artwork.surface = NIL THEN RETURN[artwork.color]; WITH artwork.surface SELECT FROM tube: Tube => { onTube: BOOL; surfacePoint _ SVMappings.Point3dToTubePoint[point3d]; [imagePoint, onTube] _ SVMappings.TubeToImage[surfacePoint, tube]; }; box: Box =>{ onBox: BOOL; SELECT artwork.oMap FROM orthogonal => [surfacePoint, onBox] _ SVMappings.BoxOrthogonalOInverse[point3d, normal, box]; radial => [surfacePoint, onBox] _ SVMappings.BoxRadialOInverse[point3d, normal, box]; ENDCASE => ERROR; IF NOT onBox THEN RETURN[artwork.color]; [imagePoint, onBox] _ SVMappings.BoxToImage[surfacePoint, box]; IF NOT onBox THEN RETURN[artwork.color]; }; ENDCASE => ERROR; color _ FindImageColorAtPoint[artwork, imagePoint]; }; -- end of FindColorAtSurfacePoint DrawArtwork: PUBLIC PROC [dc: Graphics.Context, artwork: Artwork, origin: Point2d, scalar: REAL] = { <> tubePoly, padPoly: Polygon; degrees: REAL; mark: Graphics.Mark; lowerLeftWRTCenter, lowerLeftInScreen: Point2d; mark _ Graphics.Save[dc]; Graphics.SetColor[dc, artwork.color]; Graphics.DrawBox[dc, Graphics.GetBounds[dc]]; IF artwork.source = NIL THEN {Graphics.Restore[dc, mark]; RETURN} ELSE { lowerLeftInPad: Point2d; <> <> <> <> lowerLeftWRTCenter _ SVVector2d.Scale[artwork.centerWRTLowerLeft, -1]; -- in artwork coordinates, units = screen dots lowerLeftInPad _ SVMatrix2d.Update[artwork.artWRTPad.localWRTPad, lowerLeftWRTCenter]; -- in pad coordinates lowerLeftInScreen _ PadGraphics.PadToScreen[lowerLeftInPad, origin, scalar]; degrees _ SVMatrix2d.RotationOfMatrix[artwork.artWRTPad.localWRTPad]; Graphics.Translate[dc, lowerLeftInScreen[1], lowerLeftInScreen[2]]; Graphics.Rotate[dc, degrees]; Graphics.Scale[dc, scalar, scalar]; IF artwork.isColorFile THEN SVImage.DrawColorImage[dc, artwork.source, NIL, artwork.resolution] ELSE SVImage.DrawBlackAndWhiteImage[dc, artwork.source, NIL, artwork.resolution, FALSE];-- "FALSE" means "not raw". Interpret the values appropriately for the color map Graphics.Restore[dc, mark]; <> WITH artwork.surface SELECT FROM tube: Tube => { tubePoly _ tube.tubePoly;-- a poly of [theta, h] pairs padPoly _ SVMappings.SurfacePolyToImagePoly[tubePoly, SVMappings.TubeToImage, tube]; Graphics.SetColor[dc, GraphicsColor.black]; PadGraphics.DrawPolygon[dc, padPoly, origin, scalar]; }; box: Box => { Graphics.SetColor[dc, GraphicsColor.black]; FOR i: NAT IN [1..6] DO padPoly _ SVMappings.SurfacePolyToImagePoly[box.faces[i], SVMappings.BoxToImage, box]; PadGraphics.DrawPolygon[dc, padPoly, origin, scalar]; ENDLOOP; }; ENDCASE => ERROR; }; }; MaterialToRope: PUBLIC PROC [material: Material] RETURNS [materialName: Rope.ROPE] = { <> SELECT material FROM plastic => materialName _ "plastic"; chalk => materialName _ "chalk"; ENDCASE => ERROR UpdateThisCode; }; UpdateThisCode: PUBLIC ERROR = CODE; RopeToMaterial: PUBLIC PROC [materialName: Rope.ROPE] RETURNS [material: Material, success: BOOL] = { <> success _ TRUE; SELECT TRUE FROM Rope.Equal[materialName, "plastic", FALSE] => material _ plastic; Rope.Equal[materialName, "chalk", FALSE] => material _ chalk; ENDCASE => success _ FALSE; }; OMapToRope: PUBLIC PROC [oMap: OMap] RETURNS [mapName: Rope.ROPE] = { SELECT oMap FROM orthogonal => mapName _ "orthogonal"; radial => mapName _ "radial"; tubeO => mapName _ "tubeO"; ENDCASE => ERROR UpdateThisCode; }; RopeToOMap: PUBLIC PROC [mapName: Rope.ROPE] RETURNS [oMap: OMap, success: BOOL] = { success _ TRUE; SELECT TRUE FROM Rope.Equal[mapName, "orthogonal", FALSE] => oMap _ orthogonal; Rope.Equal[mapName, "radial", FALSE] => oMap _ radial; Rope.Equal[mapName, "tubeO", FALSE] => oMap _ tubeO; ENDCASE => success _ FALSE; }; SMapToRope: PUBLIC PROC [sMap: SMap] RETURNS [mapName: Rope.ROPE] = { SELECT sMap FROM unfoldedBox => mapName _ "unfoldedBox"; tubeS => mapName _ "tubeS"; ENDCASE => ERROR UpdateThisCode; }; RopeToSMap: PUBLIC PROC [mapName: Rope.ROPE] RETURNS [sMap: SMap, success: BOOL] = { success _ TRUE; SELECT TRUE FROM Rope.Equal[mapName, "unfoldedBox", FALSE] => sMap _ unfoldedBox; Rope.Equal[mapName, "tubeS", FALSE] => sMap _ tubeS; ENDCASE => success _ FALSE; }; END.