package org.osm2world; import static java.util.Arrays.asList; import static org.junit.Assert.*; import static org.osm2world.core.test.TestUtil.assertAlmostEquals; import java.util.ArrayList; import java.util.List; import java.util.Random; import org.junit.Test; import org.osm2world.core.map_elevation.creation.DelaunayTriangulation; import org.osm2world.core.map_elevation.creation.DelaunayTriangulation.DelaunayTriangle; import org.osm2world.core.math.AxisAlignedBoundingBoxXZ; import org.osm2world.core.math.VectorXYZ; import org.osm2world.core.math.VectorXZ; public class DelaunayTriangulationTest { private static final double SIZE = 100; @Test public void testInsert() { List<Random> RANDOMS = asList( new Random(1), new Random(20), new Random(300)); for (Random random : RANDOMS) { AxisAlignedBoundingBoxXZ bounds = new AxisAlignedBoundingBoxXZ( -SIZE, -SIZE, +SIZE, +SIZE); DelaunayTriangulation triangulation = new DelaunayTriangulation(bounds); DelaunayTriangulation triangulation2 = new DelaunayTriangulation(bounds); List<VectorXYZ> points = new ArrayList<VectorXYZ>(); for (int insertCount = 0; insertCount < 100; insertCount++) { System.out.println(RANDOMS.indexOf(random) + ":" + insertCount); double x = (random.nextDouble() * 2 * SIZE) - SIZE; double z = (random.nextDouble() * 2 * SIZE) - SIZE; VectorXYZ point = new VectorXYZ(x, 0, z); points.add(point); // check whether undoing works triangulation2.probe(point.xz()); assertTriangulationsEqual(triangulation, triangulation2); // insert for real triangulation.insert(point); triangulation2.insert(point); assertTriangulationProperties(triangulation, points); } } } /** * asserts that two triangulations are equal */ private static void assertTriangulationsEqual( DelaunayTriangulation triangulation1, DelaunayTriangulation triangulation2) { for (DelaunayTriangle t1 : triangulation1.getTriangles()) { DelaunayTriangle twinTriangle = null; for (DelaunayTriangle t2 : triangulation2.getTriangles()) { if (t1.asTriangleXZ().equals(t2.asTriangleXZ())) { twinTriangle = t2; } } assertNotNull("must contain " + t1, twinTriangle); for (int i = 0; i <= 2; i++) { DelaunayTriangle n1 = t1.getNeighbor(i); DelaunayTriangle n2 = twinTriangle.getNeighbor(i); if (n1 == null && n2 == null) { continue; } else if (n1 != null && n2 != null && n1.asTriangleXZ().equals(n2.asTriangleXZ())) { continue; } else { fail(String.format("neighbor %d different: %s vs. %s", i, n1, n2)); } } } } /** * asserts that a triangulation confirms to a set of required properties */ private static void assertTriangulationProperties( DelaunayTriangulation triangulation, List<VectorXYZ> points) { for (DelaunayTriangle triangle : triangulation.getTriangles()) { /* check that neighborship relations are symmetric */ for (int i = 0; i <= 2; i++) { if (triangle.getNeighbor(i) != null) { int index = triangle.getNeighbor(i).indexOfNeighbor(triangle); assertTrue(0 <= index && index <= 2); } } /* * check that each triangle's vertices are on the * circumcircle, and all other points are outside it */ VectorXZ center = triangle.getCircumcircleCenter(); double radius = triangle.p0.distanceToXZ(center); assertAlmostEquals(radius, triangle.p1.distanceToXZ(center)); assertAlmostEquals(radius, triangle.p2.distanceToXZ(center)); for (VectorXYZ otherPoint : points) { if (triangle.p0 != otherPoint && triangle.p1 != otherPoint && triangle.p2 != otherPoint) { if (otherPoint.distanceToXZ(center) <= radius) { System.out.println(otherPoint); System.out.println(triangle); } assertTrue(otherPoint.distanceToXZ(center) > radius); } } } } }