G3dCubeTestImpl.mesa
Ken Fishkin, August 25, 1992 12:17 pm PDT
Jules Bloomenthal November 21, 1992 2:53 pm PST
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 ~ {
CubeObjectQueryProc: TYPE ~ PROC[val: REF ANY, pt: Triple] RETURNS [BOOL];
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"];
Two objects:
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"];
create some outside objects, and then add some on the inside:
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'"];
Subdivide it so that no cube contains more than one element, and try again:
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'"];
Make a whole bunch of little marbles, and check it out:
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]];
IO.PutFL[cmd.out,"probe #%g: [%g, %g, %g]\n", LIST[IO.int[i], IO.real[pt.x], IO.real[pt.y], IO.real[pt.z]]];
obj ¬ G3dOctree.QueryObjects[cube,pt];
report[obj];
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.