blob: 9da9bcb9a58f508fe65497095979495796ea066d [file] [log] [blame]
/*
* 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<S2Point> 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<S2Point> 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<S2Point> 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<S2Point> 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<S2Point> 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<S2Point> 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<S2Point> 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());
}
}
}