TubeTestsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, February 24, 1987 6:14:48 pm PST
DIRECTORY Args, Commander, Controls, Controls3d, Draw2d, Draw3d, FS, IO, Matrix3d, Misc3d, Plane3d, Real, Rope, Spline3d, TubeDefs, TubeDisplay, TubeIO, TubeContour, TubeGeometry, TubeMisc, TubePick, Vector3d, ViewerOps;
TubeTestsImpl: CEDAR PROGRAM
IMPORTS Args, Commander, Controls, Controls3d, Draw2d, Draw3d, FS, IO, Matrix3d, Misc3d, Plane3d, Real, Rope, Spline3d, TubeDisplay, TubeIO, TubeContour, TubeGeometry, TubeMisc, TubePick, Vector3d, ViewerOps
~ BEGIN
OPEN TubeDefs;
UserData:   TYPE ~ RECORD [o: OuterData, p: ProgramData];
ProgramData:  TYPE ~ REF ProgramDataRep;
ProgramDataRep: TYPE ~ RECORD [
Controls:
cam:      Camera ← NIL,    -- camera controls
space:      Control ← NIL,    -- space between objects
spin:      Control ← NIL,    -- rotate about object's vertical axis
tilt:      Control ← NIL,    -- rotate about object's horizontal axis
size:      Control ← NIL,    -- size of object
diameter:     Control ← NIL,    -- diameter of object
circleRes:     Control ← NIL,    -- circle resolution
epsilon:     Control ← NIL,    -- spline flatness threshold
Viewing:
outer:      Viewer ← NIL,
graphics:     Viewer ← NIL,
view:      Matrix ← NIL,
scratchMatrix:   Matrix ← NIL,
The tube:
tube:      Tube ← NIL, 
tube1:      Tube ← NIL,
tube2:      Tube ← NIL,
web:      Coeffs ← NIL,
State:
details:     Details
];
TubeWeb: Commander.CommandProc ~ {
p: ProgramData ← NEW[ProgramDataRep];
p.cam ← Controls3d.InitCamera[data: p, proc: CameraControl];
p.outer ← Controls.OuterViewer[
name: "Tube Web",
controls: LIST[
p.cam.xGlobal, p.cam.yGlobal, p.cam.zGlobal, p.cam.scale, p.cam.hScreen, p.cam.vScreen],
graphicsHeight: 300,
graphicsShow: TubeWebShow,
buttons: LIST[["Get Tube", GetTube]],
data: p];
p.graphics ← NARROW[p.outer.data, OuterData].graphics;
};
CameraControl: Controls3d.CameraProc ~ {
p: ProgramData ~ NARROW[data];
ViewerOps.PaintViewer[p.graphics, client, FALSE, NIL];
};
TubeWebShow: Controls.GraphicsShow ~ {
p: ProgramData ← NARROW[data];
Action: PROC ~ {
p.view ← Controls3d.InitContext[context, p.cam, p.view];
TubeDisplay.DrawSplines[p.tube, context, p.view];
Draw3d.Curve[context, p.web, p.view];
Draw3d.Segment[context, p.tube1.p1, p.tube2.p1, p.view, dotted];
IF p.tube1 # NIL AND p.tube2 # NIL THEN
FOR t: REAL ← 0.0, t+0.05 WHILE t <= 1.01 DO
plane: Plane3d.Quad ~ Plane3d.FromPtNrm[
Spline3d.Position[p.web, t],
Spline3d.Velocity[p.web, t]];
i1: Misc3d.PlaneIntersection ← Misc3d.IntersectSplineWithPlane[p.tube1.coeffs, plane];
i2: Misc3d.PlaneIntersection ← Misc3d.IntersectSplineWithPlane[p.tube2.coeffs, plane];
IF i1.nRoots = 1 AND i2.nRoots = 1 THEN {
p1: Triple ~ Spline3d.Position[p.tube1.coeffs, i1.roots[0]];
p2: Triple ~ Spline3d.Position[p.tube2.coeffs, i2.roots[0]];
Draw3d.Segment[context, p1, p2, p.view]
};
ENDLOOP;
};
IF p.tube # NIL AND p.tube1 # NIL AND p.tube2 # NIL AND p.web # NIL
THEN Draw2d.DoWithBuffer[context, Action];
};
GetTube: ClickProc ~ {
p: ProgramData ~ NARROW[NARROW[clientData, OuterData].data];
p.tube ← TubeMisc.Copy[TubePick.LastTubePicked[]];
IF p.tube # NIL AND p.tube.branches # NIL AND p.tube.branches.length > 0 THEN {
mid, ave, cross, tan: Triple;
p.tube1 ← p.tube.next;
p.tube2 ← p.tube.branches[0];
mid ← Vector3d.Mul[Vector3d.Add[p.tube1.p1, p.tube2.p1], 0.5];
ave ← Vector3d.Normalize[Vector3d.Add[p.tube1.v1, p.tube2.v1]];
cross ← Vector3d.Normalize[Vector3d.Sub[p.tube2.p1, mid]];
tan ← Vector3d.V90[cross, ave];
p.web ← Spline3d.CoeffsFromHermite[[p.tube1.p0, mid, p.tube1.v0, tan]];
};
ViewerOps.PaintViewer[p.graphics, client, FALSE, NIL];
};
TubeCompare: Commander.CommandProc ~ {
arg: ROPE ← Args.GetRope[cmd];
p: ProgramData ← NEW[ProgramDataRep];
p.details ← NEW[DetailsRep];
p.cam    ← Controls3d.InitCamera[data: p];
p.space  ← Controls.NewControl["space", vSlider, p, 0.0, 2.5, 1.0, TubeControl];
p.spin   ← Controls.NewControl["spin", dial,  p, 0.0, 360.0, 0.0, TubeControl];
p.tilt   ← Controls.NewControl["tilt", dial,  p, 0.0, 360.0, 0.0, TubeControl];
p.size    ← Controls.NewControl["size", vSlider, p, 0.0, 4.0, 1.75, TubeControl];
p.diameter  ← Controls.NewControl["dia", vSlider, p, 0.001, 2.5, 1.2, TubeControl];
p.circleRes  ← Controls.NewControl["cres", vSlider, p, 3.0, 20.0, 6.0, TubeControl,, TRUE];
p.epsilon   ← Controls.NewControl["eps", vSlider, p, 0.01, 0.1, 0.03, TubeControl];
Controls.ControlRow[p.spin, 1];
IF arg # NIL THEN {
stream: STREAMFS.StreamOpen[arg ! FS.Error => GOTO noOpen];
NewTubes[p, TubeIO.ReadTube[stream]];
IO.Close[stream];
EXITS noOpen => RETURN[$Error, Rope.Concat["Couldn't open ", arg]];
};
p.scratchMatrix ← NEW[MatrixRep];
p.outer ← Controls.OuterViewer[
name: "Tube Compare",
controls: LIST[
p.cam.yGlobal, p.cam.zGlobal, p.cam.scale, p.cam.x, p.cam.y, p.cam.z, p.cam.fieldOfView,
p.space, p.spin, p.tilt, p.size, p.diameter, p.circleRes, p.epsilon],
graphicsHeight: 300,
graphicsShow: TubesShow,
buttons: LIST[
["Tube-in", TubeIn],
["Label-On", TogLabel],
["Skel-Off", TogSkel],
["Splines-On", TogSpline],
["Circles-Off", TogContours],
["Lines-Off", TogLines],
["Frames-Off", TogFrames],
["Normals-Off", TogNormals]],
typeScriptHeight: 18,
data: p];
};
TubesShow: Controls.GraphicsShow ~ {
p: ProgramData ← NARROW[data];
OffsetTubeDisplay: PROC [tube: Tube, dx: REAL] ~ {
m: Matrix ← p.scratchMatrix;
IF tube = NIL THEN RETURN;
m ← Matrix3d.LocalTranslate[p.cam.matrix, [dx, 0.0, 0.0], m];
m ← Matrix3d.LocalScale[m, p.size.value];
m ← Matrix3d.LocalRotate[m, yAxis, p.spin.value, , , m];
m ← Matrix3d.LocalRotate[m, zAxis, p.tilt.value, , , m];
m ← Controls3d.TransformByViewPort[m, context, m];
TubeDisplay.DrawTube[tube, context, p.details, m]
};
Action: PROC ~ {
Draw2d.Clear[context];
OffsetTubeDisplay[p.tube1, -p.space.value];
OffsetTubeDisplay[p.tube1, p.space.value];
};
Draw2d.DoWithBuffer[context, Action];
};
TubeControl: Controls.ControlProc ~ {
p: ProgramData ← NARROW[control.data];
IF control.mouse.state = up THEN RETURN;
SELECT control FROM
p.epsilon => NewTubes[p, p.tube1];
p.diameter => {
TubeGeometry.ReScale[p.tube1, p.diameter.value];
TubeGeometry.ReScale[p.tube2, p.diameter.value];
};
p.circleRes => {
TubeContour.PropagateCircleRes[p.tube1, Real.RoundI[p.circleRes.value]];
TubeContour.PropagateCircleRes[p.tube2, Real.RoundI[p.circleRes.value]];
};
ENDCASE => NULL;
ViewerOps.PaintViewer[control.graphics, client, FALSE, control];
};
MakeFramesRelative: PROC [tube: Tube] ~ {
vv: Triple ← Spline3d.Velocity[tube.coeffs, 0.0];
refVec: Triple ← Spline3d.RefVec[tube.coeffs, 0.0];
ApplyFramesRelative: TubeProc ~ {
FOR i: NAT IN [0..TubeMisc.NFrames[tube]) DO
f: Frame ← tube.frames[i];
p: Triple ← [f.matrix[3][0], f.matrix[3][1], f.matrix[3][2]]; -- ~ Spline3d.Position
v: Triple ← [f.matrix[2][0], f.matrix[2][1], f.matrix[2][2]]; -- ~ Spline3d.Velocity
s: REAL ← Vector3d.Length[v];
f.triad ← TubeGeometry.Basis[v, vv, refVec];
f.matrix ← TubeGeometry.RefMatrix[p, f.triad, s, 0.0, f.matrix];
ENDLOOP;
};
TubeMisc.ApplyToTube[tube, ApplyFramesRelative];
};
NewTubes: PROC [p: ProgramData, tube: Tube] ~ {
IF tube = NIL THEN RETURN;
TubeGeometry.Make[p.tube1 ← tube, p.diameter.value, p.epsilon.value];
MakeFramesRelative[p.tube2 ← TubeMisc.Copy[p.tube1]];
};
TubeIn: Controls.ClickProc ~ {
u: UserData ← UserDataFromClientData[clientData];
NewTubes[u.p, TubeIO.QueryAndReadTube[u.o]];
ViewerOps.PaintViewer[u.o.graphics, client, FALSE, u.o.buttons];
};
Toggle: PROC [clientData: REF ANY, type: DetailType, trueName, falseName: Rope.ROPE] ~ {
u: UserData ← UserDataFromClientData[clientData];
TubeMisc.ToggleDetail[u.p.details, type, trueName, falseName, u.o];
ViewerOps.PaintViewer[u.o.graphics, client, FALSE, u.o.buttons];
};
TogLabel:  ClickProc ~ {Toggle[clientData, label, "Label-On", "Label-Off"]};
TogSkel:   ClickProc ~ {Toggle[clientData, skeleton, "Skel-On", "Skel-Off"]};
TogSpline:   ClickProc ~ {Toggle[clientData, spline, "Splines-On", "Splines-Off"]};
TogContours: ClickProc ~ {Toggle[clientData, contours, "Contours-On", "Contours-Off"]};
TogLines:   ClickProc ~ {Toggle[clientData, lines, "Lines-On", "Lines-Off"]};
TogFrames:   ClickProc ~ {Toggle[clientData, frames, "Frames-On", "Frames-Off"]};
TogNormals:  ClickProc ~ {Toggle[clientData, normals, "Normals-On", "Normals-Off"]};
UserDataFromClientData: PROC [clientData: REF ANY] RETURNS [u: UserData] ~ {
u.p ← NARROW[(u.o ← NARROW[clientData]).data];
};
Commander.Register["///Commands/TubeCompare", TubeCompare, "\nTest TubeGeometry"];
Commander.Register["///Commands/TubeWeb", TubeWeb, "\nTest connecting two tubes."];
END.