/* * Copyright 2006 Google Inc. * * 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 com.google.common.geometry; import com.google.common.collect.Lists; import junit.framework.Assert; import java.util.List; /** * Tests for {@link S2Polyline}. * */ public strictfp class S2PolylineTest extends GeometryTestCase { @Override public void setUp() { super.setUp(); } public void testBasic() { List vertices = Lists.newArrayList(); S2Polyline empty = new S2Polyline(vertices); assertEquals(empty.getRectBound(), S2LatLngRect.empty()); } public void testGetLengthCentroid() { // Construct random great circles and divide them randomly into segments. // Then make sure that the length and centroid are correct. Note that // because of the way the centroid is computed, it does not matter how // we split the great circle into segments. for (int i = 0; i < 100; ++i) { // Choose a coordinate frame for the great circle. S2Point x = randomPoint(); S2Point y = S2Point.normalize(S2Point.crossProd(x, randomPoint())); S2Point z = S2Point.normalize(S2Point.crossProd(x, y)); List vertices = Lists.newArrayList(); for (double theta = 0; theta < 2 * S2.M_PI; theta += Math.pow(rand.nextDouble(), 10)) { S2Point p = S2Point.add(S2Point.mul(x, Math.cos(theta)), S2Point.mul(y, Math.sin(theta))); if (vertices.isEmpty() || !p.equals(vertices.get(vertices.size() - 1))) { vertices.add(p); } } // Close the circle. vertices.add(vertices.get(0)); S2Polyline line = new S2Polyline(vertices); S1Angle length = line.getArclengthAngle(); assertTrue(Math.abs(length.radians() - 2 * S2.M_PI) < 2e-14); } } public void testMayIntersect() { List vertices = Lists.newArrayList(); vertices.add(S2Point.normalize(new S2Point(1, -1.1, 0.8))); vertices.add(S2Point.normalize(new S2Point(1, -0.8, 1.1))); S2Polyline line = new S2Polyline(vertices); for (int face = 0; face < 6; ++face) { S2Cell cell = S2Cell.fromFacePosLevel(face, (byte) 0, 0); assertEquals(line.mayIntersect(cell), (face & 1) == 0); } } public void testInterpolate() { List vertices = Lists.newArrayList(); vertices.add(new S2Point(1, 0, 0)); vertices.add(new S2Point(0, 1, 0)); vertices.add(S2Point.normalize(new S2Point(0, 1, 1))); vertices.add(new S2Point(0, 0, 1)); S2Polyline line = new S2Polyline(vertices); assertEquals(line.interpolate(-0.1), vertices.get(0)); assertTrue(S2.approxEquals( line.interpolate(0.1), S2Point.normalize(new S2Point(1, Math.tan(0.2 * S2.M_PI / 2), 0)))); assertTrue(S2.approxEquals(line.interpolate(0.25), S2Point.normalize(new S2Point(1, 1, 0)))); assertEquals(line.interpolate(0.5), vertices.get(1)); assertEquals(line.interpolate(0.75), vertices.get(2)); assertEquals(line.interpolate(1.1), vertices.get(3)); } public void testEqualsAndHashCode() { List vertices = Lists.newArrayList(); vertices.add(new S2Point(1, 0, 0)); vertices.add(new S2Point(0, 1, 0)); vertices.add(S2Point.normalize(new S2Point(0, 1, 1))); vertices.add(new S2Point(0, 0, 1)); S2Polyline line1 = new S2Polyline(vertices); S2Polyline line2 = new S2Polyline(vertices); checkEqualsAndHashCodeMethods(line1, line2, true); List moreVertices = Lists.newLinkedList(vertices); moreVertices.remove(0); S2Polyline line3 = new S2Polyline(moreVertices); checkEqualsAndHashCodeMethods(line1, line3, false); checkEqualsAndHashCodeMethods(line1, null, false); checkEqualsAndHashCodeMethods(line1, "", false); } public void testProject() { List latLngs = Lists.newArrayList(); latLngs.add(S2LatLng.fromDegrees(0, 0).toPoint()); latLngs.add(S2LatLng.fromDegrees(0, 1).toPoint()); latLngs.add(S2LatLng.fromDegrees(0, 2).toPoint()); latLngs.add(S2LatLng.fromDegrees(1, 2).toPoint()); S2Polyline line = new S2Polyline(latLngs); int edgeIndex = -1; S2Point testPoint = null; testPoint = S2LatLng.fromDegrees(0.5, -0.5).toPoint(); edgeIndex = line.getNearestEdgeIndex(testPoint); assertTrue(S2.approxEquals( line.projectToEdge(testPoint, edgeIndex), S2LatLng.fromDegrees(0, 0).toPoint())); assertEquals(0, edgeIndex); testPoint = S2LatLng.fromDegrees(0.5, 0.5).toPoint(); edgeIndex = line.getNearestEdgeIndex(testPoint); assertTrue(S2.approxEquals( line.projectToEdge(testPoint, edgeIndex), S2LatLng.fromDegrees(0, 0.5).toPoint())); assertEquals(0, edgeIndex); testPoint = S2LatLng.fromDegrees(0.5, 1).toPoint(); edgeIndex = line.getNearestEdgeIndex(testPoint); assertTrue(S2.approxEquals( line.projectToEdge(testPoint, edgeIndex), S2LatLng.fromDegrees(0, 1).toPoint())); assertEquals(0, edgeIndex); testPoint = S2LatLng.fromDegrees(-0.5, 2.5).toPoint(); edgeIndex = line.getNearestEdgeIndex(testPoint); assertTrue(S2.approxEquals( line.projectToEdge(testPoint, edgeIndex), S2LatLng.fromDegrees(0, 2).toPoint())); assertEquals(1, edgeIndex); testPoint = S2LatLng.fromDegrees(2, 2).toPoint(); edgeIndex = line.getNearestEdgeIndex(testPoint); assertTrue(S2.approxEquals( line.projectToEdge(testPoint, edgeIndex), S2LatLng.fromDegrees(1, 2).toPoint())); assertEquals(2, edgeIndex); } /** * Utility for testing equals() and hashCode() results at once. * Tests that lhs.equals(rhs) matches expectedResult, as well as * rhs.equals(lhs). Also tests that hashCode() return values are * equal if expectedResult is true. (hashCode() is not tested if * expectedResult is false, as unequal objects can have equal hashCodes.) * * @param lhs An Object for which equals() and hashCode() are to be tested. * @param rhs As lhs. * @param expectedResult True if the objects should compare equal, * false if not. */ private static void checkEqualsAndHashCodeMethods(Object lhs, Object rhs, boolean expectedResult) { if ((lhs == null) && (rhs == null)) { Assert.assertTrue( "Your check is dubious...why would you expect null != null?", expectedResult); return; } if ((lhs == null) || (rhs == null)) { Assert.assertFalse( "Your check is dubious...why would you expect an object " + "to be equal to null?", expectedResult); } if (lhs != null) { assertEquals(expectedResult, lhs.equals(rhs)); } if (rhs != null) { assertEquals(expectedResult, rhs.equals(lhs)); } if (expectedResult) { String hashMessage = "hashCode() values for equal objects should be the same"; Assert.assertTrue(hashMessage, lhs.hashCode() == rhs.hashCode()); } } }