DIRECTORY G3dDraw, G3dRayTrace, Commander, Controls, Convert, Draw2d, FileNames, G3dBasic, G3dMatrix, G3dSpline, G3dTool, G3dTube, G3dVector, Imager, ImagerColor, ImplicitDefs, ImplicitDesign, ImplicitSurface, ImplicitTube, ImplicitValue, IO, Menus, MessageWindow, RealFns, Rope, ViewerOps, ViewerTools; ImplicitDesignCmdsAImpl: CEDAR PROGRAM IMPORTS G3dDraw, Controls, Convert, FileNames, G3dSpline, G3dTool, G3dTube, G3dVector, ImplicitDesign, ImplicitSurface, ImplicitTube, ImplicitValue, IO, MessageWindow, RealFns, Rope, ViewerOps, ViewerTools ~ BEGIN CommandProc: TYPE ~ Commander.CommandProc; ButtonList: TYPE ~ Controls.ButtonList; Control: TYPE ~ Controls.Control; ControlProc: TYPE ~ Controls.ControlProc; OuterData: TYPE ~ Controls.OuterData; DrawProc: TYPE ~ Draw2d.DrawProc; Pair: TYPE ~ G3dBasic.Pair; Triple: TYPE ~ G3dBasic.Triple; TripleSequence: TYPE ~ G3dBasic.TripleSequence; TripleSequenceRep: TYPE ~ G3dBasic.TripleSequenceRep; Quad: TYPE ~ G3dBasic.Quad; RayProc: TYPE ~ G3dRayTrace.RayProc; NearSpline: TYPE ~ G3dSpline.NearSpline; Tube: TYPE ~ G3dTube.Tube; NearSegment: TYPE ~ G3dVector.NearSegment; CubeOkProc: TYPE ~ ImplicitDefs.CubeOkProc; StartProc: TYPE ~ ImplicitDefs.StartProc; TextureProc: TYPE ~ ImplicitDefs.TextureProc; ValueProc: TYPE ~ ImplicitDefs.ValueProc; VertexOkProc: TYPE ~ ImplicitDefs.VertexOkProc; DocProc: TYPE ~ ImplicitDesign.DocProc; Tool: TYPE ~ ImplicitDesign.Tool; ClickProc: TYPE ~ Menus.ClickProc; ROPE: TYPE ~ Rope.ROPE; TubeData: TYPE ~ REF TubeDataRep; TubeDataRep: TYPE ~ RECORD [ spheres: TripleSequence ¬ NIL, nSpheresButton: Controls.Button ¬ NIL, tool: Tool ¬ NIL, lines: BOOL ¬ FALSE, tube: Tube ¬ NIL ]; TubeCommand: CommandProc ~ { d: TubeData ¬ NEW[TubeDataRep]; d.tool ¬ ImplicitDesign.MakeTool[ name: "Tube", startProc: TubeStart, valueProc: TubeValue, client: [draw: TubeDraw, data: d], extraButtons: LIST[ d.nSpheresButton ¬ Controls.TextButton["NSpheres: ", "00", TubeNSpheres, d], Controls.ClickButton["Lines: Off", ToggleLines, d], Controls.ClickButton["Get Tube", TubeGet, d], Controls.ClickButton["Read Tube", TubeRead, d]], toolSettings: [threshold: 0.5, measureMode: $Segment]]; }; ToggleLines: ClickProc ~ { d: TubeData ¬ NARROW[clientData]; Controls.ButtonToggle[ d.tool.renderTool.outerData, d.lines ¬ NOT d.lines, "Lines: On", "Lines: Off"]; }; TubeNSpheres: ClickProc ~ { d: TubeData ¬ NARROW[clientData]; nSpheres: CARD ¬ Convert.IntFromRope[ViewerTools.GetContents[d.nSpheresButton.textViewer]]; IF d.tube = NIL THEN RETURN; IF d.spheres = NIL OR nSpheres > d.spheres.maxLength THEN { d.spheres ¬ NEW[TripleSequenceRep[nSpheres]]; }; d.spheres.length ¬ nSpheres; FOR n: NAT IN [0..d.spheres.length) DO d.spheres[n] ¬ G3dSpline.Position[d.tube.spline, REAL[n]/REAL[d.spheres.length-1]]; ENDLOOP; }; TubeValue: ValueProc ~ { d: TubeData ¬ NARROW[clientData]; t: Tool ¬ d.tool; SELECT TRUE FROM d.tube = NIL => ImplicitDesign.StopTool[d.tool, "First get a tube."]; d.spheres # NIL AND d.spheres.length # 0 => { nSphere: NAT; max: REAL ¬ 100000.0; FOR n: NAT IN [0..d.spheres.length) DO dist: REAL ¬ G3dVector.SquareDistance[point, d.spheres[n]]; IF dist < max THEN {nSphere ¬ n; max ¬ dist}; ENDLOOP; value ¬ IF t.distanceMode = inverse THEN d.tube.r0/MAX[0.0001, RealFns.SqRt[max]] ELSE d.tube.r0*d.tube.r0/MAX[0.0001, max]; } ENDCASE => value ¬ ImplicitTube.SampleTube[ point, d.tube, t.measureMode, t.distanceMode, t.tolerance, t.spread].value; }; TubeTexture: TextureProc ~ { d: TubeData ¬ NARROW[clientData]; IF d.tube = NIL THEN ImplicitDesign.StopTool[d.tool, "First get a tube."] ELSE RETURN[ImplicitTube.TextureOfTube[vertex.point, d.tube]]; }; TubeStart: StartProc ~ { d: TubeData ¬ NARROW[clientData]; IF nFrames > 1 THEN { -- we do some self-styled animation: t: REAL ¬ REAL[frame]/REAL[nFrames]; angle: REAL ¬ 90.0-180.0*t; p1: Triple ¬ [RealFns.CosDeg[angle], RealFns.SinDeg[angle], 0.0]; d.tube ¬ NEW[G3dTube.TubeRep ¬ [p0:[0,-1,0], p1:[0,0,0], v0:[0,0.5,0], v1:[0,0.5,0]]]; d.tube.next ¬ NEW[G3dTube.TubeRep ¬ [p0:[0,0,0], p1:[0,1,0], v0:[0,0.5,0], v1:[0,0.5,0]]]; d.tube.branches ¬ NEW[G3dTube.TubeSequenceRep[1]]; d.tube.branches.length ¬ 1; d.tube.branches[0] ¬ NEW[G3dTube.TubeRep ¬ [p0:[0,0,0], p1:p1, v0:[0,1,0], v1:p1]]; G3dTube.SetSpline[d.tube]; G3dTube.SelectAll[d.tube]; G3dTube.SetRadii[d.tube, 0.1]; ImplicitTube.PrepareTube[d.tube, inverse, d.tool.measureMode]; } ELSE IF d.tube = NIL THEN {ImplicitDesign.StopTool[d.tool, "First get a tube."]; RETURN}; point ¬ IF d.spheres # NIL AND d.spheres.length # 0 AND G3dTube.NBranches[d.tube] = 0 THEN G3dVector.ScaleRay[[d.tube.p0,G3dVector.Unit[G3dVector.Ortho[d.tube.v0]]],d.tube.r0] ELSE ImplicitTube.StartPoint[d.tube, TubeValue, d.tool.threshold, d.tool.measureMode, .75, d]; }; TubeDraw: DrawProc ~ { d: TubeData ¬ NARROW[clientData]; view: G3dTool.View ¬ G3dTool.GetView[viewer]; G3dTube.DrawSplines[context, d.tube, view.camera.matrix, view.viewport]; IF d.lines THEN G3dTube.DrawLines[context, d.tube, view.camera.matrix, view.viewport]; }; TubeGet: ClickProc ~ {GetTube[NARROW[clientData]]}; TubeRead: ClickProc ~ { d: TubeData ¬ NARROW[clientData]; tube: Tube ¬ ReadTube[d.tool]; IF tube # NIL THEN NewTube[d, tube]; }; GetTube: PROC [d: TubeData] ~ { tube: Tube ¬ G3dTube.CopyEntireTube[G3dTube.First[G3dTube.LastTubePicked[]]]; IF tube = NIL THEN Blink["No selected tube -- try ReadTube"] ELSE NewTube[d, tube]; }; ReadTube: PROC [tool: Tool] RETURNS [tube: Tube] ~ { r: ROPE ¬ FileNames.ResolveRelativePath[Controls.TypescriptReadFileName[tool.typescript]]; tube ¬ G3dTube.TubeFromFile[r]; IF tube = NIL THEN Blink[IO.PutFR["Can't open %g\n", IO.rope[r]]]; }; NewTube: PROC [d: TubeData, tube: Tube] ~ { G3dTube.SelectAll[d.tube ¬ tube]; IF G3dTube.NBranches[d.tube] = 0 THEN d.tool.measureMode ¬ $Sum; ImplicitTube.PrepareTube[tube, d.tool.distanceMode, d.tool.measureMode]; ImplicitDesign.Reset[d.tool]; }; CurveData: TYPE ~ REF CurveDataRep; CurveDataRep: TYPE ~ RECORD [ tool: Tool ¬ NIL, tube: Tube ¬ NIL, mode: {points, spline, kspline} ¬ points, npoints: NAT ¬ 260, points: TripleSequence ¬ NIL ]; CurveCommand: CommandProc ~ { d: CurveData ¬ NEW[CurveDataRep]; d.tool ¬ ImplicitDesign.MakeTool[ name: "Curve", startProc: CurveStart, valueProc: CurveValue, client: [draw: CurveDraw, data: d], extraButtons: LIST[ Controls.ClickButton["NPoints", CurveNPoints, d], Controls.ClickButton["Points", CurveMode, d], Controls.ClickButton["Read Tube", CurveRead, d]], toolSettings: [threshold: 0.0] ]; }; CurveMode: ClickProc ~ { d: CurveData ¬ NARROW[clientData]; outerData: OuterData ¬ d.tool.renderTool.outerData; SELECT d.mode FROM points => {Controls.ButtonRelabel[outerData, "Points", "Spline"]; d.mode ¬ spline}; spline => {Controls.ButtonRelabel[outerData, "Spline", "KSpline"]; d.mode ¬ kspline}; kspline => {Controls.ButtonRelabel[outerData, "KSpline", "Points"]; d.mode ¬ points}; ENDCASE; }; CurveValue: ValueProc ~ { d: CurveData ¬ NARROW[clientData]; SELECT d.mode FROM points => { index: NAT; min: REAL ¬ 100000.0; FOR n: NAT IN [0..d.npoints) DO dist: REAL ¬ G3dVector.SquareDistance[d.points[n], point]; IF dist < min THEN {min ¬ dist; index ¬ n}; ENDLOOP; RETURN[0.05-RealFns.SqRt[min]]; }; spline => { near3d: NearSpline ¬ G3dSpline.PreciseNearestPoint[point, d.tube.spline]; RETURN[0.05-near3d.distance]; }; kspline => { near3d: NearSpline ¬ G3dSpline.PreciseNearestPoint[point, d.tube.spline]; rad: REAL ¬ G3dTube.Radius[d.tube, near3d.t]; k: REAL ¬ G3dSpline.CurvatureMag[d.tube.spline, near3d.t]; v: REAL ¬ ImplicitValue.OfPoint[point, near3d.point, rad, d.tool.distanceMode].value; f: REAL ¬ 1.0+RealFns.Log[10, MAX[0.1, k]]; RETURN[v+0.2*f-1.0]; }; ENDCASE; }; CurveStart: StartProc ~ { d: CurveData ¬ NARROW[clientData]; t: Tool ¬ d.tool; IF d.tube = NIL THEN ImplicitDesign.StopTool[d.tool, "First get a tube."]; SELECT d.mode FROM points, spline => { out: Triple ¬ G3dVector.ScaleRay[[d.tube.p0, G3dVector.Unit[G3dVector.Ortho[d.tube.v0]]], 0.1]; RETURN[ImplicitSurface.SurfacePoint[d.tube.p0, out, CurveValue, t.threshold, d]]; }; ENDCASE => RETURN[ ImplicitTube.StartPoint[d.tube, CurveValue, t.threshold, t.measureMode, t.spread, d]]; }; CurveDraw: DrawProc ~ { d: CurveData ¬ NARROW[clientData]; view: G3dTool.View ¬ G3dTool.GetView[viewer]; G3dTube.DrawSplines[context, d.tube, view.camera.matrix, view.viewport]; }; CurvePoints: PROC [d: CurveData] ~ { IF d.points = NIL OR d.points.length < d.npoints THEN d.points ¬ NEW[TripleSequenceRep[d.npoints]]; FOR n: NAT IN [0..d.npoints) DO d.points[n] ¬ G3dSpline.Position[d.tube.spline, REAL[n]/REAL[d.npoints-1]]; ENDLOOP; }; CurveNPoints: ClickProc ~ { d: CurveData ¬ NARROW[clientData]; d.npoints ¬ Controls.GetNat[d.tool.typescript, "NPoints", d.npoints]; CurvePoints[d]; }; CurveRead: ClickProc ~ { d: CurveData ¬ NARROW[clientData]; IF (d.tube ¬ ReadTube[d.tool]) # NIL THEN CurvePoints[d]; }; ConeData: TYPE ~ REF ConeDataRep; ConeDataRep: TYPE ~ RECORD [tool: Tool, w, h, x, tip, lim, ratio, rad, rad2, vok: REAL]; ConeCommand: CommandProc ~ { d: ConeData ¬ NEW[ConeDataRep]; ConeSet[d, 1.0, 0.75]; d.tool ¬ ImplicitDesign.MakeTool[ name: "Cone", startProc: ConeStart, valueProc: ConeValue, vertexOkProc: ConeVertexOk, client: [draw: ConeDraw, data: d], extraButtons: LIST[ Controls.TextButton["Width: ", "1.00", ConeButton, d], Controls.TextButton["Height: ", "0.75", ConeButton, d]], toolSettings: [threshold: 0.0]]; }; ConeButton: ClickProc ~ { E: PROC [rope: ROPE] RETURNS [BOOL] ~ {RETURN[Rope.Equal[button.name, rope, FALSE]]}; N: PROC [o: REAL] RETURNS [r: REAL] ~ { rope: ROPE ¬ ViewerTools.GetContents[button.textViewer]; r ¬ Convert.RealFromRope[rope ! Convert.Error => {Blink["Bad value"]; r ¬ o; CONTINUE}]; }; d: ConeData ¬ NARROW[clientData]; button: Controls.Button ¬ NARROW[ViewerOps.FetchProp[parent, $ButtonText]]; SELECT TRUE FROM E["Width: "] => d.w ¬ ABS[N[d.w]]; E["Height: "] => d.h ¬ ABS[N[d.h]]; ENDCASE => RETURN; ConeSet[d, d.w, d.h]; ImplicitDesign.Repaint[d.tool]; }; ConeSet: PROC [d: ConeData, w, h: REAL] ~ { d.ratio ¬ IF (d.w ¬ ABS[w]) # 0.0 THEN (d.h ¬ ABS[h])/d.w ELSE (d.h ¬ ABS[h]); d.rad ¬ d.h/8.0; d.rad2 ¬ d.rad*d.rad; d.vok ¬ -d.w-0.001; d.x ¬ -d.rad/d.ratio; d.tip ¬ 0.5*d.w; d.lim ¬ d.tip+d.rad; }; ConeVertexOk: VertexOkProc ~ { d: ConeData ¬ NARROW[clientData]; RETURN[point.x > d.vok]; }; ConeValue: ValueProc ~ { d: ConeData ¬ NARROW[clientData]; SELECT point.x FROM < -d.w, > d.lim => RETURN[-1.0]; < d.x => { r: REAL ¬ point.x*d.ratio; RETURN[r*r-(point.y*point.y+point.z*point.z)]; }; < d.tip => RETURN[d.rad2-(point.y*point.y+point.z*point.z)]; ENDCASE => { dx: REAL ¬ point.x-d.tip; RETURN[d.rad2-(dx*dx+point.y*point.y+point.z*point.z)]; }; }; ConeStart: StartProc ~ { d: ConeData ¬ NARROW[clientData]; RETURN[[-d.w, d.h, 0.0]]; }; ConeDraw: DrawProc ~ { d: ConeData ¬ NARROW[clientData]; view: G3dMatrix.Matrix ¬ G3dTool.GetView[viewer].camera.matrix; vp: G3dMatrix.Viewport ¬ G3dTool.GetView[viewer].viewport; G3dDraw.DrawCircle[context, [-d.w,d.h,0], [-d.w,0,d.h], [-d.w,-d.h,0], 30, view, vp]; G3dDraw.DrawSegment[context, [-d.w, d.h, 0], [0, 0, 0], view, vp]; G3dDraw.DrawSegment[context, [-d.w, 0, d.h], [0, 0, 0], view, vp]; G3dDraw.DrawSegment[context, [-d.w, -d.h, 0], [0, 0, 0], view, vp]; G3dDraw.DrawSegment[context, [-d.w, 0, -d.h], [0, 0, 0], view, vp]; G3dDraw.DrawSegment[context, [d.x, d.rad, 0], [d.tip, d.rad, 0], view, vp]; G3dDraw.DrawSegment[context, [d.x, -d.rad, 0], [d.tip, -d.rad, 0], view, vp]; G3dDraw.DrawSegment[context, [d.x, 0, d.rad], [d.tip, 0, d.rad], view, vp]; G3dDraw.DrawSegment[context, [d.x, 0, -d.rad], [d.tip, 0, -d.rad], view, vp]; G3dDraw.DrawCircle[context,[d.tip,d.rad,0],[d.tip+d.rad,0,0],[d.tip,-d.rad,0],10, view, vp]; G3dDraw.DrawCircle[context,[d.tip,0,d.rad],[d.tip+d.rad,0,0],[d.tip,0,-d.rad],10, view, vp]; }; Stick: TYPE ~ RECORD [ p0, p1: Triple ¬ [0.0, 0.0, 0.0], acc: Quad ¬ [0.0, 0.0, 0.0, 0.0], r0, r1: REAL ¬ 0.0]; StickSequence: TYPE ~ REF StickSequenceRep; StickSequenceRep: TYPE ~ RECORD [ length: CARDINAL ¬ 0, element: SEQUENCE maxLength: CARDINAL OF Stick ]; StickData: TYPE ~ REF StickDataRep; StickDataRep: TYPE ~ RECORD [tool: Tool, sticks: StickSequence]; nullStick: Stick ¬ []; StickCommand: CommandProc ~ { d: StickData ¬ NEW[StickDataRep]; d.sticks ¬ NEW[StickSequenceRep[100]]; d.tool ¬ ImplicitDesign.MakeTool[ name: "Stick", startProc: StickStart, valueProc: StickValue, client: [draw: StickDraw, data: d], extraButtons: LIST[ Controls.ClickButton["Add Stick", StickAdd, d], Controls.ClickButton["Delete Stick", StickDelete, d], Controls.ClickButton["Delete All", StickAllDelete, d]]]; }; StickGet: PROC [tool: Tool] RETURNS [stick: Stick] ~ { n0, n1: NAT ¬ 0; reals: ARRAY [0..8) OF REAL; NextRope: PROC RETURNS [ROPE] ~ { IF (n0 ¬ Rope.SkipOver[reply, n1, " \t"]) = Rope.Length[reply] THEN RETURN[NIL]; n1 ¬ Rope.SkipTo[reply, n0, " \t"]; RETURN[Rope.Substr[reply, n0, n1-n0]]; }; reply: ROPE ¬ Controls.TypescriptRead[tool.typescript, "Add stick (x1,y1,z1,r1,x2,y2,z2,r2): "]; IF reply # NIL THEN FOR n: NAT IN [0..8) DO reals[n] ¬ Convert.RealFromRope[NextRope[] ! Convert.Error => GOTO BadFormat]; ENDLOOP; stick.p0 ¬ [reals[0], reals[1], reals[2]]; stick.p1 ¬ [reals[4], reals[5], reals[6]]; stick.r0 ¬ reals[3]; stick.r1 ¬ reals[7]; stick.acc ¬ G3dVector.NearnessAccelerator[stick.p0, stick.p1]; EXITS BadFormat => Controls.TypescriptWrite[tool.typescript, "Bad Format"]; }; StickAdd: ClickProc ~ { d: StickData ¬ NARROW[clientData]; stick: Stick ¬ StickGet[d.tool]; IF stick # nullStick THEN { d.sticks[d.sticks.length] ¬ stick; d.sticks.length ¬ d.sticks.length+1; ImplicitDesign.Repaint[d.tool]; }; }; StickDelete: ClickProc ~ { d: StickData ¬ NARROW[clientData]; stick: Stick ¬ StickGet[d.tool]; FOR n: NAT IN [0..d.sticks.length) DO IF d.sticks[n] = stick THEN { FOR nn: NAT IN [n..d.sticks.length-1) DO d.sticks[nn] ¬ d.sticks[nn+1]; ENDLOOP; d.sticks.length ¬ d.sticks.length-1; EXIT; }; ENDLOOP; ImplicitDesign.Repaint[d.tool]; }; StickAllDelete: ClickProc ~ { d: StickData ¬ NARROW[clientData]; d.sticks.length ¬ 0; ImplicitDesign.Repaint[d.tool]; }; StickValue: ValueProc ~ { d: StickData ¬ NARROW[clientData]; FOR n: NAT IN [0..d.sticks.length) DO s: Stick ¬ d.sticks[n]; near: NearSegment ¬ G3dVector.NearestToSegment[s.p0, s.p1, point, s.acc]; strength: REAL ¬ IF s.r0 # s.r1 THEN near.w0*s.r0+near.w1*s.r1 ELSE s.r0; value ¬ value+ImplicitValue.OfPoint[point, near.point, strength, inverseSqrd].value; ENDLOOP; }; StickStart: StartProc ~ { d: StickData ¬ NARROW[clientData]; s: Stick ¬ d.sticks[0]; pIn, pOut, v: Triple ¬ s.p0; v ¬ G3dVector.Unit[G3dVector.Ortho[G3dVector.Sub[s.p1, s.p0]]]; pOut ¬ G3dVector.ScaleRay[[s.p0, v], s.r0]; WHILE StickValue[pOut, d, NIL] > 0.0 DO pOut ¬ G3dVector.ScaleRay[[pOut, v], s.r0]; ENDLOOP; point ¬ ImplicitSurface.SurfacePoint[pIn, pOut, StickValue, d.tool.threshold, d]; }; StickDraw: DrawProc ~ { d: StickData ¬ NARROW[clientData]; v: G3dTool.View ¬ G3dTool.GetView[viewer]; FOR n: NAT IN [0..d.sticks.length) DO G3dDraw.DrawSegment[context, d.sticks[n].p0, d.sticks[n].p1, v.camera.matrix, v.viewport]; ENDLOOP; }; SteinerCommand: CommandProc ~ { [] ¬ ImplicitDesign.MakeTool[ name: "Steiner", startProc: SteinerStart, valueProc: SteinerValue, toolSettings: [trackSize: 0.02, threshold: 0.0]] }; SteinerValue: ValueProc ~ { xSq: REAL ¬ point.x*point.x; ySq: REAL ¬ point.y*point.y; zSq: REAL ¬ point.z*point.z; RETURN[xSq*ySq+xSq*zSq+ySq*zSq+point.x*point.y*point.z]; }; SteinerStart: StartProc ~ {RETURN[[0.0, 0.0, 0.0]]}; MiscData: TYPE ~ REF MiscDataRep; MiscDataRep: TYPE ~ RECORD [ tool: Tool ¬ NIL, aConstant: REAL ¬ 1.0, kConstant: REAL ¬ 1.0, vConstant: REAL ¬ 1.0 ]; MiscButtons: PROC [r: REF ANY] RETURNS [ButtonList] ~ { RETURN[LIST[ Controls.TextButton["A: ", "1.000", MiscButton, r], Controls.TextButton["K: ", "1.000", MiscButton, r], Controls.TextButton["V: ", "1.000", MiscButton, r]]]; }; MiscButton: ClickProc ~ { E: PROC [rope: ROPE] RETURNS [BOOL] ~ {RETURN[Rope.Equal[button.name, rope, FALSE]]}; N: PROC [o: REAL] RETURNS [r: REAL] ~ { rope: ROPE ¬ ViewerTools.GetContents[button.textViewer]; r ¬ Convert.RealFromRope[rope ! Convert.Error => {Blink["Bad value"]; r ¬ o; CONTINUE}]; }; m: MiscData ¬ NARROW[clientData]; button: Controls.Button ¬ NARROW[ViewerOps.FetchProp[parent, $ButtonText]]; SELECT TRUE FROM E["A: "] => m.aConstant ¬ N[m.aConstant]; E["K: "] => m.kConstant ¬ N[m.kConstant]; E["V: "] => m.vConstant ¬ N[m.vConstant]; ENDCASE; }; InterferenceCommand: CommandProc ~ { m: MiscData ¬ NEW[MiscDataRep]; }; InterferenceValue: ValueProc ~ { m: MiscData ¬ NARROW[clientData]; x2: REAL ~ point.x+point.x; xSq: REAL ~ point.x*point.x+1.0; ySq: REAL ~ point.y*point.y; zSq: REAL ~ point.z*point.z; IF NOT InBounds[point, 1.5] THEN RETURN[-1.0]; RETURN[ RealFns.Sin[m.kConstant*(xSq-x2+ySq+zSq)]+ RealFns.Sin[m.kConstant*(xSq+x2+ySq+zSq)]]; }; RippleCommand: CommandProc ~ { m: MiscData ¬ NEW[MiscDataRep]; }; RippleValue: ValueProc ~ { m: MiscData ¬ NARROW[clientData]; centers: ARRAY [0..4) OF Pair ~ [[0.0, 0.0], [0.2, 0.3], [-0.1, 0.4], [-0.2, -0.2]]; value ¬ m.vConstant*point.z; IF NOT InBounds[point, 1.5] THEN RETURN[-1.0]; FOR n: NAT IN [0..4) DO center: Pair ¬ centers[n]; y: REAL ~ center.y; dx: REAL ~ point.x-center.x; dy: REAL ~ point.y-center.y; dxSq: REAL ~ dx*dx; value ¬ value+ RealFns.Sin[m.kConstant*(dxSq+dy*dy)]*RealFns.Exp[-m.aConstant*(dxSq+y*y)]; ENDLOOP; }; InBounds: PROC [t: Triple, bound: REAL] RETURNS [ok: BOOL] ~ { ok ¬ t.x IN [-bound..bound] AND t.y IN [-bound..bound] AND t.z IN [-bound..bound]; }; Blink: PROC [message: ROPE] ~ { MessageWindow.Append[message, TRUE]; MessageWindow.Blink[]; }; ImplicitDesign.Register["Cone", ConeCommand, "explore a cone shape."]; ImplicitDesign.Register["Stick", StickCommand, "explore a stick shape."]; ImplicitDesign.Register["Steiner", SteinerCommand, "explore a steiner shape."]; ImplicitDesign.Register["Curve", CurveCommand, "explore various curve designs."]; ImplicitDesign.Register["Tube", TubeCommand, "explore various tube and web designs."]; ImplicitDesign.Register["Ripple", RippleCommand, "explore the shape of ripples."]; ImplicitDesign.Register["Interference", InterferenceCommand, "interference pattern shape."]; END. ώ ImplicitDesignCmdsAImpl.mesa Copyright Σ 1985, 1990 by Xerox Corporation. All rights reserved. Bloomenthal, August 11, 1992 4:06 pm PDT Types Tube Design textureProc: TubeTexture, Curve Design Cone Design ConeValue: ValueProc ~ { d: ConeData ¬ NARROW[clientData]; ax: REAL ¬ ABS[point.x]; IF ax > d.w THEN RETURN[-1.0] ELSE { r: REAL ¬ ax*d.ratio; RETURN[r*r-(point.y*point.y+point.z*point.z)]; }; }; ConeValue: ValueProc ~ { d: ConeData ¬ NARROW[clientData]; ax: REAL ¬ ABS[point.x]+0.05; IF ax > d.w THEN RETURN[-1.0] ELSE { r: REAL ¬ ax*ax*d.ratio; RETURN[0.05+r*r-(point.y*point.y+point.z*point.z)]; }; }; ConeDraw: DrawProc ~ { d: ConeData ¬ NARROW[data]; G3dDraw.DrawCircle[context, [-d.w,d.h,0], [-d.w,0,d.h], [-d.w,-d.h,0], 30, d.tool.view]; G3dDraw.DrawCircle[context, [d.w,d.h,0], [d.w,0,d.h], [d.w,-d.h,0], 30, d.tool.view]; G3dDraw.DrawSegment[context, [-d.w, d.h, 0], [d.w, -d.h, 0], d.tool.view]; G3dDraw.DrawSegment[context, [-d.w, 0, d.h], [d.w, 0, -d.h], d.tool.view]; G3dDraw.DrawSegment[context, [-d.w, -d.h, 0], [d.w, d.h, 0], d.tool.view]; G3dDraw.DrawSegment[context, [-d.w, 0, -d.h], [d.w, 0, d.h], d.tool.view]; }; Stick Design Steiner Surface Miscellaneous Designs Kevin's pattern. m.tool ¬ ImplicitDesign.MakeTool[toolName: "Interference", valueProc: InterferenceValue, clientData: m, extraButtons: MiscButtons[m], toolSettings: [threshold: 0.0]]; m.tool ¬ ImplicitDesign.MakeTool[toolName: "Implicit Ripple", valueProc: RippleValue,clientData: m, extraButtons: MiscButtons[m]]; Support Start Code Κ&•NewlineDelimiter ™™JšœB™BJ™(J˜JšΟk œ¦˜―J˜—šΠblœœ˜&J˜JšœΖ˜ΝJ˜—Jšœ˜headšΟl™Jšœœ˜+Jšœœ˜)Jšœ œ˜$Jšœœ˜+Jšœ œ˜'Jšœ œ˜#Jšœœ˜Jšœ œ˜"Jšœœ˜0Jšœœ˜5Jšœœ˜Jšœ œ˜'Jšœ œ˜*Jšœœ˜Jšœœ˜+Jšœ œ˜-Jšœ œ˜,Jšœœ˜/Jšœ œ˜+Jšœœ˜0Jšœ œ˜*Jšœ œ˜%Jšœ œ˜$Jšœœœ˜—šŸ ™ Jšœ œœ ˜#šœ œœ˜Jšœœ˜#Jšœ%œ˜)Jšœœ˜Jšœ œœ˜Jšœ˜J˜J˜—šΠbn œ˜Jšœœ˜˜!J˜ J˜J˜J™J˜"šœœ˜J˜LJ˜3J˜-J˜0—J˜7—J˜J˜—šΟn œ˜Jšœœ ˜!šœ˜JšœΟsœ ’œ’œ’œ’œ’œ˜O—J˜J˜—š‘ œ˜Jšœœ ˜!Jšœ œM˜[Jšœ œœœ˜šœ œœ œ˜;Jšœ œ˜-J˜—J˜šœœœ˜&Jšœ1œœ˜SJšœ˜—J˜J˜—š  œ˜Jšœœ ˜!J˜šœœ˜Jšœ œ:˜Fšœ œœ˜-Jšœ œ˜ Jšœœ ˜šœœœ˜&Jšœœ1˜;Jšœ œ˜-Jšœ˜—šœœ˜#Jšœ œ˜-Jšœœ˜*—J˜—šœ˜ ˜ J˜K———J˜J˜—š  œ˜Jšœœ ˜!šœ ˜Jšœ5˜9Jšœœ3˜>—J˜J˜—š‘ œ˜Jšœœ ˜!šœ ˜šœΟc$˜,Jšœœœœ ˜$Jšœœ˜J˜AJšœ œJ˜VJšœœI˜ZJšœœ˜2J˜Jšœœ;˜SJ˜J˜J˜J˜>J˜—Jš œœ œœ8œ˜Y—š œœ œœœ˜UJš’œT˜YJš ’œ’œ ’œ’œ’œ’œ˜^—J˜J˜—š‘œ˜Jšœœ ˜!J˜-Icode˜HLšœ œG˜VJ˜J˜—šΟbœœ˜3J˜—š€œ˜Jšœœ ˜!J˜Jšœœœ˜$J˜J˜—š‘œœ˜J˜Mšœ˜ Jšœ*˜.Jšœ˜—J˜J˜—š‘œœœ˜4JšœœS˜ZJ˜Jšœœœœ ˜BJ˜J˜—š‘œœ˜+J˜!Jšœœ˜@J˜HJ˜J˜——šŸ ™ Jšœ œœ˜%šœ œœ˜Jšœœ˜Jšœœ˜J˜/Jšœœ˜Jšœ˜!J˜J˜—š  œ˜Jšœœ˜!˜!J˜J˜J˜J˜#šœœ˜J˜1J˜-J˜1—J˜J˜—J˜J˜—š€ œ˜Jšœœ ˜"J˜3šœ˜J˜SJ˜UJ˜UJšœ˜—J˜J˜—š  œ˜Jšœœ ˜"šœ˜˜ Jšœœ˜ Jšœœ ˜šœœœ˜Jšœœ0˜:Jšœ œ˜+Jšœ˜—Jšœ˜J˜—˜ J˜IJšœ˜J˜—˜ J˜IJšœœ$˜-Jšœœ3˜:JšœœN˜UJšœœœ ˜+Jšœ˜J˜—Jšœ˜—J˜J˜—š‘ œ˜Jšœœ ˜"J˜Jšœ œœ6˜Jšœ˜˜J˜_JšœK˜QJ˜—šœœ˜J˜V——J˜J˜—š‘ œ˜Jšœœ ˜"J˜-L˜HJ˜J˜—š‘ œœ˜$šœ œœ˜0Jšœ œ˜2—šœœœ˜Jšœ0œœ˜KJšœ˜—J˜J˜—š€ œ˜Jšœœ ˜"J˜EJ˜J˜J˜—š€ œ˜Jšœœ ˜"Jšœœœ˜9J˜——šŸ ™ Jšœ œœ ˜#šœœœ8œ˜YJ˜—š  œ˜Jšœœ˜J˜˜!J˜ J˜J˜J˜J˜"šœœ˜J˜6J˜8—J˜ —J˜J˜—š€ œ˜Jš‘œœœœœœœ˜Uš ‘œœœœœ˜'Icedaršœœ.˜8MšœL œ˜XJ˜—Jšœœ ˜!Jšœœ+˜Kšœœ˜Jšœœ ˜"Jšœœ ˜#Jšœœ˜—J˜J˜J˜J˜—š‘œœœ˜+Jš œ œœ œœ œœ˜NJ˜J˜J˜J˜J˜J˜J˜J˜—š‘ œ˜Jšœœ ˜!Jšœ˜J˜J™—š  œ˜Jšœœ ˜!šœ ˜Jšœœ˜ ˜ Jšœœ˜Jšœ(˜.J˜—Jšœ œ+˜<šœ˜ Jšœœ˜Jšœ1˜7J˜——J˜J˜—š‘ œ˜Jšœœ ˜!Jšœ˜J˜J˜—š‘œ˜Jšœœ ˜!J˜?J˜:L˜UL˜BL˜BL˜CL˜CL˜KL˜ML˜KL˜MLšœ’ œJ˜\Lšœ’ œJ˜\J˜J˜—š  œ™Jšœœ ™!Jšœœœ ™šœ œœœ™$Jšœœ™Jšœ(™.J™—J™J™—š  œ™Jšœœ ™!Jšœœœ™šœ œœœ™$Jšœœ™Jšœ-™3J™—J™J˜—š‘œ™Jšœœ™L™XL™UL™JL™JL™JL™JJ™——šŸ ™ šœ œœ˜J˜&J˜'Jšœœ˜J˜—Jšœœœ˜,šœœœ˜!Jšœœ˜Jšœœ œœ˜3˜J˜——Jšœ œœ˜&šœœœ%˜AJ˜—˜J˜—š  œ˜Jšœœ˜!Jšœ œ˜&˜!J˜J˜J˜J˜#šœœ˜J˜/J˜5J˜8——J˜J˜—š‘œœœ˜6Jšœœ˜Jšœœœœ˜š‘œœœœ˜!Jšœ=œœœ˜PJ˜#Jšœ ˜&J˜—JšœœU˜`š œ œœœœœ˜+Jšœ>œ ˜NJšœ˜—J˜*J˜*J˜J˜J˜>š˜J˜E—J˜J˜—š‘œ˜Jšœœ ˜"J˜ šœœ˜J˜"J˜$J˜J˜—J˜J˜—š‘ œ˜Jšœœ ˜"J˜ šœœœ˜%šœœ˜šœœœ˜(J˜Jšœ˜—J˜$Jšœ˜J˜—Jšœ˜—J˜J˜J˜—š‘œ˜Jšœœ ˜"J˜J˜J˜J˜—š  œ˜Jšœœ ˜"šœœœ˜%J˜J˜IJš œ œœ œœ˜IJ˜TJšœ˜—J˜J˜—š‘ œ˜Jšœœ ˜"J˜J˜J˜?J˜+šœœ˜'J˜+Jšœ˜—J˜QJ˜J˜—š‘ œ˜Jšœœ ˜"J˜*šœœœ˜%J˜ZJšœ˜—J˜——šŸ™š œ˜˜J˜J˜J˜J˜0—J˜J˜—š  œ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœ2˜8J˜J˜—Jš‘ œœ˜4—šŸ™Jšœ œœ ˜$šœ œœ˜Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜J˜J˜—š ‘ œœœœœ˜7šœœ˜ J˜3J˜3J˜5—J˜J˜—š‘ œ˜Jš‘œœœœœœœ˜Uš ‘œœœœœ˜'Mšœœ.˜8MšœL œ˜XJ˜—Jšœœ ˜!Jšœœ+˜Kšœœ˜J˜)J˜)J˜)Jšœ˜—J˜J˜—š œ˜$J™Jšœœ˜J™¦J˜J˜—š€œ˜ Jšœœ ˜!Jšœœ˜Jšœœ˜ Jšœœ˜Jšœœ˜Jšœœœœ˜.šœ˜J˜*J˜+—J˜J˜—š  œ˜Jšœœ˜J™‚J˜J˜—š‘ œ˜Jšœœ ˜!Jšœ œœ<˜TJ˜Jšœœœœ˜.šœœœ˜J˜Jšœœ ˜Jšœœ˜Jšœœ˜Jšœœ ˜˜J˜K—Jšœ˜—J˜——šŸ™š ‘œœœœœ˜>Jš œ œœœœœ˜RJ˜J˜—š‘œœ œ˜Jšœœ˜$J˜J˜——šŸ ™ J˜FJ˜IJ˜OJ˜QJ˜VJ˜RJ˜\—J˜Jšœ˜—…—Gϊa