<<>> <> <> <> DIRECTORY Commander, G3dBasic, G3dBox, G3dOctree, IO, Random, Rope; G3dCubeTestImpl: CEDAR PROGRAM IMPORTS Commander, G3dBox, G3dOctree, IO, Random ~ BEGIN ROPE: TYPE ~ Rope.ROPE; Box: TYPE ~ G3dBasic.Box; Cube: TYPE ~ G3dOctree.Cube; CubeObject: TYPE ~ G3dOctree.CubeObject; Triple: TYPE ~ G3dBasic.Triple; NamedSphere: TYPE ~ REF NamedSphereRep; NamedSphereRep: TYPE ~ RECORD [ name: ROPE ¬ NIL, center: Triple, radius: REAL ]; NewNamedSphere: PROC [name: ROPE ¬ NIL, center: Triple, radius: REAL] RETURNS [NamedSphere] ~ { RETURN [NEW[NamedSphereRep ¬ [name,center,radius]]]; }; SphereBbox: PROC [ns: NamedSphere] RETURNS [Box] ~ { RETURN [G3dBox.BoxFromPoints[[ns.center.x - ns.radius, ns.center.y - ns.radius, ns.center.z - ns.radius], [ns.center.x + ns.radius, ns.center.y + ns.radius, ns.center.z + ns.radius]]]; }; SphereQueryProc: G3dOctree.CubeObjectQueryProc ~ { <> ns: NamedSphere ¬ NARROW[val]; distSq: REAL ¬ (pt.x - ns.center.x) * (pt.x - ns.center.x) + (pt.y - ns.center.y)*(pt.y-ns.center.y) + (pt.z-ns.center.z)*(pt.z-ns.center.z); RETURN [distSq <= ns.radius*ns.radius]; }; COSphere: PROC [name: ROPE ¬ NIL, center: Triple, radius: REAL] RETURNS [CubeObject] ~ { ns: NamedSphere ¬ NewNamedSphere[name,center,radius]; RETURN [NEW[G3dOctree.CubeObjectRep ¬ [ns, SphereBbox[ns], SphereQueryProc]]]; }; G3dCubeTestDoc: ROPE _ "G3dCubeTest: no aguments"; G3dCubeTestProc: Commander.CommandProc = { cube: Cube; obj: REF ANY; nMarbles: INT = 200; objList: LIST OF CubeObject; rs: Random.RandomStream ¬ Random.Create[1000]; report: PROC [obj: REF ANY, shouldBe: ROPE ¬ NIL] ~ { IF shouldBe # NIL THEN IO.PutF1[cmd.out,"Next line should say: '%g'\n", IO.rope[shouldBe]]; IF obj = NIL THEN { IO.PutRope[cmd.out,"No hit.\n"]; RETURN; }; WITH obj SELECT FROM ns: NamedSphere => IO.PutF1[cmd.out,"Hit Sphere '%g'\n", IO.rope[ns.name]]; ENDCASE => IO.PutRope[cmd.out, "Hit an object of a weird type.\n"]; }; <<-) make a really simple one, around one big sphere:>> cube ¬ G3dOctree.FromObjects[LIST[COSphere["Alice",[500,500,500],500]]]; obj ¬ G3dOctree.QueryObjects[cube,[500,500,500]]; report[obj, "Hit Sphere 'Alice'"]; obj ¬ G3dOctree.QueryObjects[cube,[1,1,1]]; report[obj, "No Hit"]; obj ¬ G3dOctree.QueryObjects[cube,[2000,2000, 2000]]; report[obj, "No Hit"]; <> cube ¬ G3dOctree.FromObjects[LIST[COSphere["Bob",[100,100,100],100], COSphere["Chuck",[200,200,100],25]]]; obj ¬ G3dOctree.QueryObjects[cube,[30,70,100]]; report[obj, "Hit Sphere 'Bob'"]; obj ¬ G3dOctree.QueryObjects[cube,[205,195,100]]; report[obj, "Hit Sphere 'Chuck'"]; obj ¬ G3dOctree.QueryObjects[cube,[190,190,100]]; report[obj, "Hit Sphere 'Chuck'"]; obj ¬ G3dOctree.QueryObjects[cube,[1500,1500,500]]; report[obj, "No Hit"]; obj ¬ G3dOctree.QueryObjects[cube,[175,175,100]]; report[obj, "No Hit"]; <> cube ¬ G3dOctree.FromObjects[LIST[COSphere["Dave",[50,50,500],45], COSphere["Ed",[350,50,500],45], COSphere["Fred",[50,350,500],45],COSphere["George",[350,350,500],45]]]; G3dOctree.AddObject[cube,COSphere["Harry",[150,250,500],45]]; G3dOctree.AddObject[cube,COSphere["Irene",[250,150,500],45]]; obj ¬ G3dOctree.QueryObjects[cube,[40,40,500]]; report[obj, "Hit Sphere 'Dave'"]; obj ¬ G3dOctree.QueryObjects[cube,[360,40,500]]; report[obj, "Hit Sphere 'Ed'"]; obj ¬ G3dOctree.QueryObjects[cube,[40,360,500]]; report[obj, "Hit Sphere 'Fred'"]; obj ¬ G3dOctree.QueryObjects[cube,[360,360,500]]; report[obj, "Hit Sphere 'George'"]; obj ¬ G3dOctree.QueryObjects[cube,[165,235,500]]; report[obj, "Hit Sphere 'Harry'"]; obj ¬ G3dOctree.QueryObjects[cube,[265,140,500]]; report[obj, "Hit Sphere 'Irene'"]; obj ¬ G3dOctree.QueryObjects[cube,[150,150,500]]; report[obj, "No Hit'"]; obj ¬ G3dOctree.QueryObjects[cube,[200,200,500]]; report[obj, "No Hit'"]; <> G3dOctree.SubdivideGivenObjects[cube,1,6]; obj ¬ G3dOctree.QueryObjects[cube,[40,40,500]]; report[obj, "Hit Sphere 'Dave'"]; obj ¬ G3dOctree.QueryObjects[cube,[360,40,500]]; report[obj, "Hit Sphere 'Ed'"]; obj ¬ G3dOctree.QueryObjects[cube,[40,360,500]]; report[obj, "Hit Sphere 'Fred'"]; obj ¬ G3dOctree.QueryObjects[cube,[360,360,500]]; report[obj, "Hit Sphere 'George'"]; obj ¬ G3dOctree.QueryObjects[cube,[165,235,500]]; report[obj, "Hit Sphere 'Harry'"]; obj ¬ G3dOctree.QueryObjects[cube,[265,140,500]]; report[obj, "Hit Sphere 'Irene'"]; obj ¬ G3dOctree.QueryObjects[cube,[150,150,500]]; report[obj, "No Hit'"]; obj ¬ G3dOctree.QueryObjects[cube,[200,200,500]]; report[obj, "No Hit'"]; <> objList ¬ NIL; FOR i: INT IN [0 .. nMarbles) DO objList ¬ CONS[COSphere[IO.PutFR1["m%g", IO.int[i]], [Random.NextInt[rs], Random.NextInt[rs], Random.NextInt[rs]], 50], objList]; ENDLOOP; cube ¬ G3dOctree.FromObjects[objList]; G3dOctree.SubdivideGivenObjects[cube,8,10]; FOR i: INT IN [0 .. nMarbles * 2) DO pt: Triple ¬ [Random.NextInt[rs], Random.NextInt[rs], Random.NextInt[rs]]; <> obj ¬ G3dOctree.QueryObjects[cube,pt]; <> IF obj = NIL THEN { FOR l2: LIST OF CubeObject _ objList, l2.rest WHILE l2 # NIL DO obj2: REF ANY ¬ l2.first.val; IF SphereQueryProc[obj2, pt] THEN { IO.PutFL[cmd.out,"ERROR: [%g,%g,%g] IS in sphere '%g'.\n",LIST[IO.real[pt.x], IO.real[pt.y], IO.real[pt.z], IO.rope[NARROW[obj2,NamedSphere].name]]]; }; ENDLOOP; } ELSE { IF NOT SphereQueryProc[obj,pt] THEN { ns: NamedSphere ¬ NARROW[obj]; IO.PutFL[cmd.out,"ERROR: [%g,%g,%g] not in sphere '%g' as claimed.\n",LIST[IO.real[pt.x], IO.real[pt.y], IO.real[pt.z], IO.rope[NARROW[obj,NamedSphere].name]]]; }; }; ENDLOOP; }; Commander.Register[key: "G3dCubeTest", proc: G3dCubeTestProc, doc: G3dCubeTestDoc, clientData: NIL]; END.