File: Scratchpad2dUserImpl.mesa
Last edited by: Eric Bier on August 1, 1985 6:17:43 pm PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: Functions called by the buttons on a Scratchpad2d viewer.
DIRECTORY
BasicTime,
Containers,
DisplayList3d,
DisplayListToTree,
Imager,
ImagerBackdoor,
ImagerInterpress,
IO,
Menus,
PadGraphics,
Rope,
Scratchpad2dUser,
SV2d,
SVError,
SVFiles,
SVInterfaceTypes,
SVModelTypes,
SVRayTypes,
SVSceneTypes,
SVSelections,
SVPolygon2d,
SVSlices,
SVViewerTool,
SVViewerUser,
SVLines2d,
SVVector2d,
ViewerClasses,
ViewerOps,
ViewerTools;
Scratchpad2dUserImpl: CEDAR PROGRAM
IMPORTS BasicTime, DisplayList3d, DisplayListToTree, Imager, ImagerBackdoor, ImagerInterpress, IO, PadGraphics, Rope, SVError, SVFiles, SVLines2d, SVPolygon2d, SVSelections, SVSlices, SVVector2d, SVViewerUser, ViewerOps, ViewerTools
EXPORTS Scratchpad2dUser =
BEGIN
Assembly: TYPE = SVSceneTypes.Assembly;
Camera: TYPE = SVModelTypes.Camera;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CSGTree: TYPE = SVRayTypes.CSGTree;
EditToolData: TYPE = SVInterfaceTypes.EditToolData;
FrameBlock: TYPE = REF FrameBlockObj;
FrameBlockObj: TYPE = SVSceneTypes.FrameBlockObj;
MouseButton: TYPE = Menus.MouseButton;
Path: TYPE = SV2d.Path;
Point2d: TYPE = SV2d.Point2d;
Polygon: TYPE = SV2d.Polygon;
Scene: TYPE = SVSceneTypes.Scene;
Slice: TYPE = SVSlices.Slice;
ToolData: TYPE = SVSceneTypes.ToolData;
TrigLineSeg: TYPE = SV2d.TrigLineSeg;
Vector2d: TYPE = SV2d.Vector2d;
Viewer: TYPE = ViewerClasses.Viewer;
ViewerToolData: TYPE = SVInterfaceTypes.ViewerToolData;
ScratchViewerData: TYPE = SVInterfaceTypes.ScratchViewerData;
ScratchpadData: TYPE = SVInterfaceTypes.ScratchpadData;
squareSide: REAL = 6;
Painter:
PUBLIC
PROC [proc:
PROC [Imager.Context], scratchViewerData: ScratchViewerData ←
NIL] =
TRUSTED {
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
scratchpadData.proc ← proc;
ViewerOps.PaintViewer[
viewer: scratchViewerData.scratchpad,
hint: client,
whatChanged: scratchViewerData,
clearClient: FALSE];
}; -- end of Painter
PaintRevo:
PUBLIC
PROC [dc: Imager.Context, scratchpadData: ScratchpadData] =
TRUSTED {
Begin at y axis to show user how the final effect will look
IF scratchpadData.path.len = 0 THEN RETURN;
Imager.SetColor[dc, Imager.black];
Paint right side
PadGraphics.MoveTo[dc, [0, scratchpadData.path[0][2]], scratchpadData.origin];
PadGraphics.DrawSquare[dc, squareSide, [0, scratchpadData.path[0][2]], scratchpadData.origin];
FOR i:
NAT
IN[0..scratchpadData.path.len)
DO
PadGraphics.DrawTo[dc, scratchpadData.path[i], scratchpadData.origin];
PadGraphics.DrawSquare[dc, squareSide, scratchpadData.path[i], scratchpadData.origin];
ENDLOOP;
End at y axis to show user how the final sweep will look
PadGraphics.DrawTo[dc, [0, scratchpadData.path[scratchpadData.path.len-1][2]],
scratchpadData.origin];
PadGraphics.DrawSquare[dc, squareSide, [0, scratchpadData.path[scratchpadData.path.len-1][2]],
scratchpadData.origin];
PadGraphics.MirrorMoveTo[dc, [0, scratchpadData.path[0][2]], scratchpadData.origin];
FOR i:
NAT
IN[0..scratchpadData.path.len)
DO
PadGraphics.MirrorDrawTo[dc, scratchpadData.path[i], scratchpadData.origin];
PadGraphics.MirrorDrawSquare[dc, squareSide, scratchpadData.path[i], scratchpadData.origin];
ENDLOOP;
End at y axis to show user how the final sweep will look
PadGraphics.MirrorDrawTo[dc,
[0, scratchpadData.path[scratchpadData.path.len-1][2]],
scratchpadData.origin];
}; -- end of PaintPoly
PaintLin:
PUBLIC
PROC [dc: Imager.Context, scratchpadData: ScratchpadData] =
TRUSTED {
Paint right side
IF scratchpadData.path.len = 0 THEN RETURN;
Imager.SetColor[dc, Imager.black];
PadGraphics.MoveTo[dc, scratchpadData.path[0], scratchpadData.origin];
PadGraphics.DrawSquare[dc, squareSide, scratchpadData.path[0], scratchpadData.origin];
FOR i:
NAT
IN[1..scratchpadData.path.len)
DO
PadGraphics.DrawTo[dc, scratchpadData.path[i], scratchpadData.origin];
PadGraphics.DrawSquare[dc, squareSide, scratchpadData.path[i], scratchpadData.origin];
ENDLOOP;
PadGraphics.DrawTo[dc, scratchpadData.path[0], scratchpadData.origin];
}; -- end of PaintLin
EraseButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
DoEraseButton:
PROC [dc: Imager.Context] =
TRUSTED {
Erase[dc];
};
Painter[DoEraseButton, scratchViewerData];
};
Erase:
PUBLIC
PROC [dc: Imager.Context] =
TRUSTED {
ir: Imager.Rectangle;
Imager.SetColor[dc, Imager.white];
ir ← ImagerBackdoor.GetBounds[dc];
Imager.MaskRectangle[dc, ir];
};
NormalsButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
Go through each segment of the current picture. Find its outward pointing normal and draw it.
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
path: Path ← scratchpadData.path;
iPlusOne: NAT;
p1, p2: Point2d;
seg: TrigLineSeg;
normal: Vector2d;
midpoint: Point2d;
DoDrawNormals:
PROC [dc: Imager.Context] =
TRUSTED {
mark: Graphics.Mark ← Graphics.Save[dc];
Imager.SetColor[dc, Imager.black];
FOR i:
NAT
IN [0..path.len)
DO
iPlusOne ← IF i = path.len -1 THEN 0 ELSE i + 1;
p1 ← path[i];
p2 ← path[iPlusOne];
seg ← SVLines2d.CreateTrigLineSeg[p1, p2];
normal ← SVVector2d.LeftNormalOfTrigLineSeg[seg];
midpoint[1] ← (p1[1]+p2[1])/2;
midpoint[2] ← (p1[2] + p2[2])/2;
PadGraphics.Draw2dVector[dc: dc, vec: normal, at: midpoint, origin: scratchpadData.origin];
ENDLOOP;
Imager.SetColor[dc, Imager.black];
Graphics.Restore[dc,mark];
};
Painter[DoDrawNormals, scratchViewerData];
};
PlaceOrigin:
PUBLIC
PROC [viewer: Viewer] =
TRUSTED {
viewer is the scratchpad window
find the center of the scratchpad window in scratchpad window coordinates
originX, originY: INTEGER;
scratchpadData: ScratchpadData ← NARROW[viewer.data];
originX ← viewer.cw;-- convert window width to real
originY ← viewer.ch;-- convert window height to real
originX ← originX/2;-- find the midpoint in window coords
originY ← originY/2;
scratchpadData.origin ← [originX, originY];
};
CrossHairsButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ←
NARROW[scratchViewerData.scratchpad.data];
DoCrossHairsButton:
PROC [dc: Imager.Context] =
TRUSTED {
CrossHairs[dc, scratchpadData];
};
Painter[DoCrossHairsButton, scratchViewerData];
};
CrossHairs:
PUBLIC
PROC [dc: Imager.Context, scratchpadData: ScratchpadData] =
TRUSTED {
Imager.SetColor[dc, Imager.black];
PadGraphics.CrossHairs[dc, scratchpadData.origin];
};
DrawSceneButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
DoDrawSceneButton:
PROC [dc: Imager.Context] =
TRUSTED {
Erase[dc];
CrossHairs[dc, scratchpadData];
DrawScene[dc, scratchpadData];
};
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
Painter[DoDrawSceneButton, scratchViewerData];
};
DrawScene:
PUBLIC
PROC [dc: Imager.Context, scratchpadData: ScratchpadData] =
TRUSTED {
SELECT scratchpadData.mode
FROM
drawLin => PaintLin[dc, scratchpadData];
drawRevo => PaintRevo[dc, scratchpadData];
drawSlice => PaintSlice[dc, scratchpadData];
ENDCASE;
};
NewLinButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
currentState: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[currentState.scratchpad.data];
scratchpadData.mode ← drawLin;
SVPolygon2d.ClearPath[scratchpadData.path];
DrawSceneButton[parent, clientData, mouseButton, shift, control];
}; -- end of NewLine
NewRevoButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
currentState: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[currentState.scratchpad.data];
scratchpadData.mode ← drawRevo;
SVPolygon2d.ClearPath[scratchpadData.path];
DrawSceneButton[parent, clientData, mouseButton, shift, control];
}; -- end of NewRevo
TestPointsButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
currentState: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ←
NARROW[currentState.scratchpad.data];
scratchpadData.mode ← pointAt;
}; -- end of TestPoints
CircleButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
DoDrawCircle:
PROC [dc: Imager.Context] =
TRUSTED {
Imager.SetColor[dc, Imager.black];
PadGraphics.Circle[dc, scratchpadData.origin[1], scratchpadData.origin[2], 100];
};
Painter[DoDrawCircle, scratchViewerData];
}; -- end of Circle
DrawSliceButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
Find the current target object and use its current plane as the slicing plane. To keep from allocating a new slice record, we reuse the old one when possible.
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
editToolData: EditToolData ← NARROW[scratchViewerData.editToolData];
viewerToolData: ViewerToolData ← editToolData.currentViewerToolData;
planeAssembly: Assembly;
block: FrameBlock;
toolData: ToolData;
camera: Camera ← viewerToolData.camera;
scene: Scene ← editToolData.sceneSection.currentScene;
slice: Slice;
plane: NAT;
tree: CSGTree;
xSize, ySize, width, height, scalar, padRatio, sliceRatio: REAL;
DoDrawSliceAux:
PROC [dc: Imager.Context] =
TRUSTED {
body:
PROC =
TRUSTED {
Erase[dc];
Imager.TranslateT[dc, [scratchpadData.origin[1], scratchpadData.origin[2]]];
Imager.ScaleT[dc, scalar];
Imager.TranslateT[dc, [-scratchpadData.origin[1], -scratchpadData.origin[2]]];
PaintSlice[dc, scratchpadData];
};
Imager.DoSaveAll[dc, body];
};
planeAssembly ← SVSelections.TopPlaneCoincident[];
IF planeAssembly = NIL THEN RETURN; -- no slice plane.
IF planeAssembly.toolMasterObject =
NIL
THEN
DisplayList3d.AddOrResizeToolToAssembly[planeAssembly, scene];
toolData ← NARROW[planeAssembly.toolMasterObject.mainBody];
block ← CopyFrameBlock[toolData.block];
plane ← toolData.plane;
IF scratchpadData.slice =
NIL
THEN {
There has been no previous slice. Use the planeAssembly to make one.
slice ← SVSlices.CreateSlice[100, planeAssembly.coordSys, block, plane];
scratchpadData.slice ← slice;
}
ELSE {
slice ← scratchpadData.slice;
SVSlices.UpdateSlice[slice, planeAssembly.coordSys, CopyFrameBlock[block], plane];
};
Now we must make a ray-tracing tree.
tree ← DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera];
viewerToolData.tree ← tree;
Now, we must ray-trace the current scene along this plane. This is view-point independent, but we need a camera anyway to specify the bounding spheres.
SVSlices.
RayTraceTheSlice [slice, tree, camera];
Finally, we must tell the Scratchpad to draw it.
xSize ← scratchpadData.origin[1]*2.0;
ySize ← scratchpadData.origin[2]*2.0;
padRatio ← xSize/ySize;
[width, height] ← SVSlices.WidthAndHeight[slice];
sliceRatio ← width/height;
IF sliceRatio > padRatio THEN scalar ← 0.6*xSize/width
ELSE scalar ← 0.6*ySize/height;
Painter[
DoDrawSliceAux, scratchViewerData];
Also, draw the slice on the appropriate solid viewer.
SVViewerUser.DrawSlice[viewerToolData, slice];
}; -- end of DrawSliceButton
CopyFrameBlock:
PRIVATE PROC [block: FrameBlock]
RETURNS [copy: FrameBlock] = {
copy ← NEW[FrameBlockObj];
copy.loX ← block.loX;
copy.hiX ← block.hiX;
copy.loY ← block.loY;
copy.hiY ← block.hiY;
copy.loZ ← block.loZ;
copy.hiZ ← block.hiZ;
};
SliceRepeatButton:
PUBLIC PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] = {
Like DrawSliceButton but doesn't recompute the ray tracing tree.
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
editToolData: EditToolData ← NARROW[scratchViewerData.editToolData];
viewerToolData: ViewerToolData ← editToolData.currentViewerToolData;
planeAssembly: Assembly;
camera: Camera ← viewerToolData.camera;
scene: Scene ← editToolData.sceneSection.currentScene;
slice: Slice;
tree: CSGTree;
xSize, ySize, width, height, scalar, padRatio, sliceRatio: REAL;
DoSliceRepeatButton:
PROC [dc: Imager.Context] =
TRUSTED {
body:
PROC =
TRUSTED {
Erase[dc];
Imager.TranslateT[dc, [scratchpadData.origin[1], scratchpadData.origin[2]]];
Imager.ScaleT[dc, scalar];
Imager.TranslateT[dc, [-scratchpadData.origin[1], -scratchpadData.origin[2]]];
PaintSlice[dc, scratchpadData];
};
Imager.DoSaveAll[dc, body];
};
planeAssembly ← SVSelections.TopTargetCoincident[];
IF planeAssembly = NIL THEN RETURN;
slice ← scratchpadData.slice;
slice.coordSys ← planeAssembly.coordSys;
tree ← viewerToolData.tree;
Now, we must ray-trace the current scene along this plane. This is view-point independent, but we need a camera anyway to specify the bounding spheres.
SVSlices.RayTraceTheSlice [slice, tree, camera];
Finally, we must tell the Scratchpad to draw it.
xSize ← scratchpadData.origin[1]*2.0;
ySize ← scratchpadData.origin[2]*2.0;
padRatio ← xSize/ySize;
[width, height] ← SVSlices.WidthAndHeight[slice];
sliceRatio ← width/height;
IF sliceRatio > padRatio THEN scalar ← 0.6*xSize/width
ELSE scalar ← 0.6*ySize/height;
Painter[DoSliceRepeatButton, scratchViewerData];
Also, draw the slice on the appropriate solid viewer.
SVViewerUser.DrawSlice[viewerToolData, slice];
}; -- end of SliceRepeatButton
HardcopyButton:
PUBLIC
PROC [parent:
REF
ANY, clientData:
REF
ANY, mouseButton: MouseButton, shift, control:
BOOL] =
TRUSTED {
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
editToolData: EditToolData ← NARROW[scratchViewerData.editToolData];
viewerToolData: ViewerToolData ← editToolData.currentViewerToolData;
Timing Varables
startTime: BasicTime.GMT;
endTime: BasicTime.GMT;
totalTime: INT;
timeRope: Rope.ROPE;
pixelsPerMeter:
REAL ← 0.0254 / 72.0;
Interpress Variables
ipressName: Rope.ROPE;
ipRef: ImagerInterpress.Ref;
DoMakeInterpress:
SAFE
PROC [dc: Imager.Context] =
TRUSTED {
Imager.ScaleT[dc, pixelsPerMeter];
DrawScene[dc, scratchpadData];
};
Start Timing
startTime ← BasicTime.Now[];
Start Pressing
ipressName ← ViewerTools.GetContents[viewerToolData.textSection.ais];
ipressName ← Rope.Concat[SVFiles.FilenameMinusExtension[ipressName], ".pd"];
SVError.Append[Rope.Cat["Interpressing file ", ipressName, " ..."], TRUE, TRUE];
ipRef ← ImagerInterpress.Create[ipressName];
ImagerInterpress.DoPage[ipRef, DoMakeInterpress, 1.0];
ImagerInterpress.Close[ipRef];
endTime ← BasicTime.Now[];
totalTime ← BasicTime.Period[startTime, endTime];
timeRope ← IO.PutFR[" Done in (%r)", [integer[totalTime]]];
SVError.Append[timeRope, TRUE, TRUE];
};
EditMode: TYPE = Scratchpad2dUser.EditMode;-- {lin, revo};
SetSlice:
PUBLIC
PROC [scratchViewerData: ScratchViewerData, slice: Slice] = {
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
scratchpadData.slice ← slice;
};
Edit:
PUBLIC
PROC [path: Path, mode: EditMode, scratchViewerData: ScratchViewerData] =
TRUSTED {
scratchpad: ViewerClasses.Viewer ← scratchViewerData.scratchpad;
scratchpadData: ScratchpadData ← NARROW[scratchpad.data];
scratchpadData.path ← path;
SELECT mode FROM
lin => {scratchpadData.mode ← drawLin;
DrawSceneButton [scratchpad, scratchpadData.scratchViewerData, red, FALSE, FALSE];
};
revo => {scratchpadData.mode ← drawRevo;
DrawSceneButton [scratchpad, scratchpadData.scratchViewerData, red, FALSE, FALSE];
};
ENDCASE => ERROR;
}; -- end of Edit
PaintSlice:
PROC [dc: Imager.Context, scratchpadData: ScratchpadData] ~ {
slice: Slice;
origin: Point2d;
Erase[dc];
CrossHairs[dc, scratchpadData];
scratchpadData.mode ← drawSlice;
slice ← scratchpadData.slice;
origin ← scratchpadData.origin;
Imager.SetColor[dc, Imager.black];
SVSlices.DrawSlice[dc, slice, origin];
END.