File: Scratchpad2dUserImpl.mesa
Last edited by: Eric Bier on August 20, 1984 0:59:09 am 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,
ImagerPD,
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, ImagerPD, 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];
Now paint left side
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.IntRectangle;
Imager.SetColor[dc, Imager.white];
ir ← Imager.GetViewBox[dc];
Imager.IntegerMaskRectangle[dc, ir.x, ir.y, ir.w, ir.h];
};
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;
Interpress Variables
ipressName: Rope.ROPE;
pdDes: ImagerPD.PDFileDescription;
ipressContext: Imager.Context;
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];
pdDes ← ImagerPD.Hornet[ipressName];
ipressContext ← Imager.Create[$PD, pdDes];
Imager.ScaleT[ipressContext, 3.527778e-4]; -- units in screen dots
DrawScene[ipressContext, scratchpadData];
[] ← Imager.SpecialOp[ipressContext, $Close, NIL];
GraphicsToPress.Close[pressContext];
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.