G3dGraphCmdImpl.mesa
Copyright Ó 1988, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, October 20, 1992 5:38 pm PDT
Glassner, September 30, 1988 12:41:52 pm PDT
DIRECTORY Commander, Controls, Draw2d, G3dBasic, G3dControl, G3dDraw, G3dFunction, G3dMatrix, G3dSpline, G3dTool, Imager, IO, Real, RealFns, Rope, ViewerOps;
G3dGraphCmdImpl: CEDAR PROGRAM
IMPORTS Controls, G3dControl, G3dDraw, G3dFunction, Draw2d, G3dSpline, G3dTool, Imager, IO, Real, RealFns, Rope, ViewerOps
~ BEGIN
Imported Types
ROPE:      TYPE ~ Rope.ROPE;
Viewer:     TYPE ~ Controls.Viewer;
ClickProc:    TYPE ~ Controls.ClickProc;
OuterData:    TYPE ~ Controls.OuterData;
Control:     TYPE ~ Controls.Control;
Request:     TYPE ~ Controls.Request;
Triple:     TYPE ~ G3dBasic.Triple;
Camera:     TYPE ~ G3dControl.CameraControl;
Matrix:     TYPE ~ G3dMatrix.Matrix;
Local Types
arraySize:   NAT ~ 40;
GraphData:  TYPE ~ REF GraphDataRep;
GraphDataRep: TYPE ~ RECORD [
a:       Control ¬ NIL,
xMin:      Control ¬ NIL,
xMax:      Control ¬ NIL,
yMin:      Control ¬ NIL,
yMax:      Control ¬ NIL,
zScale:     Control ¬ NIL,
grain:      Control ¬ NIL,
values:     ARRAY [0..arraySize) OF ARRAY [0..arraySize) OF REAL,
graphics:     Viewer ¬ NIL,
outer:      Viewer ¬ NIL,
outerData:    OuterData ¬ NIL,
camera:     Camera ¬ NIL,
view:      Matrix ¬ NIL,
axesOn:     BOOL ¬ TRUE,
graphProc:    GraphProc ¬ Gauss
];
GraphProc:  TYPE ~ PROC [x: REAL, g: GraphData] RETURNS [v: REAL];
RealFunction: TYPE ~ PROC [v: REAL] RETURNS [REAL];
Function:   TYPE ~ RECORD [name: ROPE, use: ROPE, proc: GraphProc];
Viewer Setup
Graph: Commander.CommandProc ~ {
g: GraphData ¬ NEW[GraphDataRep];
g.camera ¬ G3dControl.InitCameraControl[proc: CameraControl, clientData: g];
Controls.SetSliderDialValue[g.camera.par.zMov, -0.5];
g.a ¬ Controls.NewControl["A", , g, , , , Controller];
g.xMin ¬ Controls.NewControl["Xmin", , g, -1.0, 1.0, 0.0, Controller];
g.yMin ¬ Controls.NewControl["Ymin", , g, -1.0, 1.0, 0.0, Controller];
g.xMax ¬ Controls.NewControl["Xmax", , g, -1.0, 1.0, 1.0, Controller];
g.yMax ¬ Controls.NewControl["Ymax", , g, -1.0, 1.0, 1.0, Controller];
g.zScale ¬ Controls.NewControl["Zscale", , g, -5.0, 5.0, 1.0, Controller];
g.grain ¬ Controls.NewControl["Grain", , g, 0.05, 1.0, 0.1, Controller];
ComputeValues[g];
g.outerData ¬ Controls.OuterViewer[
name: "3dGraph Gauss",
buttons: LIST[
Controls.ClickButton["Interpress-Out", InterpressOut, g],
Controls.ClickButton["Function", FunctionSelect, g],
Controls.ClickButton["Axes-On", ToggleAxes, g]
],
controls: LIST[
g.camera.proxySelect,
g.camera.proxy.xMov, g.camera.proxy.yMov, g.camera.proxy.zMov,
g.camera.proxy.xRot, g.camera.proxy.yRot, g.camera.proxy.zRot,
g.xMin, g.xMax, g.yMin, g.yMax, g.zScale, g.grain],
controlSizes: [17, 200, 60, 20, 60, 150, 150],
graphicsHeight: 300,
drawProc: DrawProc,
typescriptHeight: 18,
biScrollable: TRUE,
clientData: g];
g.outer ¬ g.outerData.parent;
g.graphics ¬ g.outerData.graphics;
};
Controller: Controls.ControlProc ~ {
g: GraphData ¬ NARROW[control.clientData];
Set: PROC [control: Control, value: REAL] ~ {Controls.SetSliderDialValue[control, value]};
SELECT control FROM
g.xMin => IF g.xMin.value > g.xMax.value THEN Set[g.xMax, g.xMin.value];
g.yMin => IF g.yMin.value > g.yMax.value THEN Set[g.yMax, g.yMin.value];
g.xMax => IF g.xMax.value < g.xMin.value THEN Set[g.xMin, g.xMax.value];
g.yMax => IF g.xMax.value < g.xMin.value THEN Set[g.yMin, g.yMax.value];
ENDCASE;
Set[g.grain, MAX[g.grain.value, (g.xMax.value-g.xMin.value)/(arraySize-1), (g.yMax.value-g.yMin.value)/(arraySize-1)]];
IF control.whatChanged = $TypedIn OR control.mouse.button = right
THEN Repaint[g, $Controller];
};
Options
InterpressOut: ClickProc ~ {
g: GraphData ¬ NARROW[clientData];
Draw2d.IPOut[Controls.TypescriptReadFileName[g.outerData.typescript], DrawAction, g];
};
ToggleAxes: ClickProc ~ {
g: GraphData ¬ NARROW[clientData];
Controls.ButtonToggle[g.outerData, g.axesOn ¬ NOT g.axesOn, "Axes-On", "Axes-Off"];
IF mouseButton = blue THEN Repaint[g, $Axes];
};
FunctionSelect: ClickProc ~ {
Reverse: PROC [in: LIST OF Request] RETURNS [out: LIST OF Request] ~ {
FOR r: LIST OF Request ¬ in, r.rest WHILE r # NIL DO out ¬ CONS[r.first, out]; ENDLOOP;
};
g: GraphData ¬ NARROW[clientData];
n, choice: INTEGER ¬ 1;
requests: LIST OF Request ¬ NIL;
FOR l: LIST OF Function ¬ functions, l.rest WHILE l # NIL DO
requests ¬ CONS[[l.first.name, l.first.use], requests];
ENDLOOP;
choice ¬ Controls.PopUpRequest[["Function Select"], Reverse[requests]];
FOR l: LIST OF Function ¬ functions, l.rest WHILE l # NIL DO
IF n = choice THEN {
g.graphProc ¬ l.first.proc;
g.outer.name ¬ Rope.Concat["3dGraph ", l.first.name];
ViewerOps.PaintViewer[g.outer, caption];
EXIT;
};
n ¬ n+1;
ENDLOOP;
Repaint[g, $FunctionSelect];
};
View Control
CameraControl: Controls.ControlProc ~ {
g: GraphData ¬ NARROW[clientData];
IF control.mouse.button # right THEN RETURN;
Repaint[g, $Camera];
};
LF Display
Repaint: PROC [g: GraphData, whatChanged: REF ANY ¬ NIL] ~ {
IF whatChanged # $Camera THEN ComputeValues[g];
ViewerOps.PaintViewer[g.graphics, client, FALSE, whatChanged];
};
DrawProc: Controls.DrawProc ~ {
g: GraphData ~ NARROW[clientData];
Action: PROC ~ {
G3dControl.UpdateCamera[g.camera];
g.view ¬ G3dControl.InitContext[context, g.camera, viewer, , g.view];
DrawAction[context, g, whatChanged, viewer];
};
Draw2d.DoWithBuffer[context, Action];
};
ComputeValues: PROC [g: GraphData] ~ {
ix, iy: NAT ¬ 0;
FOR x: REAL ¬ g.xMin.value, x+g.grain.value WHILE x < g.xMax.value DO
xValue: REAL ¬ 0.0;
xValue ¬ g.graphProc[x, g ! Real.RealException => CONTINUE];
iy ¬ 0;
FOR y: REAL ¬ g.yMin.value, y+g.grain.value WHILE y < g.yMax.value DO
yValue: REAL ¬ 0.0;
yValue ¬ g.graphProc[y, g ! Real.RealException => CONTINUE];
g.values[ix][iy] ¬ g.zScale.value*xValue*yValue;
iy ¬ iy+1;
ENDLOOP;
ix ¬ ix+1;
ENDLOOP;
};
DrawAction: Controls.DrawProc ~ {
g: GraphData ~ NARROW[clientData];
ix, iy: NAT ¬ 0;
FOR x: REAL ¬ g.xMin.value, x+g.grain.value WHILE x < g.xMax.value DO
p0: Triple ¬ [x, g.yMin.value, g.values[ix][iy ¬ 0]];
FOR y: REAL ¬ g.yMin.value+g.grain.value, y+g.grain.value WHILE y < g.yMax.value DO
p1: Triple ¬ [x, y, g.values[ix][iy ¬ iy+1]];
G3dDraw.Segment[context, p0, p1, g.view, []];
p0 ¬ p1;
ENDLOOP;
ix ¬ ix+1;
ENDLOOP;
iy ¬ 0;
FOR y: REAL ¬ g.yMin.value, y+g.grain.value WHILE y < g.yMax.value DO
p0: Triple ¬ [g.xMin.value, y, g.values[ix ¬ 0][iy]];
FOR x: REAL ¬ g.xMin.value+g.grain.value, x+g.grain.value WHILE x < g.xMax.value DO
p1: Triple ¬ [x, y, g.values[ix ¬ ix+1][iy]];
G3dDraw.Segment[context, p0, p1, g.view, []];
p0 ¬ p1;
ENDLOOP;
iy ¬ iy+1;
ENDLOOP;
IF g.axesOn THEN G3dDraw.Axes[context, g.view, []];
};
GraphProcs
Spike:  GraphProc ~ {v ¬ G3dFunction.Spike[x]};
Gauss:  GraphProc ~ {v ¬ G3dFunction.Gauss[x]};
Poisson:  GraphProc ~ {v ¬ G3dFunction.Poisson[x, g.a.value]};
Power:  GraphProc ~ {v ¬ IF x>0 THEN RealFns.Power[x, g.a.value] ELSE 0};
Sin:   GraphProc ~ {v ¬ RealFns.Power[0.5+0.5*RealFns.Sin[x], g.a.value]};
Ln:   GraphProc ~ {v ¬ RealFns.Ln[x]};
Log:   GraphProc ~ {v ¬ RealFns.Log[g.a.value, x]};
Perlin:  GraphProc ~ {v ¬ G3dFunction.Perlin[x, g.a.value]};
Wyvill:  GraphProc ~ {v ¬ IF x>0 THEN G3dFunction.Wyvill[x/g.a.value] ELSE 0};
XSquared: GraphProc ~ {v ¬ IF x>0 THEN 1-x*x ELSE 0};
SlowInOut: GraphProc ~ {v ¬ IF x>0 THEN G3dSpline.SlowInOut[0.0, 1.0, x] ELSE 0};
Start Code
functions:  LIST OF Function ~ LIST[
["Spike",     "a second order curve",      Spike],
["Gauss",     "the normal distribution curve",   Gauss],
["Poisson",    "the poisson curve, with a the scalar", Poisson],
["Power",     "a power curve, with a the exponent", Power],
["Sin",     "a sin curve raised to the a power",  Sin],
["Ln",      "natural logarithm",       Ln],
["Log",     "logarithm to the base a",     Log],
["Perlin",     "Ken's curve, with a the scalar",   Perlin],
["Wyvill",    "Wyvill's soft function",     Wyvill],
["xSquared",    "simplifiied Wyvill",      XSquared],
["SlowInOut",   "Slow in and out curve",     SlowInOut]];
use: ROPE ¬ "graph <function> [-option]\n\tfunctions are:\n";
FOR l: LIST OF Function ¬ functions, l.rest WHILE l # NIL DO
use ¬ IO.PutFR["%g\t\t%g:\t%g\n", IO.rope[use], IO.rope[l.first.name], IO.rope[l.first.use]];
ENDLOOP;
use ¬ Rope.Concat[use, "\toptions are:
  -scale <REAL> (default = 1)
  -xMin <REAL> (default = 0)
  -xMax <REAL> (default = 1)
  -a  <REAL> (default = 1)"];
G3dTool.Register["Graph", Graph, use];
END.