DIRECTORY Commander, CommanderOps, Controls, Convert, G2dBasic, G3dBasic, G3dSpline, G3dTool, G3dTube, G3dVector, IO, Menus, Rope; G3dTubeCmdsImpl: CEDAR PROGRAM IMPORTS CommanderOps, Controls, Convert, G3dSpline, G3dTool, G3dTube, G3dVector, IO, Rope ~ BEGIN Control: TYPE ~ Controls.Control; Triple: TYPE ~ G3dBasic.Triple; Tool: TYPE ~ G3dTool.Tool; ROPE: TYPE ~ Rope.ROPE; Tube: TYPE ~ G3dTube.Tube; TubeProc: TYPE ~ G3dTube.TubeProc; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ tool: Tool ฌ NIL, alpha: Control ฌ NIL, tube1, tube2: Tube ฌ NIL, interp: Tube ฌ NIL ]; TubeInterpCmd: Commander.CommandProc ~ { argv: CommanderOps.ArgumentVector ฌ CommanderOps.Parse[cmd]; IF argv.argc # 3 THEN RETURN[$Failure, interpUsage] ELSE { Prepare: PROC [tube: Tube] ~ { tube.epsilon ฌ 1.0; G3dTube.Make[tube]; }; d: Data ฌ NEW[DataRep]; d.tube1 ฌ G3dTube.TubeFromFile[argv[1]]; d.tube2 ฌ G3dTube.TubeFromFile[argv[2]]; IF d.tube1 = NIL OR d.tube2 = NIL THEN RETURN[$Failure, "Can't read tube(s)"] ELSE { Prepare[d.tube1]; Prepare[d.tube2]; d.interp ฌ G3dTube.CopyEntireTube[d.tube1]; G3dTube.SelectAll[d.interp]; d.tool ฌ G3dTool.MakeTool[ name: "TubeInterp", extraControls: LIST[Controls.NewControl["alpha",, d, 0, 1, 0, Alpha,,,,,,, 136]], extraButtons: LIST[Controls.ClickButton["Write Tube", WriteTube, d]], client: [draw: Draw, data: d] ]; }; }; }; Alpha: Controls.ControlProc ~ { d: Data ฌ NARROW[clientData]; IF control.mouse.button # right THEN RETURN; G3dTube.InterpTubes[d.tube1, d.tube2, d.interp, control.value]; G3dTool.Repaint[d.tool]; }; Draw: G3dTool.DrawProc ~ { G3dTube.DrawSkeleton[context, NARROW[clientData, Data].interp, view, vp]; }; WriteTube: Controls.ClickProc ~ { d: Data ฌ NARROW[clientData]; fileName: ROPE ฌ Controls.TypescriptReadFileName[d.tool.typescript]; IF fileName # NIL THEN G3dTube.TubeToFile[d.interp, fileName]; }; TubeOpsCmd: Commander.CommandProc ~ { tube: Tube; argv: CommanderOps.ArgumentVector ฌ CommanderOps.Parse[cmd]; IF argv.argc < 4 THEN RETURN[$Failure, opsUsage]; IF (tube ฌ G3dTube.TubeFromFile[argv[1]]) = NIL THEN RETURN[$Failure, "Can't read tube"] ELSE { n: NAT ฌ 3; WHILE n < argv.argc DO Eq: PROC [r: ROPE] RETURNS [b: BOOL] ~ {b ฌ Rope.Equal[argv[n], r, FALSE]}; GetReal: PROC [n: NAT] RETURNS[r: REAL] ~ {r ฌ Convert.RealFromRope[argv[n]]}; SELECT TRUE FROM Eq["-fixUp"] => { Op: TubeProc ~ {IF tube.prev # NIL THEN tube.p0 ฌ tube.prev.p1}; G3dTube.ApplyToTube[tube, Op]; }; Eq["-normalize"] => { Op: TubeProc ~ { tube.p0 ฌ G3dVector.Mul[G3dVector.Sub[tube.p0, hull.center], scale]; tube.p1 ฌ G3dVector.Mul[G3dVector.Sub[tube.p1, hull.center], scale]; tube.v0 ฌ G3dVector.Mul[tube.v0, scale]; tube.v1 ฌ G3dVector.Mul[tube.v1, scale]; tube.r0 ฌ scale*tube.r0; tube.r1 ฌ scale*tube.r1; }; hull: G3dBasic.Hull ฌ G3dTube.TubeHull[tube]; size: Triple ฌ G3dVector.Sub[hull.pMax, hull.pMin]; scale: REAL ฌ 1.0/MAX[size.x, size.y, size.z]; G3dTube.ApplyToTube[tube, Op]; }; Eq["-scale"] => { Op: TubeProc ~ { tube.p0 ฌ G3dVector.Mul[tube.p0, scale]; tube.p1 ฌ G3dVector.Mul[tube.p1, scale]; }; scale: REAL ฌ GetReal[n+1]; n ฌ n+1; G3dTube.ApplyToTube[tube, Op]; }; Eq["-offset"] => { Op: TubeProc ~ { tube.p0 ฌ G3dVector.Add[tube.p0, offset]; tube.p1 ฌ G3dVector.Add[tube.p1, offset]; }; offset: Triple ฌ [GetReal[n+1], GetReal[n+2], GetReal[n+3]]; n ฌ n+3; G3dTube.ApplyToTube[tube, Op]; }; Eq["-invertZ"] => { Op: TubeProc ~ { tube.p0.z ฌ 1.0-tube.p0.z; tube.p1.z ฌ 1.0-tube.p1.z; }; G3dTube.ApplyToTube[tube, Op]; }; Eq["-interpolate"] => { Interpolate: TubeProc ~ { AddPt: PROC [p: Triple] ~ {pts[pts.length] ฌ p; pts.length ฌ pts.length+1}; temp: Tube ฌ tube; last: Tube ฌ G3dTube.Last[tube]; splines: G3dSpline.SplineSequence; tan0: Triple ฌ IF tube.prev # NIL THEN tube.prev.v1 ELSE G3dVector.Mul[G3dVector.Sub[tube.p1, tube.p0], (1.0/3.0)]; tan1: Triple ฌ G3dVector.Mul[G3dVector.Sub[last.p1, last.p0], (1.0/3.0)]; pts.length ฌ 0; AddPt[tube.p0]; FOR t: Tube ฌ tube, t.next WHILE t # NIL DO AddPt[t.p1]; ENDLOOP; splines ฌ G3dSpline.Interpolate[pts, tan0, tan1]; FOR n: NAT IN [0..splines.length) DO temp.spline ฌ splines[n]; temp.v0 ฌ G3dSpline.Velocity[temp.spline, 0.0]; temp.v1 ฌ G3dSpline.Velocity[temp.spline, 1.0]; temp ฌ temp.next; ENDLOOP; FOR t: Tube ฌ tube, t.next WHILE t # NIL DO G3dTube.ApplyToBranches[t, Interpolate, FALSE]; ENDLOOP; }; pts: G3dBasic.TripleSequence ฌ NEW[G3dBasic.TripleSequenceRep[100]]; [] ฌ Interpolate[tube]; }; ENDCASE => IO.PutF1[cmd.err, "Bad option: %g\n", IO.rope[argv[n]]]; n ฌ n+1; ENDLOOP; G3dTube.TubeToFile[tube, argv[2]]; }; }; opsUsage: ROPE ฌ " 3dTubeOps <-option> Options include: fixUp make tube.p0 = tube.prev.p1 scale scale by factor offset offset by x, y, z invertZ change z values to 1-z normalize scale and translate to +/- 1 in x, y, z interpolate create spline coefficients, v0 and v1"; interpUsage: ROPE ฌ "TubeInterp "; G3dTool.Register["TubeOps", TubeOpsCmd, opsUsage]; G3dTool.Register["TubeInterp", TubeInterpCmd, interpUsage]; END. .. DIRECTORY Commander, CommanderOps, Controls, G3dBasic, G3dTool, G3dMatrix, G3dQuaternion, G3dTimeTrees, G3dTube, G3dVector, Rope; G3dTubeInterpCmdImpl: CEDAR PROGRAM IMPORTS Commander, CommanderOps, Controls, G3dTool, G3dMatrix, G3dQuaternion, G3dTimeTrees, G3dTube, G3dVector ~ BEGIN Control: TYPE ~ Controls.Control; Tool: TYPE ~ G3dTool.Tool; Matrix: TYPE ~ G3dMatrix.Matrix; Triple: TYPE ~ G3dBasic.Triple; Quaternion: TYPE ~ G3dQuaternion.Quaternion; ROPE: TYPE ~ Rope.ROPE; TimeTree: TYPE ~ G3dTimeTrees.TimeTree; Tube: TYPE ~ G3dTube.Tube; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ tool: Tool ฌ NIL, alpha: Control ฌ NIL, tube1, tube2: Tube ฌ NIL, interp: Tube ฌ NIL, newProc: BOOL ฌ FALSE ]; NewTubeInterpCmd: Commander.CommandProc ~ { [result, msg] ฌ MakeTestTool[cmd, TRUE]; }; TubeInterpCmd: Commander.CommandProc ~ { [result, msg] ฌ MakeTestTool[cmd, FALSE]; }; MakeTestTool: PROC [cmd: Commander.Handle, newProc: BOOL] RETURNS [result: REF ฌ NIL, msg: ROPE ฌ NIL] ~ { argv: CommanderOps.ArgumentVector ฌ CommanderOps.Parse[cmd]; IF argv.argc # 3 THEN RETURN [$Failure, interpUsage] ELSE { Prepare: PROC [tube: Tube] ~ { tube.epsilon ฌ 1.0; G3dTube.Make[tube]; }; d: Data ฌ NEW[DataRep]; d.tube1 ฌ G3dTube.TubeFromFile[argv[1]]; d.tube2 ฌ G3dTube.TubeFromFile[argv[2]]; d.newProc ฌ newProc; IF d.tube1 = NIL OR d.tube2 = NIL THEN RETURN[$Failure, "Can't read tube(s)"] ELSE { Prepare[d.tube1]; Prepare[d.tube2]; d.interp ฌ G3dTube.CopyEntireTube[d.tube1]; G3dTube.SelectAll[d.interp]; d.tool ฌ G3dTool.MakeTool[ name: "3dTubeInterp", extraControls: LIST[Controls.NewControl["alpha",, d, 0, 1, 0, Alpha,,,,,,, 136]], extraButtons: LIST[Controls.ClickButton["Write Tube", WriteTube, d]], client: [draw: Draw, data: d] ]; }; }; }; Alpha: Controls.ControlProc ~ { d: Data ฌ NARROW[clientData]; IF control.mouse.button # right THEN RETURN; IF d.newProc THEN NewInterpTubes[d.tube1, d.tube2, d.interp, control.value] ELSE InterpTubes[d.tube1, d.tube2, d.interp, control.value]; G3dTool.Repaint[d.tool]; }; WriteTube: Controls.ClickProc ~ { d: Data ฌ NARROW[clientData]; fileName: ROPE ฌ Controls.TypescriptReadFileName[d.tool.typescript]; IF fileName # NIL THEN G3dTube.TubeToFile[d.interp, fileName]; }; InterpTubes: PROC [tube1, tube2, interp: Tube, alpha: REAL] ~ { GetQuaternion: PROC [t: Tube] RETURNS [Quaternion] ~ { z: Triple ฌ G3dVector.Unit[G3dVector.Sub[t.p1, t.p0]]; x: Triple ฌ G3dVector.Unit[G3dVector.V90[z, t.refVec]]; y: Triple ฌ G3dVector.Unit[G3dVector.Cross[z, x]]; m ฌ G3dMatrix.MakeFromTriad[x, y, z,, FALSE, m]; RETURN[G3dQuaternion.FromMatrix[m]]; }; Set: PROC [t, t1, t2: Tube] ~ { q1: Quaternion ฌ GetQuaternion[t1]; q2: Quaternion ฌ GetQuaternion[t2]; q: Quaternion ฌ G3dQuaternion.Slerp[ IF G3dQuaternion.Dot[q1, q2] < 0.0 THEN G3dQuaternion.Neg[q1] ELSE q1, q2, alpha]; len1: REAL ฌ G3dVector.Distance[t1.p0, t1.p1]; len2: REAL ฌ G3dVector.Distance[t2.p0, t2.p1]; len: REAL ฌ len1+alpha*(len2-len1); temp: Matrix ฌ m ฌ G3dQuaternion.ToMatrix[q, m]; z: Triple ฌ G3dMatrix.TransformVec[[0.0, 0.0, 1.0], m]; IF t.prev # NIL THEN t.p0 ฌ t.prev.p1; t.p1 ฌ G3dVector.Add[t.p0, G3dVector.SetVectorLength[z, len]]; }; DoTube: PROC [t, t1, t2: Tube] ~ { Set[t, t1, t2]; IF t.next # NIL THEN DoTube[t.next, t1.next, t2.next]; IF t.branches # NIL THEN FOR n: NAT IN [0..t.branches.length) DO DoTube[t.branches[n], t1.branches[n], t2.branches[n]]; ENDLOOP; }; m: Matrix ฌ G3dMatrix.ObtainMatrix[]; DoTube[interp, tube1, tube2]; G3dMatrix.ReleaseMatrix[m]; }; TimeTreeFromTubes: PROC [tube1, tube2: Tube] RETURNS [timeTree: TimeTree] ~ { GetMatrix: PROC [t: Tube] RETURNS [Matrix] ~ { z: Triple ฌ G3dVector.Unit[G3dVector.Sub[t.p1, t.p0]]; x: Triple ฌ G3dVector.Unit[G3dVector.V90[z, t.refVec]]; y: Triple ฌ G3dVector.Unit[G3dVector.Cross[z, x]]; RETURN[G3dMatrix.MakeFromTriad[x, y, z]]; }; NodesFromTubes: PROC [tube1, tube2: Tube] ~ { SetNode: PROC [t: Tube, time: REAL] ~ { G3dTimeTrees.InsertKey[timeTree, time, NEW[REAL ฌ G3dVector.Distance[t.p0, t.p1]], "length"]; G3dTimeTrees.InsertTransform[timeTree, time, GetMatrix[t]]; }; SetNode[tube1, 0.0]; SetNode[tube2, 1.0]; G3dTimeTrees.PushTimeTree[timeTree]; IF tube1.next # NIL THEN NodesFromTubes[tube1.next, tube2.next]; G3dTimeTrees.PopTimeTree[timeTree]; IF tube1.next = NIL THEN timeTree.activeNode.children[0] ฌ NIL; -- signify no "next" node IF tube1.branches # NIL THEN FOR n: NAT IN [0..tube1.branches.length) DO G3dTimeTrees.PushTimeTree[timeTree]; NodesFromTubes[tube1.branches[n], tube2.branches[n]]; G3dTimeTrees.PopTimeTree[timeTree]; ENDLOOP; }; timeTree ฌ G3dTimeTrees.CreateTimeTree[]; G3dTimeTrees.RegisterKeyType[timeTree, "length", real]; IF tube1 # NIL AND tube2 # NIL THEN NodesFromTubes[tube1, tube2]; }; InterpFromTimeTree: PROC [interp: Tube, timeTree: TimeTree] ~ { BuildTube: PROC [interp: Tube, node: G3dTimeTrees.Node] ~ { len: REAL ฌ NARROW[G3dTimeTrees.GetStrobedKey[node, "length"], REF REAL]ญ; z: Triple ฌ G3dMatrix.TransformVec[[0.0, 0.0, 1.0], node.globalTransform]; IF interp.prev # NIL THEN interp.p0 ฌ interp.prev.p1; interp.p1 ฌ G3dVector.Add[interp.p0, G3dVector.SetVectorLength[z, len]]; IF node.children = NIL OR node.children.length = 0 THEN RETURN; IF node.children[0] # NIL THEN BuildTube[interp.next, node.children[0]]; FOR i: INT IN [1.. node.children.length) DO BuildTube[interp.branches[i-1], node.children[i]]; ENDLOOP; }; BuildTube[interp, timeTree.root]; }; NewInterpTubes: PROC [tube1, tube2, interp: Tube, alpha: REAL] ~ { timeTree: TimeTree ฌ TimeTreeFromTubes[tube1, tube2]; G3dTimeTrees.StrobeTimeTree[timeTree, alpha]; InterpFromTimeTree[interp, timeTree]; }; interpUsage: ROPE ฌ "TubeInterp "; G3dTool.Register["TubeInterp", TubeInterpCmd, interpUsage]; G3dTool.Register["NewTubeInterp", NewTubeInterpCmd, interpUsage]; END. ˜ G3dTubeCmdsImpl.mesa Copyright ำ 1985, 1992 by Xerox Corporation. All rights reserved. Bloomenthal, October 20, 1992 5:17 pm PDT Types Interpolate Between Two Topologically Identical Tubes Tube Operations Start Code G3dTubeInterpCmdImpl.mesa Copyright ำ 1985, 1992 by Xerox Corporation. All rights reservet. Bloomenthal, July 22, 1992 11:21 pm PDT Glassner, July 3, 1990 1:29:57 pm PDT Types Interpolate Between Two Topologically Identical Tubes -- This presumes tube1 and tube2 have identical topology! Using G3dTimeTrees -- tube.next is node.children[0], other children are branches -- This presumes tube1 and tube2 have identical topology! Start Code ส ฑ•NewlineDelimiter –"cedarcode" style™™Jšœ ฯeœ6™BJ™)J˜Jšฯk œy˜‚J˜—šะblœžœž˜JšžœR˜YJ˜—Jšœž˜head™Jšœ žœ˜$Jšœ žœ˜"Jšœžœ˜šžœžœžœ˜J˜—Jšœ žœ˜Jšœ žœ˜$—šœฯzœ™5Jšœžœžœ ˜šœžœžœ˜Jšœžœ˜Jšœžœ˜Jšœžœ˜Jšœž˜J˜J˜—šฯn œ˜(J˜<šžœ˜Jšžœžœ˜"šžœ˜šกœžœ˜J˜J˜J˜—Jšœ žœ ˜J˜(J˜(šžœ žœžœ ž˜!Jšžœžœ ˜+šžœ˜J˜J˜J˜+J˜˜J˜Jšœžœ>˜QJšœžœ3˜EJ˜J˜—J˜——J˜——J˜J˜—šกœ˜Jšœ žœ ˜Jšžœžœžœ˜,Jšœ?˜?Jšœ˜J˜J˜—šกœ˜Jšœžœ%˜IJ˜J˜—šก œ˜!Jšœ žœ ˜Jšœ žœ6˜DJšžœ žœžœ(˜>J˜——™šก œ˜%J˜ J˜˜QJšœžœ3˜EJ˜J˜—J˜——J˜——J˜J˜—šกœ˜Jšœ žœ ˜Jšžœžœžœ˜,šžœ ˜ Jšžœ:˜>Jšžœ8˜<—J˜J˜J˜—šก œ˜!Jšœ žœ ˜Jšœ žœ6˜DJšžœ žœžœ(˜>J˜J˜—šก œžœ%žœ˜?J™9šก œžœ žœ˜6J˜6J˜7J˜2Jšœ&žœ˜0Jšžœ˜$J˜—šกœžœ˜J˜#J˜#˜$Jšžœ!žœžœ˜FJšœ˜Jšœ˜—Jšœžœ$˜.Jšœžœ$˜.Jšœžœ˜#J˜0J˜7Jšžœ žœžœ˜&J˜>J˜—šกœžœ˜"J˜Jšžœ žœžœฃœ˜6šžœžœž˜šžœžœžœž˜'Jšฃœ0˜6Jšžœ˜——J˜—J˜&J˜J˜J˜——™šกœžœžœ˜Mšก œžœ žœ ˜.J˜6Jšœ%žœ˜7J˜2Jšžœ#˜)J˜—šกœžœ˜-šกœžœžœ˜'Jšœ'žœžœ.˜]Jšœ;˜;—J˜J˜J˜J˜$Jšžœžœžœ(˜@Jšœ#˜#Jš žœžœžœ#žœฯc˜Yšžœžœžœ˜šžœžœžœž˜+J˜$Jšœ5˜5Jšœ#˜#Jšžœ˜——J˜—J˜)J˜7Jš žœ žœžœ žœžœ˜AJ˜J˜—šกœžœ'˜?Jšœ=™=šก œžœ,˜;Jš œžœžœ-žœžœ˜JJ˜JJšžœžœžœ˜5J˜HJš žœžœžœžœžœ˜?Jšžœžœžœ*˜Hšžœžœžœž˜+J˜2Jšžœ˜—J˜—J˜!J˜J˜—šกœžœ%žœ˜BJ™9J˜5J˜-J˜%J˜——™ –x[key: ROPE, proc: Commander.CommandProc, doc: ROPE _ NIL, clientData: REF ANY _ NIL, interpreted: BOOL _ TRUE]šœ žœ$˜5J˜—J˜;J˜AJ˜—Jšžœ˜J˜J˜—…—*ธ: