<<>> <> <> <> DIRECTORY Commander, Controls, G3dBasic, G3dDraw, G3dOctree, G3dTool, G3dVector, ImplicitDesign, ImplicitMinimal, ImplicitValue, MessageWindow, RealFns, Rope, Vector2, ViewerClasses; ImplicitSimpleCmdImpl: CEDAR PROGRAM IMPORTS Controls, G3dDraw, G3dTool, G3dVector, ImplicitDesign, ImplicitValue, MessageWindow, RealFns, Rope, Vector2 ~ BEGIN <> Triple: TYPE ~ G3dBasic.Triple; TripleSequence: TYPE ~ G3dBasic.TripleSequence; Tool: TYPE ~ ImplicitDesign.Tool; Function: TYPE ~ ImplicitMinimal.Function; Source3dSequence: TYPE ~ ImplicitValue.Source3dSequence; ROPE: TYPE ~ Rope.ROPE; ClickProc: TYPE ~ ViewerClasses.ClickProc; <> Op: TYPE ~ {union, sphere, cylinder, torus, plane, wiffle, blob, fourPoleBlob, ellipsoid, doubleCone, saddle, tubularCorner, teapotTop}; SimpleData: TYPE ~ REF SimpleDataRep; SimpleDataRep: TYPE ~ RECORD [ tool: Tool ¬ NIL, op: Op ¬ sphere, -- which of simple objects points: TripleSequence ¬ NIL, -- for quick drawing of sphere cylLength: REAL ¬ 0.0, -- half length of cylinder r: REAL ¬ 0.0, -- radius of cylinder, sphere, torus r2: REAL ¬ 0.0, -- radius squared rr: REAL ¬ 0.0, -- minor torus radius rr2, r4, rr4, a, b, c: REAL ¬ 0.0, -- accelerators for torus blobSeparation: REAL ¬ 0.185, -- distance between blob centers blobbiness: REAL ¬ 0.0, -- blobbiness between two centers blobSources: Source3dSequence ¬ NIL, -- blob centers sphereCount: INTEGER ¬ 0 <> <> <> <> <> <> <> ]; SimpleCommand: Commander.CommandProc ~ { s: SimpleData ~ NEW[SimpleDataRep]; Setup[s, 0.1]; s.tool ¬ ImplicitDesign.MakeTool[ name: "Simple", function: Value, start: Start, client: [draw: Draw, data: s], extraButtons: LIST[ Controls.ClickButton["Radius", Radius, s], Controls.ClickButton["BSep", BlobSeparation, s], Controls.ClickButton["Bness", Blobbiness, s], <> <> <> <> <> <> <> <> <> Controls.ClickButton["Type: sphere", SimpleCycle, s]], useArcBalls: FALSE, camera: [[0, 2, 0], [], 2.5, 60], toolSettings: [level: 0.0] ]; }; Start: ImplicitDesign.StartProc ~ { s: SimpleData ¬ NARROW[clientData]; point ¬ IF s.op = wiffle THEN [0.6605536, -1.449449, 1.804281] ELSE []; }; Setup: PROC [s: SimpleData, radius: REAL] ~ { s.r ¬ radius; -- radius for sphere, cylinder, major radius for torus s.cylLength ¬ 2.0*s.r; s.points ¬ G3dDraw.GetSpherePoints[[0.0, 0.0, 0.0], s.r, 10]; s.rr ¬ 0.2*radius; -- minor radius for torus s.r2 ¬ s.r*s.r; s.rr2 ¬ s.rr*s.rr; s.r4 ¬ s.r2*s.r2; s.rr4 ¬ s.rr2*s.rr2; s.a ¬ s.r2+s.rr2; s.b ¬ s.r2-s.rr2; s.c ¬ s.r2*s.rr2; s.blobSources ¬ NEW[ImplicitValue.Source3dSequenceRep[2]]; s.blobSources.length ¬ 2; s.blobSources[0] ¬ [[-0.5*s.blobSeparation, 0.0, 0.0], s.r, 1.0/(s.r*s.r)]; s.blobSources[1] ¬ [[0.5*s.blobSeparation, 0.0, 0.0], 0.5*s.r, 1.0/(0.5*0.5*s.r*s.r)]; <> }; Value: Function ~ { s: SimpleData ¬ NARROW[clientData]; SELECT s.op FROM union => { <> c1: Triple ¬ [-.15, 0, 0]; r1: REAL ¬ 0.35; c2: Triple ¬ [0.5, 0, 0]; r2: REAL ¬ 0.5; RETURN[MAX[r1-G3dVector.Distance[point, c1], r2-G3dVector.Distance[point, c2]]]; }; blob => { IF s.blobbiness < 0.0 THEN FOR n: NAT IN [0..s.blobSources.length) DO b: ImplicitValue.Source3d ¬ s.blobSources[n]; rSqrd: REAL ¬ G3dVector.SquareDistance[b.p, point]; rR: REAL ¬ rSqrd*b.sInvSqrd; exp: REAL ¬ s.blobbiness*(rR-1.0); IF exp > 50.0 THEN RETURN[1000.0]; IF exp > -50.0 THEN value ¬ value+RealFns.Exp[exp]; ENDLOOP ELSE value ¬ ImplicitValue.OfSources3d[point, s.blobSources, inverseSqrd]; value ¬ value-1.0; }; wiffle => { ax: REAL ¬ point.x/2.4; bx: REAL ¬ point.x/2.0; ay: REAL ¬ point.y/2.4; by: REAL ¬ point.y/2.0; az: REAL ¬ point.z/2.4; bz: REAL ¬ point.z/2.0; bx2: REAL ¬ bx*bx; by2: REAL ¬ by*by; bz2: REAL ¬ bz*bz; bx4: REAL ¬ bx2*bx2; by4: REAL ¬ by2*by2; bz4: REAL ¬ bz2*bz2; terma: REAL ¬ ax*ax+ay*ay+az*az; termb: REAL ¬ bx4*bx4+by4*by4+bz4*bz4; terma2: REAL ¬ terma*terma; termb2: REAL ¬ termb*termb; terma6: REAL ¬ terma2*terma2*terma2; termb6: REAL ¬ termb2*termb2*termb2; value ¬ (1.0-termb6-1.0/terma6); }; sphere => { s.sphereCount ¬ s.sphereCount+1; value ¬ s.r2-G3dVector.Square[point]; <> <> }; cylinder => value ¬ s.r2-(SELECT point.x FROM < -s.cylLength => G3dVector.SquareDistance[point, [-s.cylLength, 0.0, 0.0]], > s.cylLength => G3dVector.SquareDistance[point, [ s.cylLength, 0.0, 0.0]], ENDCASE => Vector2.Square[[point.y, point.z]]); torus => { <> x2: REAL ~ point.x*point.x; y2: REAL ~ point.y*point.y; z2: REAL ~ point.z*point.z; u: REAL ¬ x2+y2+z2+s.r2-s.rr2; value ¬ u*u-4*s.r2*(y2+z2); <<-(x2*x2+y2*y2+z2*z2+s.r4+s.rr4+2.*(x2*y2+x2*z2+y2*z2-s.a*x2+s.b*y2-s.a*z2-s.c));>> }; plane => value ¬ point.y; fourPoleBlob => { x2: REAL ¬ point.x*point.x; y2: REAL ¬ point.y*point.y; z2: REAL ¬ point.z*point.z; value ¬ x2*y2+x2*z2+y2*z2+7.0*point.x*point.y*point.z+x2+y2+z2-1; }; ellipsoid => value ¬ point.x*point.x+point.y*point.y+4.0*point.z*point.z-1.0; doubleCone => value ¬ point.x*point.x+point.y*point.y-0.8*point.z*point.z-0.3; saddle => value ¬ 3.0*point.x*point.x-point.y*point.y+2.0*point.z; tubularCorner => { x2: REAL ¬ point.x*point.x; y2: REAL ¬ point.y*point.y; z2: REAL ¬ point.z*point.z; value ¬ x2*y2+x2*z2+y2*z2+point.x+point.y-point.z+1.0; }; teapotTop => { z2: REAL ¬ point.z*point.z; value ¬ point.x*point.x+point.y*point.y+point.z*z2+1.8*z2-1.0; }; ENDCASE; }; Radius: ClickProc ~ { s: SimpleData ¬ NARROW[clientData]; s.r ¬ ReadValue[s.tool, "Radius", s.r]; Setup[s, s.r]; }; BlobSeparation: ClickProc ~ { s: SimpleData ¬ NARROW[clientData]; s.blobSeparation ¬ ReadValue[s.tool, "Blob separation", s.blobSeparation]; s.blobSources[0].p ¬ [-0.5*s.blobSeparation, 0.0, 0.0]; s.blobSources[1].p ¬ [0.5*s.blobSeparation, 0.0, 0.0]; }; Blobbiness: ClickProc ~ { s: SimpleData ¬ NARROW[clientData]; s.blobbiness ¬ ReadValue[s.tool, "Blobbiness (< 0)", s.blobbiness]; }; Draw: G3dTool.DrawProc ~ { s: SimpleData ¬ NARROW[clientData]; SELECT s.op FROM blob => { G3dDraw.Sphere[context, s.blobSources[0].p, s.blobSources[0].strength, 8, view, vp]; G3dDraw.Sphere[context, s.blobSources[1].p, s.blobSources[1].strength, 8, view, vp]; }; sphere => G3dDraw.Sphere[context, [0.0, 0.0, 0.0], s.r, 10, view, vp, s.points]; ENDCASE; }; SimpleCycle: ClickProc ~ { Roper: PROC [op: Op] RETURNS [name: ROPE] ~ { name ¬ Rope.Concat["Type: ", SELECT op FROM sphere => "sphere", cylinder => "cylinder", torus => "torus", plane => "plane", wiffle => "wiffle", union => "union", blob => "blob", fourPoleBlob => "four pole blob", ellipsoid => "ellipsoid", doubleCone => "double cone", saddle => "saddle", tubularCorner => "tubular corner", teapotTop => "teapot top", ENDCASE => NIL]; }; requests: LIST OF Controls.Request ¬ LIST[ --1-- ["sphere", "a sphere of the given radius"], --2-- ["cylinder", "a cylinder of the given radius"], --3-- ["torus", "a torus of given minor and major radii"], --4-- ["plane", "the xz plane"], --5-- ["wiffle", "the rounded edges of a cube"], --6-- ["union", "the union of two spheres"], --7-- ["blob", "the blobby combination of sources"], --8-- ["fourPoleBlob", "blobby of four elements"], --9-- ["ellipsoid", "ellipsoidal shape"], --10-- ["doubleCone", "two cones"], --11-- ["saddle", "saddle surface"], --12-- ["tubularCorner", "corners"], --13-- ["teapotTop", "top of a teapot"] ]; d: SimpleData ~ NARROW[clientData]; old: Op ~ d.op; d.op ¬ SELECT Controls.PopUpRequest[["Simple Functions"], requests] FROM 1 => sphere, 2 => cylinder, 3 => torus, 4 => plane, 5 => wiffle, 6 => union, 7 => blob, 8 => fourPoleBlob, 9 => ellipsoid, 10 => doubleCone, 11 => saddle, 12 => tubularCorner, 13 => teapotTop, ENDCASE => d.op; <> <> <> <> <<};>> Controls.ButtonRelabel[d.tool.tool3d.outerData, Roper[old], Roper[d.op]]; IF mouseButton = blue THEN ImplicitDesign.Repaint[d.tool, $Client]; }; <> TSWrite: PROC [s: SimpleData, r: ROPE] ~{G3dTool.TSWrite[s.tool.tool3d, r]}; Blink: PROC [message: ROPE] ~ { MessageWindow.Append[message, TRUE]; MessageWindow.Blink[]; }; ReadValue: PROC [t: Tool, prompt: ROPE, value: REAL] RETURNS [REAL] ~ { RETURN[Controls.TypescriptReadValue[t.tool3d.typescript, prompt, value]]; }; <> ImplicitDesign.Register["Simple", SimpleCommand, "plane, sphere, cylinder, torus, blob."]; END. .. <<>> <> <> <> <<};>> <<>> <> <> <> <> <> <> <> <> <> <<};>> <<};>> <<>> <> <> <> <> <> <> <> <> <<};>> <<};>> <<>> <> <> <> <> <> <> <> <> <<};>> <<};>> <<>> <> <> <> <> <> <> <<};>> IF whatChanged = NIL THEN { IF s.doInspect THEN G3dCubeDraw.SimpleCube[context, s.inspect, view, vp,, solid]; <> <> <> <> <> <> <> <> <> <> <> <> <<};>> } ELSE IF s.doInspect THEN { <> <> <> <> <> <<};>> <> <> <> <> }; Toggle: PROC [data: REF ANY, button: ViewerClasses.MouseButton, name: ROPE] ~ { d: SimpleData ~ NARROW[data]; bool: BOOL ¬ SELECT TRUE FROM Rope.Equal[name, "Inspect"] => (d.doInspect ¬ NOT d.doInspect), Rope.Equal[name, "Dual"] => (d.doInspect ¬ NOT d.doInspect), Rope.Equal[name, "Clip"] => (d.doClip ¬ NOT d.doClip), ENDCASE => FALSE; Controls.ButtonToggle[d.tool.tool3d.outerData, bool, Rope.Concat[name, "-On"], Rope.Concat[name, "-Off"]]; IF button = blue THEN [] ¬ ImplicitDesign.Repaint[d.tool]; }; SphereNormal: NormalProc ~ {RETURN[point]}; SphereTexture: TextureProc ~ { polar: Triple ~ G3dVector.PolarFromCartesian[vertex.point]; RETURN[[polar.x/360.0, polar.y/360.0]]; }; SetBlobColors: PROC [surface: Surface, blobSources: Source3dSequence] ~ { p0: Triple ~ blobSources[0].p; p1: Triple ~ blobSources[1].p; r0Sqd: REAL ~ blobSources[0].strength*blobSources[0].strength; r1Sqd: REAL ~ blobSources[1].strength*blobSources[1].strength; FOR n: NAT IN [0..surface.vertices.length) DO v: Vertex ~ surface.vertices[n]; pot0: REAL ~ r0Sqd/MAX[0.0001, G3dVector.SquareDistance[p0, v.point]]; pot1: REAL ~ r1Sqd/MAX[0.0001, G3dVector.SquareDistance[p1, v.point]]; [[v.rgb.x, v.rgb.y, v.rgb.z]] ¬ ImagerColorFns.RGBFromHSL[[pot0/(pot0+pot1), 1.0, 0.5]]; ENDLOOP; surface.vertexValidities.color ¬ TRUE; }; ToggleInspect: ClickProc ~ {Toggle[clientData, mouseButton, "Inspect"]}; ToggleDual: ClickProc ~ {Toggle[clientData, mouseButton, "Dual"]}; ToggleClip: ClickProc ~ {Toggle[clientData, mouseButton, "Clip"]}; Controls.ClickButton["Inspect-Off", ToggleInspect, s], Controls.ClickButton["Dual-Off", ToggleDual, s], Controls.ClickButton["Clip-Off", ToggleClip, s], Controls.ClickButton["PrintSphereCount", PrintSphereCount, s], PrintSphereCount: ClickProc ~ { s: SimpleData ¬ NARROW[clientData]; TSWrite[s, IO.PutFR["sphere count: %g",IO.int[s.sphereCount]]]; };