<> <> <> <> <> DIRECTORY AIS, AtomButtonsTypes, FS, Imager, ImagerColor, ImagerPixelArray, ImagerTransformation, PadGraphics, Real, Rope, SV2d, SV3d, SVArtwork, SVCoordSys2d, SVDraw, SVFiles, SVImage, SVMappings, SVMatrix2d, SVModelTypes, SVVector2d, ViewerClasses; SVArtworkImpl: CEDAR PROGRAM IMPORTS AIS, FS, Imager, ImagerColor, ImagerPixelArray, PadGraphics, Real, Rope, SVCoordSys2d, SVDraw, SVFiles, SVImage, SVMappings, SVMatrix2d, SVVector2d EXPORTS SVArtwork = BEGIN Artwork: TYPE = REF ArtworkObj; ArtworkObj: TYPE = SVModelTypes.ArtworkObj; Box: TYPE = SVModelTypes.Box; Color: TYPE = Imager.Color; CoordSystem2d: TYPE = SVModelTypes.CoordSystem2d; CoordSystem: TYPE = SVModelTypes.CoordSystem; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; Material: TYPE = SVModelTypes.Material; Matrix3by3: TYPE = SV2d.Matrix3by3; OMap: TYPE = SVModelTypes.OMap; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Polygon: TYPE = SV2d.Polygon; SMap: TYPE = SVModelTypes.SMap; SpaceFunction: TYPE = SVModelTypes.SpaceFunction; Tube: TYPE = SVModelTypes.Tube; Vector3d: TYPE = SV3d.Vector3d; Viewer: TYPE = ViewerClasses.Viewer; 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; halfWidth, halfHeight: REAL; halfWidthDots, halfHeightDots: REAL; image: ImagerPixelArray.PixelArray; fileFound: BOOL _ TRUE; IF isColor THEN <> image _ ImagerPixelArray.FromAIS[Rope.Concat[SVFiles.FilenameMinusExtension[filename], "-red.ais"] !FS.Error => {IF error.group = user THEN {fileFound _ FALSE; CONTINUE} ELSE REJECT}] ELSE image _ ImagerPixelArray.FromAIS[filename !FS.Error => {IF error.group = user THEN {fileFound _ FALSE; CONTINUE} ELSE REJECT}]; IF NOT fileFound THEN ERROR FileNotFound; halfWidthDots _ (image.fSize)/2.0; -- in dots halfWidth _ halfWidthDots/resolution;-- convert to inches halfHeightDots _ (image.sSize)/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 _ Imager.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.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; realRedValue _ redValue; realRedValue _ realRedValue/255.0; -- scale to the 0..1 range greenValue _ AIS.ReadSample[artwork.greenWindow, Real.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; realGreenValue _ greenValue; realGreenValue _ realGreenValue/255.0; -- scale to the 0..1 range blueValue _ AIS.ReadSample[artwork.blueWindow, Real.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; realBlueValue _ blueValue; realBlueValue _ realBlueValue/255.0; -- scale to the 0..1 range color _ ImagerColor.ColorFromRGB[[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.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; realBlackValue _ blackValue; realBlackValue _ realBlackValue/255.0; -- scale to the 0..1 range color _ ImagerColor.ColorFromGray[1.0 - realBlackValue]; }; END; }; -- end of FindImageColorAtPoint FindColorAtSurfacePoint: PUBLIC PROC [artwork: Artwork, point3d: Point3d, normal: Vector3d] 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: Vector3d] 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 _ ImagerColor.ColorFromRGB[[redFraction, greenFraction, blueFraction]]; }; DrawArtwork: PUBLIC PROC [dc: Imager.Context, artwork: Artwork, origin: Point2d, scalar: REAL] = { <> tubePoly, padPoly: Polygon; degrees: REAL; rect: Imager.Rectangle; lowerLeftWRTCenter, lowerLeftInScreen: Point2d; feedback: FeedbackData _ NIL; DrawBoxAux: PROC = { Imager.SetColor[dc, artwork.color]; <> Imager.MaskRectangle[dc, rect]; }; DrawArtworkAux: PROC = { lowerLeftInPad: Point2d; Imager.SetColor[dc, artwork.color]; <> <> <> <> 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]; Imager.TranslateT[dc, [lowerLeftInScreen[1], lowerLeftInScreen[2]]]; Imager.RotateT[dc, degrees]; Imager.ScaleT[dc, scalar]; IF artwork.isColorFile THEN SVImage.DrawColorImageAtOrigin[dc, artwork.source, artwork.resolution, feedback] ELSE SVImage.DrawBlackAndWhiteAtOrigin[dc, artwork.source, artwork.resolution, feedback]; }; rect.x _ rect.y _ 0.0; rect.w _ 8.5*72.0; rect.h _ 11.0*72.0; Imager.DoSaveAll[dc, DrawBoxAux]; IF artwork.source = NIL THEN RETURN; Imager.DoSaveAll[dc, DrawArtworkAux]; <> WITH artwork.surface SELECT FROM tube: Tube => { tubePoly _ tube.tubePoly;-- a poly of [theta, h] pairs padPoly _ SVMappings.SurfacePolyToImagePoly[tubePoly, SVMappings.TubeToImage, tube]; Imager.SetColor[dc, Imager.black]; SVDraw.DrawPolygon[dc, padPoly, origin, scalar]; }; box: Box => { Imager.SetColor[dc, Imager.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.