Skip to content

Commit

Permalink
Fix handling indexed envelopes crossing the dateline in mvt API (#91105
Browse files Browse the repository at this point in the history
…) (#91254)

This commit makes sure an envelope crossing the dateline generates a mutipolygon when creating a mvt feature 
so it is render properly.
  • Loading branch information
iverase committed Nov 2, 2022
1 parent 6bc5f51 commit 6c2fd60
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 33 deletions.
6 changes: 6 additions & 0 deletions docs/changelog/91105.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 91105
summary: Fix handling indexed envelopes crossing the dateline in mvt API
area: Geo
type: bug
issues:
- 91060
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,61 @@ private Geometry normalize(Geometry geometry) {
}
}

public void testFetchSourceValueDateLine() throws IOException {
public void testFetchSourcePolygonDateLine() throws IOException {
assertFetchSourceGeometry(
"POLYGON((170 -10, -170 -10, -170 10, 170 10, 170 -10))",
"MULTIPOLYGON (((180.0 -10.0, 180.0 10.0, 170.0 10.0, 170.0 -10.0, 180.0 -10.0)),"
+ "((-180.0 10.0, -180.0 -10.0, -170.0 -10.0, -170.0 10.0, -180.0 10.0)))",
Map.of(
"type",
"MultiPolygon",
"coordinates",
List.of(
List.of(
List.of(
List.of(180.0, -10.0),
List.of(180.0, 10.0),
List.of(170.0, 10.0),
List.of(170.0, -10.0),
List.of(180.0, -10.0)
)
),
List.of(
List.of(
List.of(-180.0, 10.0),
List.of(-180.0, -10.0),
List.of(-170.0, -10.0),
List.of(-170.0, 10.0),
List.of(-180.0, 10.0)
)
)
)
),
"MULTIPOLYGON (((180.0 -10.0, 180.0 10.0, 170.0 10.0, 170.0 -10.0, 180.0 -10.0)),"
+ "((-180.0 10.0, -180.0 -10.0, -170.0 -10.0, -170.0 10.0, -180.0 10.0)))"
);
}

public void testFetchSourceEnvelope() throws IOException {
assertFetchSourceGeometry(
"BBOX(-10, 10, 10, -10)",
"BBOX (-10.0, 10.0, 10.0, -10.0)",
Map.of("type", "Envelope", "coordinates", List.of(List.of(-10.0, 10.0), List.of(10.0, -10.0))),
"POLYGON ((-10 -10, 10 -10, 10 10, -10 10, -10 -10)))"
);
}

public void testFetchSourceEnvelopeDateLine() throws IOException {
assertFetchSourceGeometry(
"BBOX(10, -10, 10, -10)",
"BBOX (10.0, -10.0, 10.0, -10.0)",
Map.of("type", "Envelope", "coordinates", List.of(List.of(10.0, 10.0), List.of(-10.0, -10.0))),
"MULTIPOLYGON (((-180 -10, -10 -10, -10 10, -180 10, -180 -10)), ((10 -10, 180 -10, 180 10, 10 10, 10 -10)))"
);
}

private void assertFetchSourceGeometry(Object sourceValue, String wktValue, Map<String, Object> jsonValue, String mvtEquivalentAsWKT)
throws IOException {
final GeoFormatterFactory<Geometry> geoFormatterFactory = new GeoFormatterFactory<>(
new SpatialGeometryFormatterExtension().getGeometryFormatterFactories()
);
Expand All @@ -161,38 +215,13 @@ public void testFetchSourceValueDateLine() throws IOException {
false,
geoFormatterFactory
).build(MapperBuilderContext.ROOT).fieldType();
// Test a polygon crossing the dateline
Object sourceValue = "POLYGON((170 -10, -170 -10, -170 10, 170 10, 170 -10))";
String polygonDateLine = "MULTIPOLYGON (((180.0 -10.0, 180.0 10.0, 170.0 10.0, 170.0 -10.0, 180.0 -10.0)),"
+ "((-180.0 10.0, -180.0 -10.0, -170.0 -10.0, -170.0 10.0, -180.0 10.0)))";
Map<String, Object> jsonPolygonDateLine = Map.of(
"type",
"MultiPolygon",
"coordinates",
List.of(
List.of(
List.of(List.of(180.0, -10.0), List.of(180.0, 10.0), List.of(170.0, 10.0), List.of(170.0, -10.0), List.of(180.0, -10.0))
),
List.of(
List.of(
List.of(-180.0, 10.0),
List.of(-180.0, -10.0),
List.of(-170.0, -10.0),
List.of(-170.0, 10.0),
List.of(-180.0, 10.0)
)
)
)
);

assertEquals(List.of(jsonPolygonDateLine), fetchSourceValue(mapper, sourceValue, null));
assertEquals(List.of(polygonDateLine), fetchSourceValue(mapper, sourceValue, "wkt"));

String mvtPolygonDateLine = "MULTIPOLYGON (((180.0 -10.0, 180.0 10.0, 170.0 10.0, 170.0 -10.0, 180.0 -10.0)),"
+ "((-180.0 10.0, -180.0 -10.0, -170.0 -10.0, -170.0 10.0, -180.0 10.0)))";
assertEquals(List.of(jsonValue), fetchSourceValue(mapper, sourceValue, null));
assertEquals(List.of(wktValue), fetchSourceValue(mapper, sourceValue, "wkt"));

List<?> mvtExpected = fetchSourceValue(mapper, mvtPolygonDateLine, "mvt(0/0/0@256)");
List<?> mvt = fetchSourceValue(mapper, sourceValue, "mvt(0/0/0@256)");
final int extent = randomIntBetween(256, 4096);
List<?> mvtExpected = fetchSourceValue(mapper, mvtEquivalentAsWKT, "mvt(0/0/0@" + extent + ")");
List<?> mvt = fetchSourceValue(mapper, sourceValue, "mvt(0/0/0@" + extent + ")");
assertThat(mvt.size(), Matchers.equalTo(1));
assertThat(mvt.size(), Matchers.equalTo(mvtExpected.size()));
assertThat(mvtExpected.get(0), Matchers.instanceOf(byte[].class));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,15 @@ public org.locationtech.jts.geom.Geometry visit(Rectangle rectangle) throws Runt
final double yMin = SphericalMercatorUtils.latToSphericalMercator(rectangle.getMinY());
final double xMax = SphericalMercatorUtils.lonToSphericalMercator(rectangle.getMaxX());
final double yMax = SphericalMercatorUtils.latToSphericalMercator(rectangle.getMaxY());
final Envelope envelope = new Envelope(xMin, xMax, yMin, yMax);
return geomFactory.toGeometry(envelope);
if (rectangle.getMinX() > rectangle.getMaxX()) {
// crosses dateline
final Envelope westEnvelope = new Envelope(-SphericalMercatorUtils.MERCATOR_BOUNDS, xMax, yMin, yMax);
final Envelope eastEnvelope = new Envelope(xMin, SphericalMercatorUtils.MERCATOR_BOUNDS, yMin, yMax);
return geomFactory.buildGeometry(List.of(geomFactory.toGeometry(westEnvelope), geomFactory.toGeometry(eastEnvelope)));
} else {
final Envelope envelope = new Envelope(xMin, xMax, yMin, yMax);
return geomFactory.toGeometry(envelope);
}
}
}

Expand Down

0 comments on commit 6c2fd60

Please sign in to comment.