package org.osm2world.core.math.algorithms;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import org.junit.Test;
import org.osm2world.core.math.SimplePolygonXZ;
import org.osm2world.core.math.TriangleXZ;
import org.osm2world.core.math.VectorXZ;
public class EarClippingTriangulationTest {
private static final VectorXZ outlineA0 = new VectorXZ(-1.1f, -1.1f);
private static final VectorXZ outlineA1 = new VectorXZ(-1.1f, 1.1f);
private static final VectorXZ outlineA2 = new VectorXZ(1.1f, 1.1f);
private static final VectorXZ outlineA3 = new VectorXZ(1.1f, -1.1f);
private static final VectorXZ outlineA4 = new VectorXZ(0f, 1f);
private static final List<VectorXZ> outlineA = Arrays.asList(
outlineA0, outlineA1, outlineA2, outlineA3, outlineA0
);
private static final List<VectorXZ> outlineB = Arrays.asList(
outlineA0, outlineA1, outlineA2, outlineA3, outlineA4, outlineA0
);
private static final SimplePolygonXZ holeA = new SimplePolygonXZ(Arrays.asList(
new VectorXZ(0, 0f),
new VectorXZ(1f, 0f),
new VectorXZ(0f, 1f),
new VectorXZ(0, 0f)
));
private static final SimplePolygonXZ holeB = new SimplePolygonXZ(Arrays.asList(
new VectorXZ(0.6f, 0.6f),
new VectorXZ(0.6f, 0f),
new VectorXZ(0f, 0.6f),
new VectorXZ(0.6f, 0.6f)
));
@Test
public void testFindVisibleOutlineVertex1() {
assertNotNull(EarClippingTriangulationUtil.findVisibleOutlineVertex(
outlineA, new VectorXZ(0.55f, 0.55f),
Collections.<SimplePolygonXZ>emptyList()));
}
@Test
public void testFindVisibleOutlineVertex2() {
assertEquals(outlineA2, outlineA.get(
EarClippingTriangulationUtil.findVisibleOutlineVertex(
outlineA, new VectorXZ(0.55f, 0.55f),
Arrays.asList(holeA))));
}
@Test
public void testFindVisibleOutlineVertex3() {
assertNull(
EarClippingTriangulationUtil.findVisibleOutlineVertex(
outlineA, new VectorXZ(0.55f, 0.55f),
Arrays.asList(holeA, holeB)));
}
/** rearrange, no invert */
@Test
public void testRearrangeOutline1() {
List<VectorXZ> newOutline =
EarClippingTriangulationUtil.rearrangeOutline(outlineA, 3, false);
assertSame(5, newOutline.size());
assertEquals(outlineA3, newOutline.get(0));
assertEquals(outlineA0, newOutline.get(1));
assertEquals(outlineA1, newOutline.get(2));
assertEquals(outlineA2, newOutline.get(3));
assertEquals(outlineA3, newOutline.get(4));
}
/** rearrange, invert */
@Test
public void testRearrangeOutline2() {
List<VectorXZ> newOutline =
EarClippingTriangulationUtil.rearrangeOutline(outlineA, 3, true);
assertSame(5, newOutline.size());
assertEquals(outlineA3, newOutline.get(0));
assertEquals(outlineA2, newOutline.get(1));
assertEquals(outlineA1, newOutline.get(2));
assertEquals(outlineA0, newOutline.get(3));
assertEquals(outlineA3, newOutline.get(4));
}
/** no invert, same start */
@Test
public void testRearrangeOutline3() {
List<VectorXZ> newOutline =
EarClippingTriangulationUtil.rearrangeOutline(outlineA, 0, false);
assertSame(5, newOutline.size());
assertEquals(outlineA0, newOutline.get(0));
assertEquals(outlineA1, newOutline.get(1));
assertEquals(outlineA2, newOutline.get(2));
assertEquals(outlineA3, newOutline.get(3));
assertEquals(outlineA0, newOutline.get(4));
}
/** invert, same start */
@Test
public void testRearrangeOutline4() {
List<VectorXZ> newOutline =
EarClippingTriangulationUtil.rearrangeOutline(outlineA, 0, true);
assertSame(5, newOutline.size());
assertEquals(outlineA0, newOutline.get(0));
assertEquals(outlineA3, newOutline.get(1));
assertEquals(outlineA2, newOutline.get(2));
assertEquals(outlineA1, newOutline.get(3));
assertEquals(outlineA0, newOutline.get(4));
}
@Test
public void testInsertVertexInPolygonOutline() {
VectorXZ point = new VectorXZ(0.55f, 0.55f);
List<VectorXZ> newOutline = new LinkedList<VectorXZ>(outlineA);
EarClippingTriangulationUtil.insertVertexInPolygonOutline(newOutline, point);
assertSame(7, newOutline.size());
assertTrue(newOutline.contains(point));
assertEquals(newOutline.get(newOutline.indexOf(point) - 1),
newOutline.get(newOutline.indexOf(point) + 1));
}
@Test
public void testInsertHoleInPolygonOutline() {
List<VectorXZ> newOutline = new LinkedList<VectorXZ>(outlineA);
EarClippingTriangulationUtil.insertHoleInPolygonOutline(newOutline, holeB, Arrays.asList(holeA));
assertSame(outlineA.size() + holeB.getVertexLoop().size() + 1,
newOutline.size());
for (VectorXZ innerVertex : holeB.getVertexLoop()) {
assertTrue(newOutline.contains(innerVertex));
}
}
@Test
public void testTriangulateSimplePolygon() {
List<TriangleXZ> triangles = new ArrayList<TriangleXZ>(
EarClippingTriangulationUtil.triangulateSimplePolygon(new ArrayList<VectorXZ>(outlineA)));
assertSame(triangles.size(), 2);
Collection<VectorXZ> vsT0 =
Arrays.asList(triangles.get(0).v1, triangles.get(0).v2, triangles.get(0).v3);
Collection<VectorXZ> vsT1 =
Arrays.asList(triangles.get(1).v1, triangles.get(1).v2, triangles.get(1).v3);
if (vsT0.contains(outlineA0) && vsT0.contains(outlineA1) && vsT0.contains(outlineA2)) {
assertTrue(vsT1.contains(outlineA0) && vsT1.contains(outlineA3) && vsT1.contains(outlineA2));
} else if (vsT0.contains(outlineA1) && vsT0.contains(outlineA2) && vsT0.contains(outlineA3)) {
assertTrue(vsT1.contains(outlineA1) && vsT1.contains(outlineA0) && vsT1.contains(outlineA3));
} else if (vsT0.contains(outlineA2) && vsT0.contains(outlineA3) && vsT0.contains(outlineA0)) {
assertTrue(vsT1.contains(outlineA2) && vsT1.contains(outlineA1) && vsT1.contains(outlineA0));
} else if (vsT0.contains(outlineA3) && vsT0.contains(outlineA0) && vsT0.contains(outlineA1)) {
assertTrue(vsT1.contains(outlineA3) && vsT1.contains(outlineA2) && vsT1.contains(outlineA1));
} else {
fail();
}
}
@Test
public void testIsConvex1() {
for (int i=0; i < outlineA.size(); i++) {
assertTrue(EarClippingTriangulationUtil.isConvex(i, outlineA));
}
}
@Test
public void testIsEarTip1() {
for (int i=0; i < outlineA.size(); i++) {
assertTrue(EarClippingTriangulationUtil.isEarTip(i, outlineA));
}
}
@Test
public void testIsConvex2() {
List<VectorXZ> outlineNoDup = outlineB.subList(0, outlineB.size() - 1);
for (int i=0; i < outlineNoDup.size(); i++) {
if (i == 4) {
assertFalse(EarClippingTriangulationUtil.isConvex(i, outlineNoDup));
} else {
assertTrue("at " + i, EarClippingTriangulationUtil.isConvex(i, outlineNoDup));
}
}
}
@Test
public void testIsEarTip2() {
List<VectorXZ> outlineNoDup = outlineB.subList(0, outlineB.size() - 1);
assertTrue(EarClippingTriangulationUtil.isEarTip(0, outlineNoDup));
assertFalse(EarClippingTriangulationUtil.isEarTip(1, outlineNoDup));
assertFalse(EarClippingTriangulationUtil.isEarTip(2, outlineNoDup));
assertTrue(EarClippingTriangulationUtil.isEarTip(3, outlineNoDup));
assertFalse(EarClippingTriangulationUtil.isEarTip(4, outlineNoDup));
}
}