Handle some antimeridian cases

This commit is contained in:
amercader 2022-09-05 12:36:56 +02:00
parent c4fd9ce21a
commit 07a028f06f
3 changed files with 82 additions and 4 deletions

View File

@ -105,3 +105,23 @@ def fit_bbox(bbox_dict):
"miny": _adjust_latitude(bbox_dict["miny"]),
"maxy": _adjust_latitude(bbox_dict["maxy"]),
}
def fit_linear_ring(lr):
bbox = {
"minx": lr[0][0],
"maxx": lr[2][0],
"miny": lr[1][1],
"maxy": lr[0][1],
}
bbox = fit_bbox(bbox)
return [
(bbox["minx"], bbox["maxy"]),
(bbox["minx"], bbox["miny"]),
(bbox["maxx"], bbox["miny"]),
(bbox["maxx"], bbox["maxy"]),
(bbox["minx"], bbox["maxy"]),
]

View File

@ -13,7 +13,7 @@ from ckan import plugins as p
from ckan.lib.search import SearchError
from ckan.lib.helpers import json
from ckanext.spatial.lib import normalize_bbox, fit_bbox
from ckanext.spatial.lib import normalize_bbox, fit_bbox, fit_linear_ring
if tk.check_ckan_version(min_version="2.9.0"):
from ckanext.spatial.plugin.flask_plugin import (
@ -36,7 +36,6 @@ ALLOWED_SEARCH_BACKENDS = [
]
class SpatialMetadata(p.SingletonPlugin):
p.implements(p.IPackageController, inherit=True)
@ -251,8 +250,12 @@ class SpatialQuery(SpatialQueryMixin, p.SingletonPlugin):
# Check if coordinates are defined counter-clockwise,
# otherwise we'll get wrong results from Solr
lr = shapely.geometry.polygon.LinearRing(geometry['coordinates'][0])
lr_coords = list(lr.coords) if lr.is_ccw else reversed(list(lr.coords))
polygon = shapely.geometry.polygon.Polygon(lr_coords)
lr_coords = (
list(lr.coords) if lr.is_ccw
else reversed(list(lr.coords))
)
polygon = shapely.geometry.polygon.Polygon(
fit_linear_ring(lr_coords))
wkt = polygon.wkt
if not wkt:

View File

@ -107,6 +107,29 @@ class TestBBoxSearch(SpatialTestBase):
assert result["count"] == 1
assert result["results"][0]["id"] == dataset["id"]
def test_spatial_polygon_split_across_antimeridian_outside_bbox(self):
"""
This test passes because as the geometry passes the antemeridian, the
extent generated to be index is (-180, miny, 180, maxy). Sites needing to
deal with this scenario should use the `solr-spatial-field` backend.
See ``TestSpatialFieldSearch.test_spatial_polygon_split_across_antimeridian_outside_bbox``
"""
dataset = factories.Dataset(
extras=[
{
"key": "spatial",
"value": self.read_file("data/chukot.geojson")
}
]
)
result = helpers.call_action(
"package_search", extras={"ext_bbox": "0,61,15,64"}
)
assert result["count"] == 1
assert result["results"][0]["id"] == dataset["id"]
def test_spatial_query_nz(self):
dataset = factories.Dataset(extras=[{"key": "spatial", "value": extents["nz"]}])
@ -442,3 +465,35 @@ class TestSpatialFieldSearch(SpatialTestBase):
assert result["count"] == 1
assert result["results"][0]["id"] == dataset["id"]
def test_spatial_polygon_split_across_antimeridian(self):
dataset = factories.Dataset(
extras=[
{
"key": "spatial",
"value": self.read_file("data/chukot.geojson")
}
]
)
result = helpers.call_action(
"package_search", extras={"ext_bbox": "175,61,179,64"}
)
assert result["count"] == 1
assert result["results"][0]["id"] == dataset["id"]
def test_spatial_polygon_split_across_antimeridian_outside_bbox(self):
factories.Dataset(
extras=[
{
"key": "spatial",
"value": self.read_file("data/chukot.geojson")
}
]
)
result = helpers.call_action(
"package_search", extras={"ext_bbox": "0,61,15,64"}
)
assert result["count"] == 0