1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.telephony.CbGeoUtils;
22 import android.telephony.CbGeoUtils.Circle;
23 import android.telephony.CbGeoUtils.Geometry;
24 import android.telephony.CbGeoUtils.LatLng;
25 import android.telephony.CbGeoUtils.Polygon;
26 
27 import org.junit.Test;
28 
29 import java.util.Arrays;
30 import java.util.List;
31 
32 public class CbGeoUtilsTest {
33     @Test
testDistanceBetweenTwoLatLng()34     public void testDistanceBetweenTwoLatLng() {
35         LatLng latlng1 = new LatLng(37.428402, -122.084238);
36         LatLng latlng2 = new LatLng(37.399525, -121.946445);
37         double distInMeter = latlng1.distance(latlng2);
38         assertThat(distInMeter).isWithin(0.1).of(12586.1);
39     }
40 
41     @Test
testParseLatLngFromString()42     public void testParseLatLngFromString() {
43         LatLng latlng = CbGeoUtils.parseLatLngFromString("-80.1234, 179.5678");
44         assertThat(latlng.lat).isWithin(CbGeoUtils.EPS).of(-80.1234);
45         assertThat(latlng.lng).isWithin(CbGeoUtils.EPS).of(179.5678);
46     }
47 
48     @Test
testEncodeGeometries()49     public void testEncodeGeometries() {
50         List<Geometry> geo = Arrays.asList(
51                 new Polygon(Arrays.asList(
52                         new LatLng(11.11, 22.22),
53                         new LatLng(33.33, 44.44),
54                         new LatLng(55.55, -56.0))),
55                 new Circle(new LatLng(15.123, 123.456), 314));
56 
57         // Encode a list of geometry objects.
58         String encodedStr = CbGeoUtils.encodeGeometriesToString(geo);
59 
60         // Decode and verify the geometry objects.
61         List<Geometry> decodedGeo = CbGeoUtils.parseGeometriesFromString(encodedStr);
62         assertThat(decodedGeo.size()).isEqualTo(2);
63 
64         // The first one is polygon with three vertexes
65         assertThat(geo.get(0)).isInstanceOf(CbGeoUtils.Polygon.class);
66         CbGeoUtils.Polygon polygon = (Polygon) geo.get(0);
67         List<LatLng> vertexes = polygon.getVertices();
68         assertThat(vertexes.size()).isEqualTo(3);
69         LatLng p = vertexes.get(0);
70         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(11.11);
71         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(22.22);
72         p = vertexes.get(1);
73         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(33.33);
74         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(44.44);
75         p = vertexes.get(2);
76         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(55.55);
77         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(-56.0);
78 
79         // THe second one is circle.
80         assertThat(geo.get(1)).isInstanceOf(CbGeoUtils.Circle.class);
81         Circle circle = (Circle) geo.get(1);
82         p = circle.getCenter();
83         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(15.123);
84         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(123.456);
85         assertThat(circle.getRadius()).isWithin(CbGeoUtils.EPS).of(314);
86     }
87 
88     @Test
testParseGeometriesFromString()89     public void testParseGeometriesFromString() {
90         String geometriesStr =
91                 "polygon|11.11,22.22|33.33, 44.44| 55.55, -56.0; circle|15.123, 123.456|314";
92         List<Geometry> geo = CbGeoUtils.parseGeometriesFromString(geometriesStr);
93 
94         assertThat(geo.size()).isEqualTo(2);
95 
96         // The first one is polygon with three vertexes
97         assertThat(geo.get(0)).isInstanceOf(CbGeoUtils.Polygon.class);
98         CbGeoUtils.Polygon polygon = (Polygon) geo.get(0);
99         List<LatLng> vertexes = polygon.getVertices();
100         assertThat(vertexes.size()).isEqualTo(3);
101         LatLng p = vertexes.get(0);
102         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(11.11);
103         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(22.22);
104         p = vertexes.get(1);
105         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(33.33);
106         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(44.44);
107         p = vertexes.get(2);
108         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(55.55);
109         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(-56.0);
110 
111         // THe second one is circle.
112         assertThat(geo.get(1)).isInstanceOf(CbGeoUtils.Circle.class);
113         Circle circle = (Circle) geo.get(1);
114         p = circle.getCenter();
115         assertThat(p.lat).isWithin(CbGeoUtils.EPS).of(15.123);
116         assertThat(p.lng).isWithin(CbGeoUtils.EPS).of(123.456);
117         assertThat(circle.getRadius()).isWithin(CbGeoUtils.EPS).of(314);
118     }
119 
120     @Test
testPointInPolygon()121     public void testPointInPolygon() {
122         List<LatLng> vertex = Arrays.asList(
123                 new LatLng(-1, 0),
124                 new LatLng(0, 1),
125                 new LatLng(1, 0),
126                 new LatLng(0, -1));
127         Polygon polygon = new Polygon(vertex);
128 
129         assertThat(polygon.contains(new LatLng(0, 0))).isTrue();
130 
131         assertThat(polygon.contains(new LatLng(0.5, 0.5))).isTrue();
132 
133         assertThat(polygon.contains(new LatLng(-2, -1))).isFalse();
134 
135         assertThat(polygon.contains(new LatLng(1.0001, 1.0001))).isFalse();
136     }
137 
138     @Test
testPointInPolygon_crossing180thMeridian()139     public void testPointInPolygon_crossing180thMeridian() {
140         List<LatLng> vertices = Arrays.asList(
141                 new LatLng(68.7153, 176.76038),
142                 new LatLng(68.69982, -179.61491),
143                 new LatLng(68.09107, -177.87357),
144                 new LatLng(67.51155, -179.73498),
145                 new LatLng(66.69957, -178.76818),
146                 new LatLng(66.7126, 177.43054),
147                 new LatLng(67.95902, 178.33927));
148 
149         Polygon polygon = new Polygon(vertices);
150 
151         // Verify the points are inside the polygon(manually check in google map).
152         assertThat(polygon.contains(new LatLng(68.65294, 177.16205))).isTrue();
153         assertThat(polygon.contains(new LatLng(68.60522, 178.83294))).isTrue();
154         assertThat(polygon.contains(new LatLng(68.63098, -179.90943))).isTrue();
155         assertThat(polygon.contains(new LatLng(67.51219, -179.74427))).isTrue();
156         assertThat(polygon.contains(new LatLng(67.91933, 179.46802))).isTrue();
157 
158         // Verify the points are outside the polygon(manually check in google map).
159         assertThat(polygon.contains(new LatLng(67.50498, -179.48277))).isFalse();
160         assertThat(polygon.contains(new LatLng(67.95463, 178.23206))).isFalse();
161     }
162 
163     @Test
testPointInPolygon_crossing0thMeridian()164     public void testPointInPolygon_crossing0thMeridian() {
165         List<LatLng> vertices = Arrays.asList(
166                 new LatLng(51.79327, -1.00339),
167                 new LatLng(51.79327, 1.00339),
168                 new LatLng(49.79327, 1.00339),
169                 new LatLng(49.79327, -2.1234));
170 
171         Polygon polygon = new Polygon(vertices);
172 
173         // Verify the points are inside the polygon(manually check on google map).
174         assertThat(polygon.contains(new LatLng(51.78091, 0.97431))).isTrue();
175         assertThat(polygon.contains(new LatLng(49.97102, 0.72206))).isTrue();
176         assertThat(polygon.contains(new LatLng(50.82538, -0.17881))).isTrue();
177         assertThat(polygon.contains(new LatLng(51.50735, -0.12775))).isTrue();
178 
179         // Verify the points are outside the polygon(manually check on google map).
180         assertThat(polygon.contains(new LatLng(51.28268, 1.06951))).isFalse();
181         assertThat(polygon.contains(new LatLng(50.30352, -1.94073))).isFalse();
182         assertThat(polygon.contains(new LatLng(51.74758, -1.27057))).isFalse();
183     }
184 
185     @Test
testPointInCircle()186     public void testPointInCircle() {
187         Circle circle = new Circle(new LatLng(37.42331, -122.08636), 500);
188 
189         // ~ 307 meters
190         assertThat(circle.contains(new LatLng(37.42124, -122.08405))).isTrue();
191 
192         // ~ 451 meters
193         assertThat(circle.contains(new LatLng(37.42093, -122.08222))).isTrue();
194 
195         // ~ 622 meters
196         assertThat(circle.contains(new LatLng(37.41807, -122.08389))).isFalse();
197     }
198 }
199