/*
* Copyright 2014 MovingBlocks
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.terasology.utilities.tree;
import org.junit.Test;
import java.util.Collection;
import java.util.Iterator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class SpaceTreeTest {
@Test
public void test2DTreeErrors() {
SpaceTree<Object> tree = new SpaceTree<>(2);
try {
tree.add(null, new Object());
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException exp) {
// Expected
}
try {
tree.add(new float[1], new Object());
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException exp) {
// Expected
}
try {
tree.add(new float[3], new Object());
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException exp) {
// Expected
}
try {
tree.add(new float[2], null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException exp) {
// Expected
}
try {
tree.remove(null);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException exp) {
// Expected
}
try {
tree.remove(new float[1]);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException exp) {
// Expected
}
try {
tree.remove(new float[3]);
fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException exp) {
// Expected
}
}
@Test
public void test2DTreeValues() {
SpaceTree<Object> tree = new SpaceTree<>(2);
assertNull(tree.remove(new float[2]));
Object obj1 = new Object();
Object obj2 = new Object();
assertNull(tree.add(new float[2], obj1));
assertSame(obj1, tree.add(new float[2], obj2));
assertSame(obj2, tree.remove(new float[2]));
assertNull(tree.remove(new float[2]));
}
@Test
public void test3DTreeBasicProximity() {
SpaceTree<Object> tree = new SpaceTree<>(3);
Object obj1 = new Object();
Object obj2 = new Object();
float[] location1 = {0f, 0f, 0f};
float[] location2 = {10f, 10f, 10f};
tree.add(location1, obj1);
tree.add(location2, obj2);
assertSame(obj1, tree.findNearest(new float[]{3f, 3f, 3f}).value);
assertSame(obj2, tree.findNearest(new float[]{100f, 100f, 0f}).value);
float[] location3 = {5f, 5f, 5f};
Object obj3 = new Object();
tree.add(location3, obj3);
assertSame(obj3, tree.findNearest(new float[]{3f, 3f, 3f}).value);
assertSame(obj2, tree.findNearest(new float[]{100f, 100f, 0f}).value);
}
@Test
public void test3DProximityTest() {
SpaceTree<Object> tree = new SpaceTree<>(3);
Object[] objects = {new Object(), new Object(), new Object(), new Object(), new Object(), new Object()};
float[][] locations = {{0f, 0f, 0f}, {0f, 0f, 1f}, {0f, 0f, 2f}, {0f, 0f, 3f}, {0f, 0f, 4f}, {0f, 0f, 5f}};
for (int i = 0; i < objects.length; i++) {
tree.add(locations[i], objects[i]);
}
float delta = 0.0000001f;
for (int i = 0; i < objects.length; i++) {
DimensionalMap.Entry<Object> nearest = tree.findNearest(locations[i]);
assertSame(objects[i], nearest.value);
assertEquals(0f, nearest.distance, delta);
}
DimensionalMap.Entry<Object> nearestOne = tree.findNearest(new float[]{0f, 0f, -1f});
assertSame(objects[0], nearestOne.value);
assertEquals(1f, nearestOne.distance, delta);
DimensionalMap.Entry<Object> nearestRoot = tree.findNearest(new float[]{0f, 1f, 6f});
assertSame(objects[5], nearestRoot.value);
assertEquals((float) Math.sqrt(2), nearestRoot.distance, delta);
assertNull(tree.findNearest(new float[]{0f, 0f, -1f}, 0.5f));
Collection<DimensionalMap.Entry<Object>> nearestTwo = tree.findNearest(new float[]{0f, 0f, 0f}, 2);
assertEquals(2, nearestTwo.size());
Iterator<DimensionalMap.Entry<Object>> nearestTwoIterator = nearestTwo.iterator();
DimensionalMap.Entry<Object> firstNearest = nearestTwoIterator.next();
DimensionalMap.Entry<Object> secondNearest = nearestTwoIterator.next();
assertSame(objects[0], firstNearest.value);
assertSame(objects[1], secondNearest.value);
assertEquals(0, firstNearest.distance, delta);
assertEquals(1, secondNearest.distance, delta);
Collection<DimensionalMap.Entry<Object>> nearestThree = tree.findNearest(new float[]{0f, 0f, 5f}, 3, 1f);
assertEquals(2, nearestThree.size());
Iterator<DimensionalMap.Entry<Object>> nearestThreeIterator = nearestThree.iterator();
firstNearest = nearestThreeIterator.next();
secondNearest = nearestThreeIterator.next();
assertSame(objects[5], firstNearest.value);
assertSame(objects[4], secondNearest.value);
assertEquals(0, firstNearest.distance, delta);
assertEquals(1, secondNearest.distance, delta);
}
@Test
public void testSearchDuplicationByDistance() {
SpaceTree<Object> tree = new SpaceTree<>(3);
Object[] objects = {new Object(), new Object(), new Object(), new Object(), new Object(), new Object()};
float[][] locations = {{0f, 0f, 0f}, {0f, 0f, 1f}, {0f, 0f, 2f}, {0f, 0f, 3f}, {0f, 0f, 4f}, {0f, 0f, 5f}};
for (int i = 0; i < objects.length; i++) {
tree.add(locations[i], objects[i]);
}
float delta = 0.0000001f;
Collection<DimensionalMap.Entry<Object>> nearest = tree.findNearest(locations[2], 3);
assertEquals(3, nearest.size());
Iterator<DimensionalMap.Entry<Object>> nearestIterator = nearest.iterator();
DimensionalMap.Entry<Object> firstNearest = nearestIterator.next();
DimensionalMap.Entry<Object> secondNearest = nearestIterator.next();
DimensionalMap.Entry<Object> thirdNearest = nearestIterator.next();
assertSame(objects[2], firstNearest.value);
assertTrue(objects[1] == secondNearest.value || objects[3] == secondNearest.value);
assertTrue(objects[1] == thirdNearest.value || objects[3] == thirdNearest.value);
assertNotSame(secondNearest.value, thirdNearest.value);
assertEquals(0, firstNearest.distance, delta);
assertEquals(1, secondNearest.distance, delta);
assertEquals(1, thirdNearest.distance, delta);
}
}