1 package org.apache.lucene.spatial;
3 import junit.framework.TestCase;
4 import org.apache.lucene.spatial.tier.InvalidGeoException;
8 * Licensed to the Apache Software Foundation (ASF) under one or more
9 * contributor license agreements. See the NOTICE file distributed with
10 * this work for additional information regarding copyright ownership.
11 * The ASF licenses this file to You under the Apache License, Version 2.0
12 * (the "License"); you may not use this file except in compliance with
13 * the License. You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
29 public class DistanceUtilsTest extends TestCase {
31 public void testBoxCorner() throws Exception {
32 double[] zero = new double[]{0, 0};
33 double[] zeroOne = new double[]{0, 1};
34 double[] oneOne = new double[]{1, 1};
35 double[] pt1 = new double[]{1.5, 110.3};
36 double[] result = DistanceUtils.vectorBoxCorner(zero, null, Math.sqrt(2), true);
37 assertEquals(1.0, result[0]);
38 assertEquals(1.0, result[1]);
40 result = DistanceUtils.vectorBoxCorner(zero, null, Math.sqrt(2), false);
41 assertEquals(-1.0, result[0]);
42 assertEquals(-1.0, result[1]);
44 result = DistanceUtils.vectorBoxCorner(oneOne, null, Math.sqrt(2), true);
45 assertEquals(2.0, result[0]);
46 assertEquals(2.0, result[1]);
48 result = DistanceUtils.vectorBoxCorner(zeroOne, null, Math.sqrt(2), true);
49 assertEquals(1.0, result[0]);
50 assertEquals(2.0, result[1]);
52 result = DistanceUtils.vectorBoxCorner(pt1, null, Math.sqrt(2), true);
53 assertEquals(2.5, result[0]);
54 assertEquals(111.3, result[1]);
56 result = DistanceUtils.vectorBoxCorner(pt1, null, Math.sqrt(2), false);
57 assertEquals(0.5, result[0]);
58 assertEquals(109.3, result[1]);
62 public void testNormLatLon() throws Exception {
66 public void testLatLonCorner() throws Exception {
67 double[] zero = new double[]{0, 0};
68 double[] zero45 = new double[]{0, DistanceUtils.DEG_45_AS_RADS};
70 // 00°38′09″N, 000°38′09″E
71 //Verify at http://www.movable-type.co.uk/scripts/latlong.html
72 result = DistanceUtils.latLonCorner(zero[0], zero[1], 100, null, true, DistanceUtils.EARTH_MEAN_RADIUS_KM);
73 assertEquals(0.63583 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
74 assertEquals(0.63583 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
76 result = DistanceUtils.latLonCornerDegs(zero[0], zero[1], 100, null, true, DistanceUtils.EARTH_MEAN_RADIUS_KM);
77 // 00°38′09″N, 000°38′09″E
78 assertEquals(0.63583, result[0], 0.001);
79 assertEquals(0.63583, result[1], 0.001);
81 result = DistanceUtils.latLonCornerDegs(zero[0], zero[1], 100, null, false, DistanceUtils.EARTH_MEAN_RADIUS_KM);
82 // 00°38′09″N, 000°38′09″E
83 assertEquals(-0.63583, result[0], 0.001);
84 assertEquals(-0.63583, result[1], 0.001);
86 //test some edge cases
87 //89°16′02″N, 060°12′35″E
88 result = DistanceUtils.latLonCornerDegs(89.0, 0, 100, null, true, DistanceUtils.EARTH_MEAN_RADIUS_KM);
89 assertEquals(89.26722, result[0], 0.001);
90 assertEquals(60.20972, result[1], 0.001);
92 result = DistanceUtils.latLonCornerDegs(0, -179.0, 100, null, true, DistanceUtils.EARTH_MEAN_RADIUS_KM);
93 assertEquals(0.63583, result[0], 0.001);
94 assertEquals(-178.36417, result[1], 0.001);
98 public void testPointBearing() throws Exception {
99 double[] zero = new double[]{0, 0};
100 double[] zero45 = new double[]{40 * DistanceUtils.DEGREES_TO_RADIANS, DistanceUtils.DEG_45_AS_RADS};
102 // 00°38′09″N, 000°38′09″E
103 //Verify at http://www.movable-type.co.uk/scripts/latlong.html
104 result = DistanceUtils.pointOnBearing(zero[0], zero[1], 100, DistanceUtils.DEG_45_AS_RADS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
105 assertEquals(0.63583 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
106 assertEquals(0.63583 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
108 //should be above the current point at 0.8994°,0.0000°
109 result = DistanceUtils.pointOnBearing(zero[0], zero[1], 100, 0, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
110 assertEquals(0.8994 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
111 assertEquals(0, result[1], 0.001);
113 result = DistanceUtils.pointOnBearing(zero[0], zero[1], 100, DistanceUtils.DEG_180_AS_RADS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
114 assertEquals(-0.8994 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
115 assertEquals(0, result[1], 0.001);
116 //0.7183°,0.5414° -- 37 deg bearing
117 result = DistanceUtils.pointOnBearing(zero[0], zero[1], 100, 37 * DistanceUtils.DEGREES_TO_RADIANS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
118 assertEquals(0.7183 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
119 assertEquals(0.5414 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
121 result = DistanceUtils.pointOnBearing(zero45[0], zero45[1], 100, DistanceUtils.DEG_45_AS_RADS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
123 assertEquals(40.6328 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
124 assertEquals(45.8381 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
126 result = DistanceUtils.pointOnBearing(1 * DistanceUtils.DEGREES_TO_RADIANS, 1 * DistanceUtils.DEGREES_TO_RADIANS, 100, DistanceUtils.DEG_90_AS_RADS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
128 assertEquals(0.9997 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
129 assertEquals(1.8994 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
131 result = DistanceUtils.pointOnBearing(-10 * DistanceUtils.DEGREES_TO_RADIANS, -150 * DistanceUtils.DEGREES_TO_RADIANS, 15, 205*DistanceUtils.DEGREES_TO_RADIANS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
132 //-10.1222°,-150.0578°
133 assertEquals(-10.1222 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
134 assertEquals(-150.0578 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
136 result = DistanceUtils.pointOnBearing(-10 * DistanceUtils.DEGREES_TO_RADIANS, -150 * DistanceUtils.DEGREES_TO_RADIANS, 200, 63*DistanceUtils.DEGREES_TO_RADIANS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
137 //-9.1797°,-148.3767°
138 assertEquals(-9.1797 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
139 assertEquals(-148.3767 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
141 result = DistanceUtils.pointOnBearing(-10 * DistanceUtils.DEGREES_TO_RADIANS, -150 * DistanceUtils.DEGREES_TO_RADIANS, 3000, 63*DistanceUtils.DEGREES_TO_RADIANS, null, DistanceUtils.EARTH_MEAN_RADIUS_KM);
143 assertEquals(2.7561 * DistanceUtils.DEGREES_TO_RADIANS, result[0], 0.001);
144 assertEquals(-126.1281 * DistanceUtils.DEGREES_TO_RADIANS, result[1], 0.001);
148 public void testVectorDistance() throws Exception {
149 double[] zero = new double[]{0, 0};
151 double[] zeroOne = new double[]{0, 1};
152 double[] oneZero = new double[]{1, 0};
153 double[] oneOne = new double[]{1, 1};
155 distance = DistanceUtils.vectorDistance(zero, zeroOne, 2);
156 assertEquals(1.0, distance);
157 distance = DistanceUtils.vectorDistance(zero, oneZero, 2);
158 assertEquals(1.0, distance);
159 distance = DistanceUtils.vectorDistance(zero, oneOne, 2);
160 assertEquals(Math.sqrt(2), distance, 0.001);
162 distance = DistanceUtils.squaredEuclideanDistance(zero, oneOne);
163 assertEquals(2, distance, 0.001);
166 public void testHaversine() throws Exception {
168 //compare to http://www.movable-type.co.uk/scripts/latlong.html
169 distance = DistanceUtils.haversine(0, 0, Math.PI / 4.0, Math.PI / 4.0, DistanceUtils.EARTH_MEAN_RADIUS_KM);
170 assertEquals(6672.0, distance, 0.5);
172 distance = DistanceUtils.haversine(0, 0, Math.toRadians(20), Math.toRadians(20), DistanceUtils.EARTH_MEAN_RADIUS_KM);
173 assertEquals(3112, distance, 0.5);
175 distance = DistanceUtils.haversine(0, 0, Math.toRadians(1), Math.toRadians(1), DistanceUtils.EARTH_MEAN_RADIUS_KM);
176 assertEquals(157.2, distance, 0.5);
178 //Try some around stuff
179 distance = DistanceUtils.haversine(Math.toRadians(1), Math.toRadians(-1),
180 Math.toRadians(1), Math.toRadians(1), DistanceUtils.EARTH_MEAN_RADIUS_KM);
181 assertEquals(222.4, distance, 0.5);
183 distance = DistanceUtils.haversine(Math.toRadians(89), Math.toRadians(-1),
184 Math.toRadians(89), Math.toRadians(179), DistanceUtils.EARTH_MEAN_RADIUS_KM);
185 assertEquals(222.4, distance, 0.5);
187 distance = DistanceUtils.haversine(Math.toRadians(89), Math.toRadians(-1),
188 Math.toRadians(49), Math.toRadians(179), DistanceUtils.EARTH_MEAN_RADIUS_KM);
189 assertEquals(4670, distance, 0.5);
191 distance = DistanceUtils.haversine(Math.toRadians(0), Math.toRadians(-179),
192 Math.toRadians(0), Math.toRadians(179), DistanceUtils.EARTH_MEAN_RADIUS_KM);
193 assertEquals(222.4, distance, 0.5);
197 public void testParse() throws Exception {
199 parse = DistanceUtils.parsePoint(null, "89.0,73.2", 2);
200 assertEquals(2, parse.length);
201 assertEquals("89.0", parse[0]);
202 assertEquals("73.2", parse[1]);
204 parse = DistanceUtils.parsePoint(null, "89.0,73.2,-92.3", 3);
205 assertEquals(3, parse.length);
206 assertEquals("89.0", parse[0]);
207 assertEquals("73.2", parse[1]);
208 assertEquals("-92.3", parse[2]);
210 parse = DistanceUtils.parsePoint(null, " 89.0 , 73.2 , -92.3 ", 3);
211 assertEquals(3, parse.length);
212 assertEquals("89.0", parse[0]);
213 assertEquals("73.2", parse[1]);
214 assertEquals("-92.3", parse[2]);
217 String[] foo = DistanceUtils.parsePoint(parse, "89.0 , 73.2 , -92.3", 3);
218 //should be same piece of memory
219 assertTrue(foo == parse);
220 assertEquals(3, parse.length);
221 assertEquals("89.0", parse[0]);
222 assertEquals("73.2", parse[1]);
223 assertEquals("-92.3", parse[2]);
224 //array should get automatically resized
225 parse = DistanceUtils.parsePoint(new String[1], "89.0 , 73.2 , -92.3", 3);
226 assertEquals(3, parse.length);
227 assertEquals("89.0", parse[0]);
228 assertEquals("73.2", parse[1]);
229 assertEquals("-92.3", parse[2]);
233 parse = DistanceUtils.parsePoint(null, "89.0 , ", 3);
235 } catch (InvalidGeoException e) {
238 parse = DistanceUtils.parsePoint(null, " , 89.0 ", 3);
240 } catch (InvalidGeoException e) {
244 parse = DistanceUtils.parsePoint(null, "", 3);
246 } catch (InvalidGeoException e) {
250 double[] dbls = DistanceUtils.parsePointDouble(null, "89.0 , 73.2 , -92.3", 3);
251 assertEquals(3, dbls.length);
252 assertEquals(89.0, dbls[0]);
253 assertEquals(73.2, dbls[1]);
254 assertEquals(-92.3, dbls[2]);
257 dbls = DistanceUtils.parsePointDouble(null, "89.0 , foo , -92.3", 3);
259 } catch (NumberFormatException e) {
262 dbls = DistanceUtils.parseLatitudeLongitude(null, "89.0 , 73.2 ");
263 assertEquals(2, dbls.length);
264 assertEquals(89.0, dbls[0]);
265 assertEquals(73.2, dbls[1]);
267 //test some bad lat/long pairs
269 dbls = DistanceUtils.parseLatitudeLongitude(null, "189.0 , 73.2 ");
271 } catch (InvalidGeoException e) {
276 dbls = DistanceUtils.parseLatitudeLongitude(null, "89.0 , 273.2 ");
278 } catch (InvalidGeoException e) {