Improve latitude and longitude normalization
This commit is contained in:
parent
97b5c100ce
commit
8f0ecbcc0b
|
@ -24,32 +24,20 @@ package org.elasticsearch.index.search.geo;
|
|||
public class GeoUtils {
|
||||
|
||||
public static double normalizeLon(double lon) {
|
||||
double delta = 0;
|
||||
if (lon < 0) {
|
||||
delta = 360;
|
||||
} else if (lon >= 0) {
|
||||
delta = -360;
|
||||
}
|
||||
|
||||
double newLng = lon;
|
||||
while (newLng < -180 || newLng > 180) {
|
||||
newLng += delta;
|
||||
}
|
||||
return newLng;
|
||||
return centeredModulus(lon, 360);
|
||||
}
|
||||
|
||||
public static double normalizeLat(double lat) {
|
||||
double delta = 0;
|
||||
if (lat < 0) {
|
||||
delta = 180;
|
||||
} else if (lat >= 0) {
|
||||
delta = -180;
|
||||
return centeredModulus(lat, 180);
|
||||
}
|
||||
|
||||
double newLat = lat;
|
||||
while (newLat < -90 || newLat > 90) {
|
||||
newLat += delta;
|
||||
}
|
||||
return newLat;
|
||||
private static double centeredModulus(double dividend, double divisor) {
|
||||
double rtn = dividend % divisor;
|
||||
if (rtn <= 0)
|
||||
rtn += divisor;
|
||||
if (rtn > divisor/2)
|
||||
rtn -= divisor;
|
||||
return rtn;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Licensed to ElasticSearch and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. ElasticSearch licenses this
|
||||
* file to you 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 org.elasticsearch.test.unit.index.search.geo;
|
||||
|
||||
import org.elasticsearch.index.search.geo.GeoUtils;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class GeoUtilsTests {
|
||||
|
||||
/**
|
||||
* Test special values like inf, NaN and -0.0.
|
||||
*/
|
||||
@Test
|
||||
public void testSpecials() {
|
||||
assertThat(GeoUtils.normalizeLon(Double.POSITIVE_INFINITY), equalTo(Double.NaN));
|
||||
assertThat(GeoUtils.normalizeLat(Double.POSITIVE_INFINITY), equalTo(Double.NaN));
|
||||
assertThat(GeoUtils.normalizeLon(Double.NEGATIVE_INFINITY), equalTo(Double.NaN));
|
||||
assertThat(GeoUtils.normalizeLat(Double.NEGATIVE_INFINITY), equalTo(Double.NaN));
|
||||
assertThat(GeoUtils.normalizeLon(Double.NaN), equalTo(Double.NaN));
|
||||
assertThat(GeoUtils.normalizeLat(Double.NaN), equalTo(Double.NaN));
|
||||
assertThat(0.0, not(equalTo(-0.0)));
|
||||
assertThat(GeoUtils.normalizeLon(-0.0), equalTo(0.0));
|
||||
assertThat(GeoUtils.normalizeLat(-0.0), equalTo(0.0));
|
||||
assertThat(GeoUtils.normalizeLon( 0.0), equalTo(0.0));
|
||||
assertThat(GeoUtils.normalizeLat( 0.0), equalTo(0.0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test bounding values.
|
||||
*/
|
||||
@Test
|
||||
public void testBounds() {
|
||||
assertThat(GeoUtils.normalizeLon(-360.0), equalTo(0.0));
|
||||
assertThat(GeoUtils.normalizeLat(-180.0), equalTo(0.0));
|
||||
assertThat(GeoUtils.normalizeLon( 360.0), equalTo(0.0));
|
||||
assertThat(GeoUtils.normalizeLat( 180.0), equalTo(0.0));
|
||||
// and halves
|
||||
assertThat(GeoUtils.normalizeLon(-180.0), equalTo(180.0));
|
||||
assertThat(GeoUtils.normalizeLat(- 90.0), equalTo( 90.0));
|
||||
assertThat(GeoUtils.normalizeLon( 180.0), equalTo(180.0));
|
||||
assertThat(GeoUtils.normalizeLat( 90.0), equalTo( 90.0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test normal values.
|
||||
*/
|
||||
@Test
|
||||
public void testNormal() {
|
||||
// Near bounds
|
||||
assertThat(GeoUtils.normalizeLon(-360.5), equalTo(-0.5));
|
||||
assertThat(GeoUtils.normalizeLat(-180.5), equalTo(-0.5));
|
||||
assertThat(GeoUtils.normalizeLon( 360.5), equalTo( 0.5));
|
||||
assertThat(GeoUtils.normalizeLat( 180.5), equalTo( 0.5));
|
||||
// and near halves
|
||||
assertThat(GeoUtils.normalizeLon(-180.5), equalTo( 179.5));
|
||||
assertThat(GeoUtils.normalizeLat(- 90.5), equalTo( 89.5));
|
||||
assertThat(GeoUtils.normalizeLon( 180.5), equalTo(-179.5));
|
||||
assertThat(GeoUtils.normalizeLat( 90.5), equalTo(- 89.5));
|
||||
// Every 10-units, multiple full turns
|
||||
for (int shift = -20 ; shift <= 20 ; ++shift) {
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 0.0), equalTo( 0.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 10.0), equalTo( 10.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 20.0), equalTo( 20.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 30.0), equalTo( 30.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 40.0), equalTo( 40.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 50.0), equalTo( 50.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 60.0), equalTo( 60.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 70.0), equalTo( 70.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 80.0), equalTo( 80.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 90.0), equalTo( 90.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 100.0), equalTo( 100.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 110.0), equalTo( 110.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 120.0), equalTo( 120.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 130.0), equalTo( 130.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 140.0), equalTo( 140.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 150.0), equalTo( 150.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 160.0), equalTo( 160.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 170.0), equalTo( 170.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 180.0), equalTo( 180.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 190.0), equalTo(-170.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 200.0), equalTo(-160.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 210.0), equalTo(-150.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 220.0), equalTo(-140.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 230.0), equalTo(-130.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 240.0), equalTo(-120.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 250.0), equalTo(-110.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 260.0), equalTo(-100.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 270.0), equalTo(- 90.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 280.0), equalTo(- 80.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 290.0), equalTo(- 70.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 300.0), equalTo(- 60.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 310.0), equalTo(- 50.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 320.0), equalTo(- 40.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 330.0), equalTo(- 30.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 340.0), equalTo(- 20.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 350.0), equalTo(- 10.0));
|
||||
assertThat(GeoUtils.normalizeLon(shift*360.0+ 360.0), equalTo( 0.0));
|
||||
}
|
||||
for (int shift = -20 ; shift <= 20 ; ++shift) {
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 0.0), equalTo( 0.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 10.0), equalTo( 10.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 20.0), equalTo( 20.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 30.0), equalTo( 30.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 40.0), equalTo( 40.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 50.0), equalTo( 50.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 60.0), equalTo( 60.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 70.0), equalTo( 70.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 80.0), equalTo( 80.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 90.0), equalTo( 90.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 100.0), equalTo(-80.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 110.0), equalTo(-70.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 120.0), equalTo(-60.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 130.0), equalTo(-50.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 140.0), equalTo(-40.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 150.0), equalTo(-30.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 160.0), equalTo(-20.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 170.0), equalTo(-10.0));
|
||||
assertThat(GeoUtils.normalizeLat(shift*180.0+ 180.0), equalTo( 0.0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test huge values.
|
||||
*/
|
||||
@Test
|
||||
public void testHuge() {
|
||||
assertThat(GeoUtils.normalizeLon(-36000000000181.0), equalTo(GeoUtils.normalizeLon(-181.0)));
|
||||
assertThat(GeoUtils.normalizeLon(-36000000000180.0), equalTo(GeoUtils.normalizeLon(-180.0)));
|
||||
assertThat(GeoUtils.normalizeLon(-36000000000179.0), equalTo(GeoUtils.normalizeLon(-179.0)));
|
||||
assertThat(GeoUtils.normalizeLon(-36000000000178.0), equalTo(GeoUtils.normalizeLon(-178.0)));
|
||||
assertThat(GeoUtils.normalizeLon(-36000000000001.0), equalTo(GeoUtils.normalizeLon(-001.0)));
|
||||
assertThat(GeoUtils.normalizeLon(+36000000000000.0), equalTo(GeoUtils.normalizeLon(+000.0)));
|
||||
assertThat(GeoUtils.normalizeLon(+36000000000001.0), equalTo(GeoUtils.normalizeLon(+001.0)));
|
||||
assertThat(GeoUtils.normalizeLon(+36000000000002.0), equalTo(GeoUtils.normalizeLon(+002.0)));
|
||||
assertThat(GeoUtils.normalizeLon(+36000000000178.0), equalTo(GeoUtils.normalizeLon(+178.0)));
|
||||
assertThat(GeoUtils.normalizeLon(+36000000000179.0), equalTo(GeoUtils.normalizeLon(+179.0)));
|
||||
assertThat(GeoUtils.normalizeLon(+36000000000180.0), equalTo(GeoUtils.normalizeLon(+180.0)));
|
||||
assertThat(GeoUtils.normalizeLon(+36000000000181.0), equalTo(GeoUtils.normalizeLon(+181.0)));
|
||||
assertThat(GeoUtils.normalizeLat(-18000000000091.0), equalTo(GeoUtils.normalizeLat(-091.0)));
|
||||
assertThat(GeoUtils.normalizeLat(-18000000000090.0), equalTo(GeoUtils.normalizeLat(-090.0)));
|
||||
assertThat(GeoUtils.normalizeLat(-18000000000089.0), equalTo(GeoUtils.normalizeLat(-089.0)));
|
||||
assertThat(GeoUtils.normalizeLat(-18000000000088.0), equalTo(GeoUtils.normalizeLat(-088.0)));
|
||||
assertThat(GeoUtils.normalizeLat(-18000000000001.0), equalTo(GeoUtils.normalizeLat(-001.0)));
|
||||
assertThat(GeoUtils.normalizeLat(+18000000000000.0), equalTo(GeoUtils.normalizeLat(+000.0)));
|
||||
assertThat(GeoUtils.normalizeLat(+18000000000001.0), equalTo(GeoUtils.normalizeLat(+001.0)));
|
||||
assertThat(GeoUtils.normalizeLat(+18000000000002.0), equalTo(GeoUtils.normalizeLat(+002.0)));
|
||||
assertThat(GeoUtils.normalizeLat(+18000000000088.0), equalTo(GeoUtils.normalizeLat(+088.0)));
|
||||
assertThat(GeoUtils.normalizeLat(+18000000000089.0), equalTo(GeoUtils.normalizeLat(+089.0)));
|
||||
assertThat(GeoUtils.normalizeLat(+18000000000090.0), equalTo(GeoUtils.normalizeLat(+090.0)));
|
||||
assertThat(GeoUtils.normalizeLat(+18000000000091.0), equalTo(GeoUtils.normalizeLat(+091.0)));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue