예제 #1
0
        public void ItemRetrieval_AABB()
        {
            var treeBounds = new AABB(Vector3.zero, new Vector3(distanceOfSideOfTreeFromCentre, distanceOfSideOfTreeFromCentre, distanceOfSideOfTreeFromCentre));
            var octree     = new Octree <TestObject>(minNodeWidth, treeBounds);

            var insertedObjects = new List <TestObject>();

            /*
             * This will make it easier to go through all the permutations of AABBs
             * this will give us objects which touch the edge of the Octree
             */
            var testPositions = new List <Vector3>();

            #region Try putting one item in each node
            for (var x = -distanceOfSideOfTreeFromCentre + distanceOfSideOfTreeFromCentre / 2f; x < distanceOfSideOfTreeFromCentre; x += minNodeWidth)
            {
                for (var y = -distanceOfSideOfTreeFromCentre + distanceOfSideOfTreeFromCentre / 2f; y < distanceOfSideOfTreeFromCentre; y += minNodeWidth)
                {
                    for (var z = -distanceOfSideOfTreeFromCentre + distanceOfSideOfTreeFromCentre / 2f; z < distanceOfSideOfTreeFromCentre; z += minNodeWidth)
                    {
                        var testPosition = new Vector3(x, y, z);
                        testPositions.Add(testPosition);

                        var testObj = new TestObject(testPosition);

                        octree.Insert(testObj);

                        insertedObjects.Add(testObj);
                    }
                }
            }
            #endregion

            var objectsOutsideTree = new List <TestObject>();

            #region Insert objects which do not fit in the tree
            foreach (var extent in treeBounds.EnumerateExtents())
            {
                var extentDir = new Vector3(Math.Sign(extent.x), Math.Sign(extent.y), Math.Sign(extent.z));
                var offset    = extentDir * TestObject.Dimensions;

                var testObj = new TestObject(treeBounds.center + extent + offset);

                octree.Insert(testObj);

                objectsOutsideTree.Add(testObj);
            }
            #endregion

            #region Getting all items in tree returns correct result

            var allItemsInTree = octree.getAllContents().ToHashSet();

            foreach (var testObj in insertedObjects)
            {
                Assert.IsTrue(allItemsInTree.Contains(testObj), $"The object {testObj} was inserted into the octree but was not found when fetching all objects");
            }

            foreach (var testObj in objectsOutsideTree)
            {
                Assert.IsFalse(allItemsInTree.Contains(testObj), $"The object {testObj} falls outside the tree bounds but was successfully inserted into the tree");
            }

            Assert.AreEqual(insertedObjects.Count, allItemsInTree.Count, "Duplicate items in tree");

            #endregion

            #region Brute force test that any bounds query returns all objects in that bounds

            for (var i = 0; i < testPositions.Count; ++i)
            {
                for (var j = i + 1; j < testPositions.Count; ++j)
                {
                    var bottomCorner = testPositions[i];
                    var upperCorner  = testPositions[j];

                    var queryAABB = AABB.Create(new[] { bottomCorner, upperCorner });

                    octree.GetOverlappingItems(queryAABB, out var queryResult);

                    var queryResultHashset = queryResult.ToHashSet();

                    foreach (var item in allItemsInTree)
                    {
                        if (queryAABB.Overlaps(item.AABB))
                        {
                            Assert.IsTrue(queryResultHashset.Contains(item), $"{item} overlaps query bounds {queryAABB} but was not found in the results");
                        }
                        else if (queryResultHashset.Contains(item))
                        {
                            Assert.Fail($"Query bounds {queryAABB} does not overlap {item} but it was in the results set");
                        }
                    }
                }
            }
            #endregion
        }