DIRECTORY Buttons, CedarProcess, CtBasic, Commander, CommanderOps, Controls, Convert, Draw2d, FileNames, FS, G3dBasic, G3dControl, G3dMatrix, G3dTool, Icons, Imager, ImagerBackdoor, ImagerFont, ImplicitSlice, MessageWindow, Real, Rope, SF, TEditSelection, TiogaMenuOps, VFonts, ViewerClasses, ViewerOps, ViewerTools;
ImplicitSliceImpl: CEDAR PROGRAM
IMPORTS Buttons, CedarProcess, CtBasic, Commander, CommanderOps, Controls, Convert, Draw2d, FileNames, FS, G3dControl, G3dMatrix, G3dTool, Icons, Imager, ImagerBackdoor, ImagerFont, MessageWindow, Real, Rope, TEditSelection, TiogaMenuOps, VFonts, ViewerOps, ViewerTools
EXPORTS ImplicitSlice
~ BEGIN
CommandProc: TYPE ~ Commander.CommandProc;
ButtonList: TYPE ~ Controls.ButtonList;
ClickProc: TYPE ~ Controls.ClickProc;
Control: TYPE ~ Controls.Control;
ControlList: TYPE ~ Controls.ControlList;
SampleMap: TYPE ~ CtBasic.SampleMap;
SampleMaps: TYPE ~ CtBasic.SampleMaps;
DrawProc: TYPE ~ Draw2d.DrawProc;
Pair: TYPE ~ G3dBasic.Pair;
Triple: TYPE ~ G3dBasic.Triple;
Slice: TYPE ~ G3dControl.Slice;
Context: TYPE ~ Imager.Context;
Function: TYPE ~ ImplicitSlice.Function;
Pix: TYPE ~ ImplicitSlice.Pix;
PixRep: TYPE ~ ImplicitSlice.PixRep;
PixSequence: TYPE ~ ImplicitSlice.PixSequence;
Tool: TYPE ~ ImplicitSlice.Tool;
ToolRep: TYPE ~ ImplicitSlice.ToolRep;
ROPE: TYPE ~ Rope.ROPE;
Viewer: TYPE ~ ViewerClasses.Viewer;
icon: Icons.IconFlavor _ Icons.NewIconFromFile["ImplicitSurfaces.icon", 0];
MakeTool: PUBLIC PROC [
toolName: ROPE,
functions: LIST OF Function _ NIL,
clientDraw: DrawProc _ NIL,
clientData: REF ANY _ NIL,
extraControls: ControlList _ NIL,
extraButtons: ButtonList _ NIL]
RETURNS [t: Tool]
~ {
t _ NEW[ToolRep];
t.clientDraw _ clientDraw;
t.clientData _ clientData;
t.slice _ G3dControl.InitSlice[proc: SliceControl, data: t];
t.slice.phi.value _ 90.0;
FOR b: ButtonList _ extraButtons, b.rest WHILE b # NIL DO b.first.row _ 1; ENDLOOP;
extraButtons _ CONS[Controls.ClickButton["Help", Help, t, 0], extraButtons];
extraButtons _ CONS[Controls.ClickButton["IP Out", IPOut, t, 0], extraButtons];
extraButtons _ CONS[Controls.ClickButton["Display-Ops", DisplayOps, t, 0], extraButtons];
extraButtons _ CONS[Controls.TextButton["MoveSlice: ","-.03", CheckValue, t, 0], extraButtons];
extraButtons _ CONS[Controls.TextButton["H: ", "80 ", CheckValue, t, 0], extraButtons];
extraButtons _ CONS[Controls.TextButton["W: ", "80 ", CheckValue, t, 0], extraButtons];
extraButtons _ CONS[Controls.ClickButton["Name", NamePix, t, 0], extraButtons];
extraButtons _ CONS[Controls.ClickButton["STOP", Stop, t, 0], extraButtons];
extraButtons _ CONS[Controls.ClickButton["StartAndMove", StartAndMove, t, 0], extraButtons];
extraButtons _ CONS[Controls.ClickButton["Start", Start, t, 0], extraButtons];
extraButtons _ CONS[Controls.ClickButton["Mode: Slice", ToggleMode, t, 0], extraButtons];
extraControls _ CONS[t.slice.size, extraControls];
extraControls _ CONS[t.slice.theta, extraControls];
extraControls _ CONS[t.slice.phi, extraControls];
extraControls _ CONS[t.slice.z, extraControls];
extraControls _ CONS[t.slice.y, extraControls];
extraControls _ CONS[t.slice.x, extraControls];
FOR f: LIST OF Function _ functions, f.rest WHILE f # NIL DO AddPix[t, f.first]; ENDLOOP;
t.renderTool _ G3dTool.MakeTool[
name: toolName,
ops: [TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE],
extraButtons: extraButtons,
extraControls: extraControls,
controlSizes: [15, 200, 60, 20, 60, 150, 150],
arcBallSize: 80,
nViews: 3,
client: [mouse: Mouse3d, destroy: Destroy, draw: Draw, data: t],
noOpen: TRUE];
t.viewer2d _ Controls.OuterViewer[mouse: Mouse2d, clientData: t, destroy: Destroy];
t.renderTool.outer.icon _ icon;
t.typescript _ t.renderTool.typescript;
t.valueViewer _ ViewerOps.CreateViewer[
flavor: $ValueViewer, paint: FALSE, info: [data: t, scrollable: FALSE, wx: 510, wy: 16, ww: 80, wh: 80, border: FALSE, parent: t.renderTool.outer]];
ViewerOps.AddProp[t.valueViewer, $CreatedInOuterViewer, $True];
ViewerOps.OpenIcon[t.renderTool.outer];
};
Destroy: Controls.DestroyProc ~ {NARROW[clientData, Tool].stop _ TRUE};
SliceControl: Controls.ControlProc ~ {
t: Tool _ NARROW[control.clientData];
t.pixPicked _ NIL;
G3dControl.UpdateSlice[t.slice];
IF control.whatChanged = $TypedIn OR control.mouse.button = right THEN Repaint[t, $Slice];
};
Mouse3d: Controls.MouseProc ~ {
t: Tool _ NARROW[clientData];
IF mouse.controlKey THEN {
x: G3dMatrix.Matrix _ G3dTool.GetView[viewer, t.renderTool].camera.matrix;
t.pixPicked _ t.pixes[0];
t.point _ SELECT t.mode FROM
slice => G3dMatrix.TripleFromScreenAndPlane[[mouse.pos.x, mouse.pos.y], t.slice.plane, x],
ENDCASE => t.renderTool.sprite;
IF t.pixPicked # NIL AND t.pixPicked.valueProc # NIL THEN {
t.value _ t.pixPicked.valueProc[t.point, t.clientData];
ViewerOps.PaintViewer[t.valueViewer, client, FALSE];
};
};
};
Mouse2d: Controls.MouseProc ~ {
t: Tool ~ NARROW[clientData];
IF mouse.state = up AND mouse.pos.y <= t.ySize THEN
FOR n: NAT IN [0..t.pixes.length) DO
t.pixPicked _ t.pixes[n];
IF mouse.pos.x IN [t.pixPicked.box.min.f..t.pixPicked.box.max.f] THEN {
t.point _ GetPixPoint[t, t.pixPicked, mouse.pos.x, mouse.pos.y];
Repaint[t, $PixPicked];
EXIT;
};
ENDLOOP;
};
Repaint: PUBLIC PROC [tool: Tool, whatChanged: REF ANY _ NIL] ~ {
G3dTool.Repaint[tool.renderTool, whatChanged];
};
PaintValueViewer: ViewerClasses.PaintProc ~ {
Action: PROC ~ {
IF whatChanged = NIL THEN Draw2d.Circle[context, [size, size], size];
Draw2d.Circle[context, [size, size], radius, t.value > 0.0];
};
t: Tool _ NARROW[self.data];
size: INTEGER _ self.ww/2;
radius: REAL _ ABS[t.value]*self.ww;
Draw2d.DoWithBuffer[context, Action];
};
Draw: DrawProc ~ {
t: Tool ~ NARROW[data];
DiagramPix: PROC [pix: Pix] ~ {
IF v.index = 0 AND pix # NIL AND pix.diagramProc # NIL
THEN pix.diagramProc[context, t.point, t.clientData, whatChanged, viewer];
};
DrawSlice: PROC ~ {
IF t.mode = slice AND t.showSlice
THEN G3dControl.DrawSlice[context, t.slice, v.camera.matrix, vp];
};
v: G3dTool.View _ G3dTool.GetView[viewer, t.renderTool];
vp: G3dMatrix.Viewport _ G3dView.GetViewport[viewer];
SELECT whatChanged FROM
$Clear => Draw2d.Clear[context];
$Slice => G3dTool.Restore[context, v];
$FinishingTouches => {DiagramPix[t.pixPicked]; DrawSlice[]};
ENDCASE =>
IF t.clientDraw # NIL THEN t.clientDraw[context, t.clientData, whatChanged, viewer];
IF t.cdContext # NIL THEN context _ t.cdContext;
};
DisplayOps: ClickProc ~ {
t: Tool _ NARROW[clientData];
SELECT Controls.PopUpRequest[["Display Options"], LIST[
Controls.BoolRequest[t.showSlice, "Show Slice"]]] FROM
1 => t.showSlice _ NOT t.showSlice;
ENDCASE => RETURN;
IF Controls.GetPopUpButton[] = right THEN Repaint[t];
};
ToggleMode: ClickProc ~ {
t: Tool _ NARROW[clientData];
IF t.mode = slice
THEN {t.mode _ sprite; Buttons.ReLabel[parent, "Mode: Sprite"]}
ELSE {t.mode _ slice; Buttons.ReLabel[parent, "Mode: Slice"]};
t.renderTool.drawSprite _ t.mode = sprite;
Repaint[t];
};
doc: ROPE _ FileNames.StripVersionNumber[FS.FileInfo["ImplicitSurfacesDoc.tioga"].fullFName];
Help: ClickProc ~ {
v: Viewer _ TiogaMenuOps.Open[doc,, right];
TEditSelection.FindRope[v, "ImplicitSlice Buttons and Controls"];
};
IPOut: ClickProc ~ {
t: Tool _ NARROW[clientData];
Draw2d.IPOut[Controls.TypescriptReadFileName[t.typescript], Draw, t];
};
NamePix: ClickProc ~ {SetUpPix[NARROW[clientData], 0.5, FALSE, TRUE]};
SetParameters: PROC [t: Tool] ~ {
FOR b: LIST OF Controls.Button _ t.renderTool.buttons, b.rest WHILE b # NIL DO
E: PROC [r: ROPE] RETURNS [BOOL] ~ {RETURN[Rope.Equal[b.first.name, r, FALSE]]};
N: PROC [o: REAL] RETURNS [i: REAL] ~ {
r: ROPE _ ViewerTools.GetContents[b.first.textViewer];
i _ Convert.RealFromRope[r ! Convert.Error => {Blink["Bad value"]; i _ o; CONTINUE}];
};
SELECT TRUE FROM
E["MoveSlice: "] => t.moveSlice _ N[t.moveSlice];
E["W: "] => t.xSize _ Real.Round[N[t.xSize]];
E["H: "] => t.ySize _ Real.Round[N[t.ySize]];
ENDCASE;
ENDLOOP;
ResizePixes[t];
};
CheckValue: ClickProc ~ {
button: Controls.Button _ NARROW[ViewerOps.FetchProp[parent, $ButtonText]];
IF button # NIL THEN {
r: ROPE _ ViewerTools.GetContents[button.textViewer];
[] _ Convert.RealFromRope[r ! Convert.Error => {Blink["Bad value"]; CONTINUE}];
};
};
Stop: ClickProc ~ {
t: Tool _ NARROW[clientData];
t.stop _ TRUE;
Controls.TypescriptWrite[t.typescript, " . . . aborted.\n"];
};
Start: ClickProc ~ {StartShade[NARROW[clientData], Shade]};
StartAndMove: ClickProc ~ {StartShade[NARROW[clientData], ShadeAndMoveSlice]};
StartShade: PROC [t: Tool, proc: CedarProcess.ForkableProc] ~ {
t.stop _ FALSE;
SetParameters[t];
[] _ CedarProcess.Fork[proc, t, [background, TRUE]];
t.stop _ FALSE;
};
Shade: CedarProcess.ForkableProc ~ {
t: Tool _ NARROW[data];
SetUpPix[t, 0.0, TRUE, TRUE];
FOR y: NAT IN [1..t.ySize-1) DO
FOR x: NAT IN [1..t.xSize-1) DO
t.point _ GetPixPoint[t, t.pixes[0], x, y];
FOR n: NAT IN [0..t.pixes.length) DO
pix: Pix _ t.pixes[n];
value: REAL _ pix.valueProc[t.point, t.clientData];
pVal: CARDINAL _ Real.Round[MIN[255.0, MAX[0., 255.0*value]]];
xx: NAT _ x+pix.box.min.f;
yy: NAT _ y+pix.box.min.s;
IF t.stop THEN RETURN;
SELECT pix.maps.bpp FROM
8 => CtBasic.PutBWPixel[pix.maps[0].map, xx, yy, pVal];
24 => CtBasic.PutRGBPixel[pix.maps, xx, yy, [pVal, pVal, pVal]];
ENDCASE;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
ShadeAndMoveSlice: CedarProcess.ForkableProc ~ {
t: Tool _ NARROW[data];
box: SF.Box _ t.cdMaps.box;
FOR y: NAT _ box.min.s, y+t.ySize WHILE y < box.max.s DO
FOR x: NAT _ box.min.f, x+t.xSize WHILE x < box.max.f DO
FOR n: NAT IN [0..t.pixes.length) DO
IF t.stop THEN RETURN;
t.pixes[n].maps _ CtBasic.CopyOfMaps[t.cdMaps, x, y, t.xSize, t.ySize];
ENDLOOP;
[] _ Shade[t];
G3dControl.MoveSliceInZ[t.slice, t.moveSlice];
Repaint[t];
ENDLOOP;
ENDLOOP;
};
ImagerShade: CedarProcess.ForkableProc ~ {
t: Tool _ NARROW[data];
t.cdContext _ CtBasic.InitCd[gray];
Repaint[t, $Clear];
[] _ Shade[t];
t.cdContext _ CtBasic.InitCd[smooth];
Repaint[t];
t.cdContext _ NIL;
};
AddPix: PROC [t: Tool, f: Function] ~ {
xStart: NAT _ IF t.pixes # NIL THEN t.xSize*t.pixes.length ELSE 0;
pix: Pix _ NEW[PixRep];
new: REF PixSequence _ NEW[PixSequence[IF t.pixes # NIL THEN t.pixes.length+1 ELSE 1]];
FOR n: NAT IN [0..new.length-1) DO new[n] _ t.pixes[n]; ENDLOOP;
t.pixes _ new;
pix.name _ f.name;
pix.diagramProc _ f.diagramProc;
pix.valueProc _ f.valueProc;
SetPixSize[pix, xStart, 0, t.xSize, t.ySize, t.cdMaps];
t.pixes[t.pixes.length-1] _ pix;
};
SetPixSize: PROC [pix: Pix, x, y, w, h: NAT, cd: SampleMaps] ~ {
pix.maps _ CtBasic.CopyOfMaps[cd, x, y, w, h];
pix.box _ pix.maps.box;
pix.context _ CtBasic.InitCd[smooth, TRUE, FALSE, FALSE];
CtBasic.TransformContextToMap[
pix.context, SELECT pix.maps.bpp FROM 8 => pix.maps[0].map ENDCASE => pix.maps[1].map];
pix.start _ ImagerFont.RopeEscapement[ImagerBackdoor.GetFont[pix.context], pix.name];
pix.start _ [-0.5*pix.start.x, -0.9];
};
ResizePixes: PROC [t: Tool] ~ {
IF t.pixes # NIL THEN FOR n: NAT IN [0..t.pixes.length) DO
SetPixSize[t.pixes[n], n*t.xSize, 0, t.xSize, t.ySize, t.cdMaps];
ENDLOOP;
};
GetPixPoint: PROC [t: Tool, pix: Pix, x, y: NAT] RETURNS [Triple] ~ {
map: SampleMap _ IF pix.maps.bpp = 8 THEN pix.maps[0].map ELSE pix.maps[1].map;
realPair: CtBasic.RealPair _ CtBasic.PairFromMapCoords[x, y, map];
RETURN[G3dMatrix.TransformPair[[realPair.x, realPair.y], t.slice.matrix]];
};
SetUpPix: PROC [t: Tool, gray: REAL, clear, name: BOOL] ~ {
FOR n: NAT IN [0..t.pixes.length) DO
pix: Pix _ t.pixes[n];
Imager.SetGray[pix.context, gray];
Imager.SetStrokeWidth[pix.context, 0.02];
IF clear THEN CtBasic.FillMaps[pix.maps, 100, 100, 100, 100];
IF name THEN Draw2d.Label[pix.context, pix.start, pix.name];
ENDLOOP;
};
Blink: PROC [rope: ROPE] ~ {
MessageWindow.Append[rope, TRUE];
MessageWindow.Blink[];
};
PixelValueFromValue: PROC [value: REAL] RETURNS [CARDINAL] ~ {
RETURN[Real.Round[MIN[255.0, MAX[0.0, 255.0*value]]]];
};
Registration: TYPE ~ RECORD [
name: ROPE, -- name of option
command: CommandProc, -- proc to be called
doc: ROPE -- documentation of option
];
registry: LIST OF Registration _ NIL;
font: VFonts.Font ~ VFonts.EstablishFont["Tioga", 10];
tabWidth: INT _ 2*VFonts.StringWidth["\t"]; -- VFonts says 12; but should be 24
toolOptions: ROPE _ NIL;
toolUsage: ROPE _ "ImplicitSlice