DIRECTORY Commander, Controls, Controls3d, Draw2d, Draw3d, FileNames, Icons, IO, Real, Rope, Spline3d, TubeDefs, TubeIO, TubeDisplay, TubePick, TubeStructure, Vector3d, ViewerOps; TubeCommandsImpl: CEDAR PROGRAM IMPORTS Commander, Controls, Controls3d, Draw2d, Draw3d, FileNames, Icons, IO, Real, Spline3d, TubeDisplay, TubeIO, TubePick, TubeStructure, Vector3d, ViewerOps ~ BEGIN OPEN TubeDefs; ActionType: TYPE ~ {none, select, camera, spline, shape, button}; ProgramData: TYPE ~ REF ProgramDataRec; ProgramDataRec: TYPE ~ RECORD [ out: IO.STREAM _ NIL, wDir: Rope.ROPE _ NIL, outer, graphics: Controls.Viewer _ NIL, mouse, mousePrev: Mouse _ [0, 0, none, left], entries: LIST OF Controls.Entry _ NIL, cam: Controls3d.Camera, -- camera hold: Controls3d.Hold, -- handle on a point and its tangent twist0: ControlData _ NIL, -- twist 0 twist1: ControlData _ NIL, -- twist 1 r0: ControlData _ NIL, -- radius 0 r1: ControlData _ NIL, -- radius 1 scal: ControlData _ NIL, -- scale eps: ControlData _ NIL, -- spline flatness value cres: ControlData _ NIL, -- circ. resolution lim: ControlData _ NIL, -- vector limit graphicsData: GraphicsData _ NIL, view: Matrix _ NIL, xmats: MatrixSeq _ NIL, tube: Tube _ NIL, -- all the tube splines pick: Pick _ NIL, action: ActionType _ none, details: Details _ NIL, circle: PairSequence _ NIL, noDraw: BOOL _ FALSE ]; TubeCommand: Commander.CommandProc ~ { d: ProgramData _ NEW[ProgramDataRec _ [out: cmd.err]]; Spline3d.DebugStream[cmd.out]; InitProgramData[d]; MakeDetails[d]; InitViewer[d]; }; InitProgramData: PROC [d: ProgramData] ~ { d.wDir _ FileNames.CurrentWorkingDirectory[]; d.pick _ NEW[PickRec]; d.view _ NEW[MatrixRep]; d.tube _ NEW[TubeRec _ [p0: [-0.5,0.,0.], p1: [0.5,0.,0.], v0: [1.,1.,0.], v1: [1.,1.,0.]]]; d.cam _ Controls3d.InitCamera[dz: 0.5, zoom: 3., fov: 0., proc: Controller, data: d]; d.hold _ Controls3d.InitHold[Controller, d]; d.twist0 _ Controls.NewControl["tw0", vert, , -1000., 1000., 0.0, , , , Controller, d]; d.twist1 _ Controls.NewControl["tw1", vert, , -1000., 1000., 0.0, , , , Controller, d]; d.r0 _ Controls.NewControl["r0", vert, , 0.0, 0.5, 0.0, , , , Controller, d]; d.r1 _ Controls.NewControl["r1", vert, , 0.0, 0.5, 0.0, , , , Controller, d]; d.scal _ Controls.NewControl["scal", vert, , 0.0, 4.0, 1.0, , , , Controller, d]; d.eps _ Controls.NewControl["eps", vert, , 0.001, 0.1, 0.03, , , , Controller, d]; d.cres _ Controls.NewControl["cres", vert, , 3.0, 15.0, 6.0, , TRUE, , Controller, d]; d.lim _ Controls.NewControl["lim", vert, , 0.0, 1000.0, 500.0, , TRUE, , Controller, d]; (d.pick.tube _ d.tube).c _ Spline3d.CoeffsFromHermite[[d.tube.p0, d.tube.v0, d.tube.p1, d.tube.v1]]; d.details _ NEW[DetailsRec]; TubePick.PointPick[d.pick]; }; InitViewer: PROC [d: ProgramData] ~ { Controls.ControlRow[d.twist0, 2]; Controls.ControlRow[d.cam.pan, 3]; d.outer _ Controls.OuterViewer[ name: "Tube", column: left, entries: LIST[ [name: "Help", proc: Help, row: 0], [name: "Auto-On", proc: TogAuto, row: 0], [name: "Label-On", proc: TogLabel, row: 0], [name: "Max-Out", proc: MaxPointsPolyOut, row: 0], [name: "Poly-Out", proc: PointsPolyOut, row: 0], [name: "IP-out", proc: IPOut, row: 0], [name: "Skel-Off", proc: TogSkel, row: 1], [name: "Pick-On", proc: TogPick, row: 1], [name: "Splines-On", proc: TogSpline, row: 1], [name: "Circles-Off", proc: TogCircles, row: 2], [name: "Lines-Off", proc: TogLines, row: 2], [name: "Frames-Off", proc: TogFrames, row: 2], [name: "Normals-Off", proc: TogNormals, row: 2], [name: "Curv-Off", proc: TogCurv, row: 2], [name: "Vel-Off", proc: TogVel, row: 2], [name: "Acc-Off", proc: TogAcc, row: 2]], controls: LIST[ d.hold.dx, d.hold.dy, d.hold.dz, d.hold.lng, d.hold.lat, d.hold.mag, d.twist0, d.twist1, d.r0, d.r1, d.scal, d.eps, d.cres, d.lim, d.cam.pan, d.cam.tilt, d.cam.roll, d.cam.zoom, d.cam.dx, d.cam.dy, d.cam.dz, d.cam.fov], typeScript: TRUE, graphicsHeight: 300, graphicsProc: ScreenPick, graphicsShow: Display, data: d, noOpen: TRUE]; d.entries _ NARROW[d.outer.data, Controls.OuterData].entries; d.graphics _ NARROW[d.outer.data, Controls.OuterData].graphics; d.graphicsData _ NARROW[d.graphics.data]; d.outer.icon _ Icons.NewIconFromFile["Tube.icon", 0]; Controls3d.FocusHold[d.pick.tan, d.hold]; ViewerOps.OpenIcon[d.outer]; }; Display: Controls.GraphicsShow ~ { d: ProgramData _ NARROW[data]; Action: PROC ~ { d.view _ Controls3d.InitPix[context, w, h, d.view]; IF d.details.spline THEN TubeDisplay.ShowSplineEnds[d.tube, context, d.view]; TubeDisplay.ShowTube[d.tube, context, d.details, d.view]; IF d.details.pick THEN Draw3d.PV[d.pick.pos, d.pick.tan, , context, d.view, IF d.pick.t IN (0.0..1.0) THEN cross ELSE none]; }; IF whatChanged # NIL AND d.noDraw THEN RETURN; IF TubeDisplay.NVectors[d.tube, d.details] < d.lim.val THEN Draw2d.DoWithBuffer[context, Action, w, h] ELSE Draw2d.DoNoBuffer[context, Action, w, h]; }; Controller: Controls.ControlProc ~ { d: ProgramData _ NARROW[control.data]; MouseAction[d, control.mouse, control]; IF NOT d.noDraw THEN { d.details.on _ NOT d.details.auto OR d.action = shape OR d.mouse.state # held; IF d.action = spline AND d.pick.dividePending THEN { TubePick.DivideSpline[d.pick]; Controls.ControlVal[d.hold.mag, Vector3d.Mag[d.pick.tubePt0.v1]]; }; SELECT control FROM d.scal => MakeDetails[d]; d.r0, d.r1 => ChangeRadii[d]; d.twist0 => ChangeTwist0[d]; d.twist1 => ChangeTwist1[d]; d.cres => TubeStructure.PropagateCircleRes[d.tube, Real.RoundI[d.cres.val]]; d.eps => MakeDetails[d]; d.hold.dx, d.hold.dy, d.hold.dz => ChangePosition[d]; d.hold.lng, d.hold.lat, d.hold.mag => ChangeTangent[d]; d.cam.pan, d.cam.tilt, d.cam.roll, d.cam.zoom, d.cam.dx, d.cam.dy, d.cam.dz, d.cam.fov => Controls3d.SetCamera[d.cam]; ENDCASE => NULL; }; ViewerOps.PaintViewer[control.graphics, client, FALSE, control]; }; MakeDetails: PROC [d: ProgramData] ~ { TubeStructure.PropagateFrames[d.tube, d.scal.val, d.eps.val]; }; ChangePosition: PROC [d: ProgramData] ~ { TubePick.ChangePosition[d.pick, [d.hold.dx.val, d.hold.dy.val, d.hold.dz.val]]; IF d.details.on THEN MakeDetails[d]; }; ChangeTangent: PROC [d: ProgramData] ~ { v: Triple _ Vector3d.CartesianFromPolar[[d.hold.lng.val, d.hold.lat.val, d.hold.mag.val]]; TubePick.ChangeTangent[d.pick, v]; IF d.details.on THEN MakeDetails[d]; }; ChangeRadii: PROC [d: ProgramData] ~ { r, dr: REAL; n: NAT _ TubePick.NumberPicked[d.pick]; IF n = 0 THEN RETURN; r _ d.r0.val; dr _ (d.r1.val-r)/REAL[n]; IF d.pick.tubePick0.prev # NIL THEN d.pick.tubePick0.prev.r1 _ r; FOR s: Tube _ d.pick.tubePick0, s.next WHILE s # NIL AND s # d.pick.tubePick1.next DO s.r0 _ r; r _ r+dr; s.r1 _ r; ENDLOOP; IF d.pick.tubePick1.next # NIL THEN d.pick.tubePick1.next.r0 _ r; TubePick.RemakePicked[d.pick, d.scal.val, d.eps.val]; }; ChangeTwist0: PROC [d: ProgramData] ~ { nBefore: NAT _ TubePick.BeforePicked[d.pick]; change: REAL _ d.twist0.val-d.twist0.preval; IF nBefore > 0 THEN { dchange: REAL _ 0.0; ddchange: REAL _ change/REAL[nBefore]; FOR s: Tube _ d.tube, s.next WHILE s # d.pick.tubePick0 DO s.twist0 _ s.twist0+dchange; dchange _ dchange+ddchange; s.twist1 _ s.twist1+dchange; ENDLOOP; }; FOR s: Tube _ d.pick.tubePick0, s.next WHILE s # NIL DO s.twist0 _ s.twist0+change; s.twist1 _ s.twist1+change; ENDLOOP; IF d.pick.tubePick1 # NIL THEN Controls.ControlVal[d.twist1, d.pick.tubePick1.twist1]; IF d.details.on THEN MakeDetails[d]; }; ChangeTwist1: PROC [d: ProgramData] ~ { nPicked: NAT _ TubePick.NumberPicked[d.pick]; change: REAL _ d.twist1.val-d.twist1.preval; IF nPicked > 0 THEN { dchange: REAL _ 0.0; ddchange: REAL _ change/REAL[nPicked]; FOR s: Tube _ d.pick.tubePick0, s.next WHILE s # d.pick.tubePick1.next DO s.twist0 _ s.twist0+dchange; dchange _ dchange+ddchange; s.twist1 _ s.twist1+dchange; ENDLOOP; }; IF d.pick.tubePick1 # NIL THEN FOR s: Tube _ d.pick.tubePick1.next, s.next WHILE s # NIL DO s.twist0 _ s.twist0+change; s.twist1 _ s.twist1+change; ENDLOOP; IF d.details.on THEN MakeDetails[d]; }; ScreenPick: Controls.GraphicsProc ~ { d: ProgramData _ NARROW[graphics.data]; MouseAction[d, graphics.mouse, graphics]; IF d.mouse.state = up THEN RETURN; TubePick.ScreenPick[d.tube, d.mouse, d.view, d.pick]; IF d.mouse.button = left THEN Controls3d.FocusHold[d.pick.tan, d.hold]; FocusPick[d]; }; FocusPick: PROC [d: ProgramData] ~ { IF d.pick.tubePick0 # NIL THEN { Controls.ControlVal[d.r0, d.pick.tubePick0.r0]; Controls.ControlVal[d.twist0, d.pick.tubePick0.twist0]; }; IF d.pick.tubePick1 # NIL THEN { Controls.ControlVal[d.r1, d.pick.tubePick1.r1]; Controls.ControlVal[d.twist1, d.pick.tubePick1.twist1]; }; }; MouseAction: PROC [d: ProgramData, mouse: Mouse, whatChanged: REF ANY] ~ { wasDown: BOOL _ d.mouse.state = down; d.mousePrev _ d.mouse; d.mouse _ mouse; d.action _ SELECT whatChanged FROM d.entries => button, d.graphicsData => select, d.cam.roll, d.cam.pan, d.cam.tilt, d.cam.zoom, d.cam.fov => camera, d.cam.dx, d.cam.dy, d.cam.dz => camera, d.hold.dx, d.hold.dy, d.hold.dz, d.hold.lng, d.hold.lat, d.hold.mag => spline, d.twist0, d.twist1, d.r0, d.r1, d.scal, d.cres => shape, ENDCASE => none; d.noDraw _ d.mouse.state = up AND wasDown AND d.action # button AND d.details.on; Controls.TypeScriptClear[NARROW[d.outer.data, Controls.OuterData]]; }; Toggle: PROC [clientData: REF ANY, type: DetailType, trueName, falseName: Rope.ROPE] ~ { outer: OuterData _ NARROW[clientData]; d: ProgramData _ NARROW[outer.data]; TubeDisplay.ToggleDetail[d.details, type, trueName, falseName, outer]; MouseAction [d, [0, 0, up, left], d.entries]; MakeDetails[d]; ViewerOps.PaintViewer[d.graphics, client, FALSE, d.entries]; }; TogLabel: Controls.ClickProc ~ {Toggle[clientData, label, "Label-On", "Label-Off"]}; TogAuto: Controls.ClickProc ~ {Toggle[clientData, auto, "Auto-On", "Auto-Off"]}; TogSkel: Controls.ClickProc ~ {Toggle[clientData, skel, "Skel-On", "Skel-Off"]}; TogPick: Controls.ClickProc ~ {Toggle[clientData, pick, "Pick-On", "Pick-Off"]}; TogSpline: Controls.ClickProc ~ {Toggle[clientData, spline, "Splines-On", "Splines-Off"]}; TogCircles: Controls.ClickProc ~ {Toggle[clientData, circles, "Circles-On", "Circles-Off"]}; TogLines: Controls.ClickProc ~ {Toggle[clientData, lines, "Lines-On", "Lines-Off"]}; TogFrames: Controls.ClickProc ~ {Toggle[clientData, frames, "Frames-On", "Frames-Off"]}; TogNormals: Controls.ClickProc ~ {Toggle[clientData, normals, "Normals-On", "Normals-Off"]}; TogCurv: Controls.ClickProc ~ {Toggle[clientData, curv, "Curv-On", "Curv-Off"]}; TogVel: Controls.ClickProc ~ {Toggle[clientData, vel, "Vel-On", "Vel-Off"]}; TogAcc: Controls.ClickProc ~ {Toggle[clientData, acc, "Acc-On", "Acc-Off"]}; IPOut: Controls.ClickProc ~ { outer: Controls.OuterData _ NARROW[clientData]; d: ProgramData _ NARROW[outer.data]; TubeIO.QueryAndPrintTube[d.tube, d.details, d.view, d.wDir, outer]; }; PointsPolyOut: Controls.ClickProc ~ { outer: Controls.OuterData _ NARROW[clientData]; d: ProgramData _ NARROW[outer.data]; TubeIO.QueryAndPointsPolyOut[d.tube, d.wDir, outer]; }; MaxPointsPolyOut: Controls.ClickProc ~ { outer: Controls.OuterData _ NARROW[clientData]; d: ProgramData _ NARROW[outer.data]; TubeIO.QueryAndMaxPointsPolyOut[d.tube, d.wDir, outer]; }; Help: Controls.ClickProc ~ { d: ProgramData _ NARROW[NARROW[clientData, Controls.OuterData].data]; helpMessage: Rope.ROPE _ " Mouse use: any button to manipulate sliders or dials left button to select a point on a spline middle button to select an initial spline right button to select an ending spline General approach: use top row of controls to adjust viewing parameters use middle row to control selected splines use bottom row to control selected point location and tangent\n"; IO.PutF[d.out, helpMessage]; }; Commander.Register["///Commands/Tube", TubeCommand, "\nModel tubular structures."]; END. .. XTubeCommandsImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Bloomenthal, April 29, 1986 4:51:22 pm PDT Proc called as result of any slider or dial manipulation. Proc called as result of mousing down in graphics viewer. adjust controls to selected splines settings: Controls3d.PaintControls[d.lng, d.lat, d.mag]; Κ •˜šœ™Jšœ Οmœ1™žœ˜VJšœ@žœ˜XJšœd˜dJšœ žœ ˜J˜Icode˜K˜—š’ œžœ˜%J˜!J˜"šœ˜Jšœ ˜ Jšœ ˜ šœ žœ˜Jšœ#˜#Jšœ)˜)Jšœ+˜+Jšœ2˜2Jšœ0˜0Jšœ&˜&Jšœ*˜*Jšœ)˜)Jšœ.˜.Jšœ0˜0Jšœ,˜,Jšœ.˜.Jšœ0˜0Jšœ*˜*Jšœ(˜(Jšœ)˜)—šœ žœ˜JšœD˜DJ˜=JšœX˜X—Jšœ žœ˜J˜J˜J˜J˜Jšœžœ˜—Jšœ žœ+˜=Jšœ žœ,˜?Jšœžœ˜)Jšœ5˜5K˜)Jšœ˜J˜J˜—š‘œ˜"Jšœžœ˜š’œžœ˜Jšœ3˜3Kšžœžœ5˜MKšœ9˜9šžœžœžœ+˜KJšžœ žœ žœžœ˜0—Jšœ˜—Jš žœžœžœ žœžœ˜.šžœ4˜6Jšžœ+˜/Jšžœ*˜.—J˜J˜—šΠbn œ˜$J™9Jšœžœ˜&J˜J˜'šžœžœ žœ˜Jšœžœžœžœ˜Nšžœžœžœ˜4Jšœ˜JšœA˜AJ˜—šžœ ž˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜LJšœ˜Jšœ5˜5Jšœ7˜7J˜vJšžœžœ˜—J˜—Jšœ0žœ ˜@J˜J˜—š’ œžœ˜&Jšœ=˜=J˜J˜—š’œžœ˜)JšœO˜OJšžœžœ˜$J˜J˜—š’ œžœ˜(JšœZ˜ZJšœ"˜"Jšžœžœ˜$J˜J˜—š’ œžœ˜&Kšœžœ˜ Kšœžœ!˜'Kšžœžœžœ˜K˜ Kšœžœ˜Kšžœžœžœ˜Aš žœ$žœžœžœž˜UK˜ K˜ K˜ Kšžœ˜—Kšžœžœžœ˜AK˜5K˜K˜—š’ œžœ˜'Kšœ žœ!˜-Kšœžœ ˜,K˜šžœ žœ˜Kšœ žœ˜Kšœ žœ žœ ˜&šžœžœž˜:K˜K˜K˜Kšžœ˜—K˜K˜—šžœ$žœžœž˜7K˜K˜Kšžœ˜—K˜šžœžœžœ8˜VK˜—Kšžœžœ˜$K˜K˜—š’ œžœ˜'Kšœ žœ!˜-Kšœžœ ˜,K˜šžœ žœ˜Kšœ žœ˜Kšœ žœ žœ ˜&šžœ$žœž˜IK˜K˜K˜Kšžœ˜—K˜K˜—š žœžœžœžœ)žœžœž˜[K˜K˜Kšžœ˜K˜—Kšžœžœ˜$K˜K˜—š‘ œ˜%J™9J™Jšœžœ˜'J˜Jšœ)˜)Jšžœžœžœ˜"J˜5Jšžœžœ*˜GJ˜ J˜J˜—š’ œžœ˜$J™-J™šžœžœžœ˜ Jšœ/˜/Jšœ7˜7J˜—šžœžœžœ˜ Jšœ/˜/Jšœ7˜7J˜—J™.J˜J˜—š’ œžœ-žœžœ˜JJšœ žœ˜%Jšœ˜Jšœ˜šœ žœ ž˜"J˜J˜J˜CJ˜'JšœN˜NJ˜8Jšžœ ˜—Jšœžœ žœžœ˜QJšœžœ$˜CJ˜J˜—š ’œžœžœžœ.žœ˜XJšœžœ ˜&Jšœžœ ˜$J˜JšœF˜FJšœ-˜-J˜Jšœ*žœ ˜