DIRECTORY AIS, FS, Graphics, GraphicsColor, GraphicsOps, PadGraphics, Real, Rope, SV2d, SV3d, SVArtwork, SVCoordSys2d, SVDraw, SVFiles, SVImage, SVMappings, SVMatrix2d, SVModelTypes, SVVector2d; SVArtworkImpl: PROGRAM IMPORTS AIS, FS, GraphicsColor, Graphics, GraphicsOps, PadGraphics, Real, Rope, SVCoordSys2d, SVDraw, SVFiles, SVImage, SVMappings, SVMatrix2d, SVVector2d EXPORTS SVArtwork = BEGIN Color: TYPE = GraphicsColor.Color; Artwork: TYPE = REF ArtworkObj; ArtworkObj: TYPE = SVModelTypes.ArtworkObj; CoordSystem2d: TYPE = SVModelTypes.CoordSystem2d; CoordSystem: TYPE = SVModelTypes.CoordSystem; ImageRef: TYPE = GraphicsOps.ImageRef; Matrix3by3: TYPE = SV2d.Matrix3by3; OMap: TYPE = SVModelTypes.OMap; SMap: TYPE = SVModelTypes.SMap; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Polygon: TYPE = SV2d.Polygon; Vector: TYPE = SV3d.Vector; Material: TYPE = SVModelTypes.Material; Box: TYPE = SVModelTypes.Box; Tube: TYPE = SVModelTypes.Tube; SpaceFunction: TYPE = SVModelTypes.SpaceFunction; CreateFileArtwork: PUBLIC PROC [coordSys: CoordSystem, 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"] !FS.Error => {IF error.group = user THEN {fileFound _ FALSE; CONTINUE} ELSE REJECT}] ELSE image _ GraphicsOps.NewAisImage[filename !FS.Error => {IF error.group = user 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 _ [class: simpleSurface, coordSys: coordSys, 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; Create3DArtwork: PUBLIC PROC [coordSys: CoordSystem, material: Material, data: REF ANY] RETURNS [artwork: Artwork] = { centerWRTLowerLeft: Point2d; artWRTPad: CoordSystem2d; color: Color _ GraphicsColor.white; centerWRTLowerLeft _ [0,0]; artWRTPad _ SVCoordSys2d.CreateCoordSys[SVMatrix2d.Identity[], NIL]; artwork _ NEW[ArtworkObj _ [class: spaceFunction, coordSys: coordSys, material: material, surface: data, 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]]; }; 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 _ [class: justColor, coordSys: NIL, 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.class _ artwork.class; copy.coordSys _ artwork.coordSys; 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], "-grn.ais"]; blueRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[artwork.source], "-blu.ais"]; artwork.open _ TRUE; artwork.redfile _ AIS.OpenFile[redRope, FALSE]; artwork.greenfile _ AIS.OpenFile[greenRope, FALSE]; artwork.bluefile _ AIS.OpenFile[blueRope, FALSE]; 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 artwork.open _ TRUE; artwork.blackfile _ AIS.OpenFile[artwork.source, FALSE]; artwork.blackWindow _ AIS.OpenWindow[artwork.blackfile]; }; }; CloseArtwork: PUBLIC PROC [artwork: Artwork] = { artwork.open _ FALSE; 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; } ELSE { -- close the single black and white file artwork.blackWindow _ NIL; artwork.blackfile _ NIL; }; }; 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 FindColorAtSpacePoint: PUBLIC PROC [artwork: Artwork, point3d: Point3d, normal: Vector] RETURNS [color: Color] = { redFraction, greenFraction, blueFraction: REAL; halfSide: REAL = 1.0; spaceFunction: SpaceFunction; spaceFunction _ NARROW[artwork.surface]; redFraction _ (point3d[1]+spaceFunction.scalars[1]/2.0)/spaceFunction.scalars[1]; greenFraction _ (point3d[2]+spaceFunction.scalars[2]/2.0)/spaceFunction.scalars[2]; blueFraction _ (point3d[3]+spaceFunction.scalars[3]/2.0)/spaceFunction.scalars[3]; IF redFraction < 0 THEN redFraction _ 0.0; IF greenFraction < 0 THEN greenFraction _ 0.0; IF blueFraction < 0 THEN blueFraction _ 0.0; IF redFraction > 1.0 THEN redFraction _ 1.0; IF greenFraction > 1.0 THEN greenFraction _ 1.0; IF blueFraction > 1.0 THEN blueFraction _ 1.0; color _ GraphicsColor.RGBToColor[redFraction, greenFraction, blueFraction]; }; 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]; SVDraw.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]; SVDraw.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. ^File: SVArtworkImpl.mesa Author: Eric Bier in November, 1982 Last edited by Bier on January 13, 1985 10:44:12 pm PST Contents: Procedures for mapping from simple surfaces to arbitrary surfaces and back again Last Edited by: Spreitzer, July 19, 1984 12:11:00 pm PDT fileName must be a full path name. Open just one separation to gauge its size. Assume for now that artwork.file is an 8 bit-per-pixel ais file with rd scanning with origin in its lower left corner. imagePoint is in screen dots. Find the bounding box of the AIS file. If [u,v] is outside the AIS image, just use the background color. normal and point3d in Master Object coordinates first map surface point to tube point. Next map tube point to image point. Finally, find color at image point. For now, use the rgb cube of side 2 with origin at [-1, -1, -1]. Ignore "normal". Draw a colored box. Draw the image so that its declared center is placed at its declared displacement from the center of the artwork pad. Find out where its lower left corner should be in pad coordinates. Then find out where its lower left corner should be in viewer coordinates. Draw. SVImage will draw the ais file centered on the current dc origin. Move this origin as needed. Now draw the boundaries of the current simple surface ie returns "plastic" given plastic, "chalk" given chalk Does the inverse of MaterialToRope. Κ%˜Iheadšœ™Jšœ#™#Jšœ7™7JšœZ™ZJ™8J˜šΟk ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ ˜ Jšœ˜Jšœ˜Jšœ˜J˜Jšœ ˜ Jšœ ˜ J˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ ˜ J˜ Jšœ ˜ —J˜šœ˜Jšœœœ‹˜šJšœ ˜—Jš˜˜Jšœœ˜"J˜Jšœ œœ ˜Jšœ œ˜+Jšœœ˜1Jšœ œ˜-Jšœ œ˜&Jšœ œ˜#Jšœœ˜Jšœœ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœœ˜Jšœ œ˜'J˜Jšœœ˜Jšœœ˜Jšœœ˜1J˜—šΟnœœœ6œœ)œ œ!œ2œ˜ŒJ™"Jšœ˜Jšœ˜Jšœ,œ˜1Jšœœ˜Jšœœ˜$Jšœ˜Jšœ œœ˜šœ ˜J™+Jšœa˜aJš œœœœœœœ˜T—šœ)˜-Jš œœœœœœœ˜U—Jšœœ œœ˜)JšœK˜KJšœ5˜5Jšœ9˜9Jšœ6˜6Jšœ;˜;JšœI˜IJšœ-œ˜2Jšœ œύœ œ œ œ œœœœœ˜‘Jšœ˜—Jšœœœœ˜"J˜š žœœœ3œœœ˜vJšœ˜Jšœ˜J˜#Jšœ˜Jšœ?œ˜DJšœ œ‰œœ œ œ œ œ œœœœœ˜βJšœ˜—J˜šžœœœ$œ˜aJšœ˜Jšœ˜Jšœ˜Jšœ?œ˜DJšœ œ+œœ/œœ œ œ œ œ œœœœœ˜ΨJšœ˜—J˜šžœœœœ˜@Jšœœ ˜Jšœ˜Jšœ!˜!Jšœ!˜!Jšœ˜Jšœ˜Jšœ˜Jšœ'˜'Jšœ%˜%Jšœ#˜#Jšœ+˜+Jšœ5˜5Jšœ#˜#Jšœ˜Jšœ#˜#Jšœ!˜!Jšœ#˜#Jšœ#˜#Jšœ'˜'Jšœ%˜%Jšœ'˜'Jšœ˜Jšœ˜J˜—šž œœœ˜/Jšœ œœœ˜Jšœœœœ˜$šœœ˜:JšœœK˜]JšœœK˜_JšœœK˜^Jšœœ˜Jšœœœ˜/Jšœœœ˜3Jšœœœ˜1Jšœœ˜4Jšœœ˜8Jšœœ˜6Jšœ˜—šœ)˜-Jšœœ˜Jšœœœ˜8Jšœœ˜8Jšœ˜—Jšœ˜J˜—šž œœœ˜0Jšœœ˜šœœ ˜;Jšœ ˜#Jšœ˜Jšœœ˜Jšœœ˜Jšœ"˜%Jšœ˜!Jšœœ˜Jšœœ˜Jšœ!˜$Jšœ˜ Jšœœ˜Jšœœ˜Jšœ˜—šœ+˜/Jšœœ˜Jšœœ˜Jšœ˜—Jšœ˜—J˜šžœœœ)œ˜eJšœv™vJšœ™Jšœ&™&Jšœ˜Jšœœœœ˜3J˜š˜Jšœ œ6˜FJšœœ˜(Jšœ^˜^Jšœ<˜Jšœœ˜6Jšœœ˜4Jšœœ˜—Jšœ˜—J˜š ž œœœœœ˜Ešœ˜Jšœ'˜'Jšœ˜Jšœœ˜ —Jšœ˜—š ž œœœœœœ˜Tšœ œ˜šœœ˜Jšœ#œ˜@Jšœœ˜4Jšœœ˜—Jšœ˜——J˜Jšœ˜—…—6ΒJE