package com.google.maps.android;
import com.google.android.gms.maps.model.LatLng;
import com.google.maps.android.PolyUtil;
import junit.framework.Assert;
import junit.framework.TestCase;
import java.lang.String;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
public class PolyUtilTest extends TestCase {
private static final String TEST_LINE = "_cqeFf~cjVf@p@fA}AtAoB`ArAx@hA`GbIvDiFv@gAh@t@X\\|@z@`@Z\\Xf@Vf@VpA\\tATJ@NBBkC";
private static void expectNearNumber(double expected, double actual, double epsilon) {
Assert.assertTrue(String.format("Expected %f to be near %f", actual, expected),
Math.abs(expected - actual) <= epsilon);
}
private static List<LatLng> makeList(double... coords) {
int size = coords.length / 2;
ArrayList<LatLng> list = new ArrayList<LatLng>(size);
for (int i = 0; i < size; ++i) {
list.add(new LatLng(coords[i + i], coords[i + i + 1]));
}
return list;
}
private static void containsCase(List<LatLng> poly, List<LatLng> yes, List<LatLng> no) {
for (LatLng point : yes) {
Assert.assertTrue(PolyUtil.containsLocation(point, poly, true));
Assert.assertTrue(PolyUtil.containsLocation(point, poly, false));
}
for (LatLng point : no) {
Assert.assertFalse(PolyUtil.containsLocation(point, poly, true));
Assert.assertFalse(PolyUtil.containsLocation(point, poly, false));
}
}
private static void onEdgeCase(boolean geodesic,
List<LatLng> poly, List<LatLng> yes, List<LatLng> no) {
for (LatLng point : yes) {
Assert.assertTrue(PolyUtil.isLocationOnEdge(point, poly, geodesic));
Assert.assertTrue(PolyUtil.isLocationOnPath(point, poly, geodesic));
}
for (LatLng point : no) {
Assert.assertFalse(PolyUtil.isLocationOnEdge(point, poly, geodesic));
Assert.assertFalse(PolyUtil.isLocationOnPath(point, poly, geodesic));
}
}
private static void onEdgeCase(List<LatLng> poly, List<LatLng> yes, List<LatLng> no) {
onEdgeCase(true, poly, yes, no);
onEdgeCase(false, poly, yes, no);
}
public void testOnEdge() {
// Empty
onEdgeCase(makeList(), makeList(), makeList(0, 0));
final double small = 5e-7; // About 5cm on equator, half the default tolerance.
final double big = 2e-6; // About 10cm on equator, double the default tolerance.
// Endpoints
onEdgeCase(makeList(1, 2), makeList(1, 2), makeList(3, 5));
onEdgeCase(makeList(1, 2, 3, 5), makeList(1, 2, 3, 5), makeList(0, 0));
// On equator.
onEdgeCase(makeList(0, 90, 0, 180),
makeList(0, 90-small, 0, 90+small, 0-small, 90, 0, 135, small, 135),
makeList(0, 90-big, 0, 0, 0, -90, big, 135));
// Ends on same latitude.
onEdgeCase(makeList(-45, -180, -45, -small),
makeList(-45, 180+small, -45, 180-small, -45-small, 180-small, -45, 0),
makeList(-45, big, -45, 180-big, -45+big, -90, -45, 90));
// Meridian.
onEdgeCase(makeList(-10, 30, 45, 30),
makeList(10, 30-small, 20, 30+small, -10-small, 30+small),
makeList(-10-big, 30, 10, -150, 0, 30-big));
// Slanted close to meridian, close to North pole.
onEdgeCase(makeList(0, 0, 90-small, 0+big),
makeList(1, 0+small, 2, 0-small, 90-small, -90, 90-small, 10),
makeList(-big, 0, 90-big, 180, 10, big));
// Arc > 120 deg.
onEdgeCase(makeList(0, 0, 0, 179.999),
makeList(0, 90, 0, small, 0, 179, small, 90),
makeList(0, -90, small, -100, 0, 180, 0, -big, 90, 0, -90, 180));
onEdgeCase(makeList(10, 5, 30, 15),
makeList(10+2*big, 5+big, 10+big, 5+big/2, 30-2*big, 15-big),
makeList(20, 10, 10-big, 5-big/2, 30+2*big, 15+big, 10+2*big, 5, 10, 5+big));
onEdgeCase(makeList(90-small, 0, 0, 180-small/2),
makeList(big, -180+small/2, big, 180-small/4, big, 180-small),
makeList(-big, -180+small/2, -big, 180, -big, 180-small));
// Reaching close to North pole.
onEdgeCase(true, makeList(80, 0, 80, 180-small),
makeList(90-small, -90, 90, -135, 80-small, 0, 80+small, 0),
makeList(80, 90, 79, big));
onEdgeCase(false, makeList(80, 0, 80, 180-small),
makeList(80-small, 0, 80+small, 0, 80, 90),
makeList(79, big, 90-small, -90, 90, -135));
}
public void testContainsLocation() {
// Empty.
containsCase(makeList(),
makeList(),
makeList(0, 0));
// One point.
containsCase(makeList(1, 2),
makeList(1, 2),
makeList(0, 0));
// Two points.
containsCase(makeList(1, 2, 3, 5),
makeList(1, 2, 3, 5),
makeList(0, 0, 40, 4));
// Some arbitrary triangle.
containsCase(makeList(0., 0., 10., 12., 20., 5.),
makeList(10., 12., 10, 11, 19, 5),
makeList(0, 1, 11, 12, 30, 5, 0, -180, 0, 90));
// Around North Pole.
containsCase(makeList(89, 0, 89, 120, 89, -120),
makeList(90, 0, 90, 180, 90, -90),
makeList(-90, 0, 0, 0));
// Around South Pole.
containsCase(makeList(-89, 0, -89, 120, -89, -120),
makeList(90, 0, 90, 180, 90, -90, 0, 0),
makeList(-90, 0, -90, 90));
// Over/under segment on meridian and equator.
containsCase(makeList(5, 10, 10, 10, 0, 20, 0, -10),
makeList(2.5, 10, 1, 0),
makeList(15, 10, 0, -15, 0, 25, -1, 0));
}
public void testDecodePath() {
List<LatLng> latLngs = PolyUtil.decode(TEST_LINE);
int expectedLength = 21;
Assert.assertEquals("Wrong length.", expectedLength, latLngs.size());
LatLng lastPoint = latLngs.get(expectedLength - 1);
expectNearNumber(37.76953, lastPoint.latitude, 1e-6);
expectNearNumber(-122.41488, lastPoint.longitude, 1e-6);
}
public void testEncodePath() {
List<LatLng> path = PolyUtil.decode(TEST_LINE);
String encoded = PolyUtil.encode(path);
Assert.assertEquals(TEST_LINE, encoded);
}
}