/* * Copyright (c) 2016 Vivid Solutions. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Eclipse Distribution License v. 1.0 which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * * http://www.eclipse.org/org/documents/edl-v10.php. */ package org.locationtech.jts.algorithm; import org.locationtech.jts.geom.Coordinate; import junit.framework.TestCase; import junit.textui.TestRunner; /** * Tests failure cases of CGAlgorithms.computeOrientation * @version 1.7 */ public class OrientationIndexFailureTest extends TestCase { public static void main(String args[]) { TestRunner.run(OrientationIndexFailureTest.class); } public OrientationIndexFailureTest(String name) { super(name); } /** * This is included to confirm this test is operating correctly * @throws Exception */ public void testSanity() throws Exception { assertTrue(OrientationIndexTest.isAllOrientationsEqual( OrientationIndexTest.getCoordinates("LINESTRING ( 0 0, 0 1, 1 1)"))); } public void testBadCCW() throws Exception { // this case fails because subtraction of small from large loses precision Coordinate[] pts = { new Coordinate(1.4540766091864998, -7.989685402102996), new Coordinate(23.131039116367354, -7.004368924503866), new Coordinate(1.4540766091865, -7.989685402102996), }; checkOrientation(pts); } public void testBadCCW2() throws Exception { // this case fails because subtraction of small from large loses precision Coordinate[] pts = { new Coordinate(219.3649559090992, 140.84159161824724), new Coordinate(168.9018919682399, -5.713787599646864), new Coordinate(186.80814046338352, 46.28973405831556), }; checkOrientation(pts); } public void testBadCCW3() throws Exception { // this case fails because subtraction of small from large loses precision Coordinate[] pts = { new Coordinate(279.56857838488514, -186.3790522565901), new Coordinate(-20.43142161511487, 13.620947743409914), new Coordinate(0, 0) }; checkOrientation(pts); } public void testBadCCW4() throws Exception { // from JTS list - 5/15/2012 strange case for the GeometryNoder Coordinate[] pts = { new Coordinate(-26.2, 188.7), new Coordinate(37.0, 290.7), new Coordinate(21.2, 265.2) }; checkOrientation(pts); } public void testBadCCW5() throws Exception { // from JTS list - 6/15/2012 another case from Tomas Fa Coordinate[] pts = { new Coordinate(-5.9, 163.1), new Coordinate(76.1, 250.7), new Coordinate(14.6, 185) //new Coordinate(96.6, 272.6) }; checkOrientation(pts); } public void testBadCCW7() throws Exception { // from JTS list - 6/26/2012 another case from Tomas Fa Coordinate[] pts = { new Coordinate(-0.9575, 0.4511), new Coordinate(-0.9295, 0.3291), new Coordinate(-0.8945, 0.1766) }; checkDD(pts, true); checkShewchuk(pts, false); checkOriginalJTS(pts, false); } public void testBadCCW7_2() throws Exception { // from JTS list - 6/26/2012 another case from Tomas Fa // scale to integers - all methods work on this Coordinate[] pts = { new Coordinate(-9575, 4511), new Coordinate(-9295, 3291), new Coordinate(-8945, 1766) }; checkDD(pts, true); checkShewchuk(pts, true); checkOriginalJTS(pts, true); } public void testBadCCW6() throws Exception { // from JTS Convex Hull "Almost collinear" unit test Coordinate[] pts = { new Coordinate(-140.8859438214298, 140.88594382142983), new Coordinate(-57.309236848216706, 57.30923684821671), new Coordinate(-190.9188309203678, 190.91883092036784) }; checkOrientation(pts); } /** * Shorthand method for most common case, * where the high-precision methods work but JTS Robust algorithm fails. * @param pts */ void checkOrientation(Coordinate[] pts) { // this should succeed checkDD(pts, true); checkShewchuk(pts, true); // this is expected to fail checkOriginalJTS(pts, false); } private void checkShewchuk(Coordinate[] pts, boolean expected) { assertTrue("Shewchuk", expected == isAllOrientationsEqualSD(pts)); } private void checkOriginalJTS(Coordinate[] pts, boolean expected) { assertTrue("JTS Robust FAIL", expected == OrientationIndexTest.isAllOrientationsEqual(pts)); } private void checkDD(Coordinate[] pts, boolean expected) { assertTrue("DD", expected == isAllOrientationsEqualDD(pts)); } public static boolean isAllOrientationsEqual( double p0x, double p0y, double p1x, double p1y, double p2x, double p2y) { Coordinate[] pts = { new Coordinate(p0x, p0y), new Coordinate(p1x, p1y), new Coordinate(p2x, p2y) }; if (! isAllOrientationsEqualDD(pts)) throw new IllegalStateException("High-precision orientation computation FAILED"); return OrientationIndexTest.isAllOrientationsEqual(pts); } public static boolean isAllOrientationsEqualDD(Coordinate[] pts) { int orient0 = CGAlgorithmsDD.orientationIndex(pts[0], pts[1], pts[2]); int orient1 = CGAlgorithmsDD.orientationIndex(pts[1], pts[2], pts[0]); int orient2 = CGAlgorithmsDD.orientationIndex(pts[2], pts[0], pts[1]); return orient0 == orient1 && orient0 == orient2; } public static boolean isAllOrientationsEqualSD(Coordinate[] pts) { int orient0 = ShewchuksDeterminant.orientationIndex(pts[0], pts[1], pts[2]); int orient1 = ShewchuksDeterminant.orientationIndex(pts[1], pts[2], pts[0]); int orient2 = ShewchuksDeterminant.orientationIndex(pts[2], pts[0], pts[1]); return orient0 == orient1 && orient0 == orient2; } }