From 097df5490937de78013f4708738ab2fe53f139d3 Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 1 Jul 2022 17:08:39 +0200 Subject: [PATCH 1/5] Use faster maths to project WGS84 to mercator --- .../common/geo/SphericalMercatorUtils.java | 10 +++++++--- .../common/geo/SphericalMercatorUtilTests.java | 13 +++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/common/geo/SphericalMercatorUtils.java b/server/src/main/java/org/elasticsearch/common/geo/SphericalMercatorUtils.java index 9cf1c10d75ffb..dd6da478824c6 100644 --- a/server/src/main/java/org/elasticsearch/common/geo/SphericalMercatorUtils.java +++ b/server/src/main/java/org/elasticsearch/common/geo/SphericalMercatorUtils.java @@ -8,6 +8,8 @@ package org.elasticsearch.common.geo; +import org.apache.lucene.util.SloppyMath; +import org.elasticsearch.core.ESSloppyMath; import org.elasticsearch.geometry.Rectangle; /** @@ -17,8 +19,8 @@ public class SphericalMercatorUtils { public static final double MERCATOR_BOUNDS = 20037508.34; private static final double MERCATOR_FACTOR = MERCATOR_BOUNDS / 180.0; - // latitude lower limit. Below this limit the transformation might result in -Infinity - private static final double LAT_LOWER_LIMIT = Math.nextUp(-90.0); + // tangent lower limit. Below this limit the transformation result is -Infinity + private static final double TAN_LOWER_LIMIT = Math.tan(Math.nextUp(0.0)); /** * Transforms WGS84 longitude to a Spherical mercator longitude @@ -31,7 +33,9 @@ public static double lonToSphericalMercator(double lon) { * Transforms WGS84 latitude to a Spherical mercator latitude */ public static double latToSphericalMercator(double lat) { - double y = Math.log(Math.tan((90 + Math.max(lat, LAT_LOWER_LIMIT)) * Math.PI / 360)) / (Math.PI / 180); + final double cos = SloppyMath.cos((90 + lat) * Math.PI / 360); + final double tan = Math.max(TAN_LOWER_LIMIT, Math.sqrt(1 - cos * cos) / cos); + final double y = ESSloppyMath.log(tan) / (Math.PI / 180); return y * MERCATOR_FACTOR; } diff --git a/server/src/test/java/org/elasticsearch/common/geo/SphericalMercatorUtilTests.java b/server/src/test/java/org/elasticsearch/common/geo/SphericalMercatorUtilTests.java index 9426f1e29eb88..1db4f7edbbb29 100644 --- a/server/src/test/java/org/elasticsearch/common/geo/SphericalMercatorUtilTests.java +++ b/server/src/test/java/org/elasticsearch/common/geo/SphericalMercatorUtilTests.java @@ -66,4 +66,17 @@ public void testRectangle() { assertThat(mercatorRect.getMinY(), Matchers.equalTo(latToSphericalMercator(rect.getMinY()))); assertThat(mercatorRect.getMaxY(), Matchers.equalTo(latToSphericalMercator(rect.getMaxY()))); } + + public void testLatitudeExactMath() { + // check that the maths we are using are precise to 1mm from the strict maths + for (int i = 0; i < 10000; i++) { + double lat = randomDoubleBetween(-GeoTileUtils.LATITUDE_MASK, GeoTileUtils.LATITUDE_MASK, true); + assertEquals(lat + "", strictLatToSphericalMercator(lat), latToSphericalMercator(lat), 1e-3); + } + } + + private static double strictLatToSphericalMercator(double lat) { + double y = Math.log(Math.tan((90 + Math.max(lat, Math.nextUp(-90.0))) * Math.PI / 360)) / (Math.PI / 180); + return y * SphericalMercatorUtils.MERCATOR_BOUNDS / 180; + } } From 9c02cd4db9838f94aa7d6d48961600931b82337a Mon Sep 17 00:00:00 2001 From: Ignacio Vera Date: Fri, 1 Jul 2022 17:17:39 +0200 Subject: [PATCH 2/5] Update docs/changelog/88231.yaml --- docs/changelog/88231.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/changelog/88231.yaml diff --git a/docs/changelog/88231.yaml b/docs/changelog/88231.yaml new file mode 100644 index 0000000000000..a4958b58805aa --- /dev/null +++ b/docs/changelog/88231.yaml @@ -0,0 +1,5 @@ +pr: 88231 +summary: Use faster maths to project WGS84 to mercator +area: Geo +type: enhancement +issues: [] From 2864d93925e5b3d601e1f2352b6e3024c92b61c5 Mon Sep 17 00:00:00 2001 From: iverase Date: Fri, 1 Jul 2022 17:41:16 +0200 Subject: [PATCH 3/5] fix test --- .../rest-api-spec/test/spatial/70_script_doc_values.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml index aa2b3812c1c87..c589f41a80df9 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml @@ -143,4 +143,4 @@ setup: script: source: "doc['geo_shape'].getMercatorHeight()" - match: { hits.hits.0.fields.width.0: 389.62170283915475 } - - match: { hits.hits.0.fields.height.0: 333.37976840604097 } + - match: { hits.hits.0.fields.height.0: 333.37976841442287 } From 9f4919507d44eff5dc3633e22ac8d0e972883046 Mon Sep 17 00:00:00 2001 From: iverase Date: Sat, 2 Jul 2022 08:35:48 +0200 Subject: [PATCH 4/5] fix test --- .../rest-api-spec/test/spatial/70_script_doc_values.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml index c589f41a80df9..5ffdcaaa2cc36 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml @@ -131,6 +131,10 @@ setup: --- "diagonal length": + - skip: + reason: "precision changed in 8.4.0" + version: "8.3.99 - " + - do: search: rest_total_hits_as_int: true From fab04267622bc9faa28486249802f231f7968c03 Mon Sep 17 00:00:00 2001 From: iverase Date: Sat, 2 Jul 2022 08:59:06 +0200 Subject: [PATCH 5/5] fix test --- x-pack/plugin/build.gradle | 1 + .../rest-api-spec/test/spatial/70_script_doc_values.yml | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/x-pack/plugin/build.gradle b/x-pack/plugin/build.gradle index 1c77629af888c..04105eb1235d7 100644 --- a/x-pack/plugin/build.gradle +++ b/x-pack/plugin/build.gradle @@ -143,6 +143,7 @@ tasks.named("yamlRestTestV7CompatTransform").configure { task -> task.skipTest("indices.freeze/10_basic/Test index options", "#70192 -- the freeze index API is removed from 8.0") task.skipTest("sql/sql/Paging through results", "scrolling through search hit queries no longer produces empty last page in 8.2") task.skipTest("service_accounts/10_basic/Test get service accounts", "new service accounts are added") + task.skipTest("spatial/70_script_doc_values/diagonal length", "precision changed in 8.4.0") task.replaceValueInMatch("_type", "_doc") task.addAllowedWarningRegex("\\[types removal\\].*") diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml index 5ffdcaaa2cc36..c589f41a80df9 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/spatial/70_script_doc_values.yml @@ -131,10 +131,6 @@ setup: --- "diagonal length": - - skip: - reason: "precision changed in 8.4.0" - version: "8.3.99 - " - - do: search: rest_total_hits_as_int: true