File: SVScratchpadUserImpl.mesa
Last edited by: Eric Bier on August 7, 1987 0:32:19 am PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: Functions called by the buttons on a SVScratchpad viewer.
DIRECTORY
BasicTime, Containers, SVSceneToTree, Feedback, Imager, ImagerBackdoor, ImagerInterpress, IO, Menus, SVPadGraphics, Rope, SVScratchpadUser, SV2d, SVEvent, SVFiles, SVInterfaceTypes, SVLines2d, SVModelTypes, SVPolygon2d, SVScene, SVSceneTypes, SVSelections, SVCatScan, SVVector2d, SVViewerTool, ViewerClasses, ViewerOps;
SVScratchpadUserImpl: CEDAR PROGRAM
IMPORTS BasicTime, SVSceneToTree, Feedback, Imager, ImagerBackdoor, ImagerInterpress, IO, SVPadGraphics, Rope, SVEvent, SVFiles, SVLines2d, SVPolygon2d, SVScene, SVSelections, SVCatScan, SVVector2d, ViewerOps
EXPORTS SVScratchpadUser =
BEGIN
Slice: TYPE = SVSceneTypes.Slice;
Camera: TYPE = SVModelTypes.Camera;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CSGTree: TYPE = SVSceneTypes.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;
CatScan: TYPE = SVCatScan.CatScan;
ToolData: TYPE = SVSceneTypes.ToolData;
TrigLineSeg: TYPE = SV2d.TrigLineSeg;
Vector2d: TYPE = SV2d.Vector2d;
Viewer: TYPE = ViewerClasses.Viewer;
SVData: TYPE = SVInterfaceTypes.SVData;
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
SVPadGraphics.MoveTo[dc, [0, scratchpadData.path[0][2]], scratchpadData.origin];
SVPadGraphics.DrawSquare[dc, squareSide, [0, scratchpadData.path[0][2]], scratchpadData.origin];
FOR i: NAT IN[0..scratchpadData.path.len) DO
SVPadGraphics.DrawTo[dc, scratchpadData.path[i], scratchpadData.origin];
SVPadGraphics.DrawSquare[dc, squareSide, scratchpadData.path[i], scratchpadData.origin];
ENDLOOP;
End at y axis to show user how the final sweep will look
SVPadGraphics.DrawTo[dc, [0, scratchpadData.path[scratchpadData.path.len-1][2]],
scratchpadData.origin];
SVPadGraphics.DrawSquare[dc, squareSide, [0, scratchpadData.path[scratchpadData.path.len-1][2]],
scratchpadData.origin];
Now paint left side
SVPadGraphics.MirrorMoveTo[dc, [0, scratchpadData.path[0][2]], scratchpadData.origin];
FOR i: NAT IN[0..scratchpadData.path.len) DO
SVPadGraphics.MirrorDrawTo[dc, scratchpadData.path[i], scratchpadData.origin];
SVPadGraphics.MirrorDrawSquare[dc, squareSide, scratchpadData.path[i], scratchpadData.origin];
ENDLOOP;
End at y axis to show user how the final sweep will look
SVPadGraphics.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];
SVPadGraphics.MoveTo[dc, scratchpadData.path[0], scratchpadData.origin];
SVPadGraphics.DrawSquare[dc, squareSide, scratchpadData.path[0], scratchpadData.origin];
FOR i: NAT IN[1..scratchpadData.path.len) DO
SVPadGraphics.DrawTo[dc, scratchpadData.path[i], scratchpadData.origin];
SVPadGraphics.DrawSquare[dc, squareSide, scratchpadData.path[i], scratchpadData.origin];
ENDLOOP;
SVPadGraphics.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;
SVPadGraphics.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];
SVPadGraphics.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];
drawCatScan => PaintCatScan[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];
SVPadGraphics.Circle[dc, scratchpadData.origin[1], scratchpadData.origin[2], 100];
};
Painter[DoDrawCircle, scratchViewerData];
}; -- end of Circle
DrawCatScanButton: 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: SVData ← editToolData.currentSVData;
planeAssembly: Slice;
block: FrameBlock;
toolData: ToolData;
camera: Camera ← viewerToolData.camera;
scene: Scene ← editToolData.sceneSection.currentScene;
catScan: CatScan;
plane: NAT;
tree: CSGTree;
xSize, ySize, width, height, scalar, padRatio, sliceRatio: REAL;
DoDrawCatScanAux: 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]]];
PaintCatScan[dc, scratchpadData];
};
Imager.DoSaveAll[dc, body];
};
planeAssembly ← SVSelections.TopPlaneCoincident[];
IF planeAssembly = NIL THEN RETURN; -- no slice plane.
IF planeAssembly.toolMasterObject = NIL THEN
SVScene.AddOrResizeToolToAssembly[planeAssembly, scene];
toolData ← NARROW[planeAssembly.toolMasterObject.mainBody];
block ← CopyFrameBlock[toolData.block];
plane ← toolData.plane;
IF scratchpadData.catScan = NIL THEN {
There has been no previous slice. Use the planeAssembly to make one.
catScan ← SVCatScan.CreateCatScan[100, planeAssembly.coordSys, block, plane];
scratchpadData.catScan ← catScan;
}
ELSE {
catScan ← scratchpadData.catScan;
SVCatScan.UpdateCatScan[catScan, planeAssembly.coordSys, CopyFrameBlock[block], plane];
};
Now we must make a ray-tracing tree.
tree ← SVSceneToTree.AssemblyToTree[scene.assembly, scene, camera];
viewerToolData.scene.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.
SVCatScan.RayTraceTheCatScan [catScan, 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] ← SVCatScan.WidthAndHeight[catScan];
sliceRatio ← width/height;
IF sliceRatio > padRatio THEN scalar ← 0.6*xSize/width
ELSE scalar ← 0.6*ySize/height;
Painter[DoDrawCatScanAux, scratchViewerData];
Also, draw the catScan on the appropriate solid viewer.
SVEvent.DrawCatScan[viewerToolData, catScan];
}; -- end of DrawCatScanButton
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;
};
CatScanRepeatButton: PUBLIC PROC [parent: REF ANY, clientData: REF ANY, mouseButton: MouseButton, shift, control: BOOL] = {
Like DrawCatScanButton but doesn't recompute the ray tracing tree.
scratchViewerData: ScratchViewerData ← NARROW[clientData];
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
editToolData: EditToolData ← NARROW[scratchViewerData.editToolData];
viewerToolData: SVData ← editToolData.currentSVData;
planeAssembly: Slice;
camera: Camera ← viewerToolData.camera;
scene: Scene ← editToolData.sceneSection.currentScene;
catScan: CatScan;
tree: CSGTree;
xSize, ySize, width, height, scalar, padRatio, sliceRatio: REAL;
DoCatScanRepeatButton: 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]]];
PaintCatScan[dc, scratchpadData];
};
Imager.DoSaveAll[dc, body];
};
planeAssembly ← SVSelections.TopTargetCoincident[];
IF planeAssembly = NIL THEN RETURN;
catScan ← scratchpadData.catScan;
catScan.coordSys ← planeAssembly.coordSys;
tree ← viewerToolData.scene.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.
SVCatScan.RayTraceTheCatScan [catScan, 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] ← SVCatScan.WidthAndHeight[catScan];
sliceRatio ← width/height;
IF sliceRatio > padRatio THEN scalar ← 0.6*xSize/width
ELSE scalar ← 0.6*ySize/height;
Painter[DoCatScanRepeatButton, scratchViewerData];
Also, draw the catScan on the appropriate solid viewer.
SVEvent.DrawCatScan[viewerToolData, catScan];
}; -- end of CatScanRepeatButton
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: SVData ← editToolData.currentSVData;
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 ← Rope.Concat[SVFiles.FilenameMinusExtension["Scratchpad.ais"], ".pd"];
Feedback.Append[viewerToolData.feedback, Rope.Cat["Interpressing file ", ipressName, " ..."], oneLiner];
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]]];
Feedback.AppendRaw[$Solidviews, timeRope, oneLiner];
};
EditMode: TYPE = SVScratchpadUser.EditMode;-- {lin, revo};
SetCatScan: PUBLIC PROC [scratchViewerData: ScratchViewerData, catScan: CatScan] = {
scratchpadData: ScratchpadData ← NARROW[scratchViewerData.scratchpad.data];
scratchpadData.catScan ← catScan;
};
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
PaintCatScan: PROC [dc: Imager.Context, scratchpadData: ScratchpadData] ~ {
catScan: CatScan;
origin: Point2d;
Erase[dc];
CrossHairs[dc, scratchpadData];
scratchpadData.mode ← drawCatScan;
catScan ← scratchpadData.catScan;
origin ← scratchpadData.origin;
Imager.SetColor[dc, Imager.black];
SVCatScan.DrawCatScan[dc, catScan, origin];
};
END.