Skip to content

Commit

Permalink
Vector tiles: Add support for Geometry collections (#75697) (#75719)
Browse files Browse the repository at this point in the history
It creates a feature fir each entry in the collection
  • Loading branch information
iverase authored Jul 27, 2021
1 parent 73dfd75 commit d0d86db
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 177 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import com.wdtinc.mapbox_vector_tile.VectorTile;

import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
Expand All @@ -21,7 +20,7 @@
import org.elasticsearch.search.aggregations.bucket.geogrid.GeoTileUtils;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;

import java.io.IOException;
Expand All @@ -35,20 +34,27 @@ public class VectorTileRestIT extends ESRestTestCase {

private static final String INDEX_POINTS = "index-points";
private static final String INDEX_SHAPES = "index-shapes";
private static final String INDEX_COLLECTION = "index-collection";
private static final String INDEX_POINTS_SHAPES = INDEX_POINTS + "," + INDEX_SHAPES;
private static final String INDEX_ALL = "index*";
private static final String META_LAYER = "meta";
private static final String HITS_LAYER = "hits";
private static final String AGGS_LAYER = "aggs";

private int x, y, z;
private static boolean oneTimeSetup = false;
private static int x, y, z;

@Before
public void indexDocuments() throws IOException {
z = randomIntBetween(1, GeoTileUtils.MAX_ZOOM - 10);
x = randomIntBetween(0, (1 << z) - 1);
y = randomIntBetween(0, (1 << z) - 1);
indexPoints();
indexShapes();
if (oneTimeSetup == false) {
z = randomIntBetween(1, GeoTileUtils.MAX_ZOOM - 10);
x = randomIntBetween(0, (1 << z) - 1);
y = randomIntBetween(0, (1 << z) - 1);
indexPoints();
indexShapes();
indexCollection();
oneTimeSetup = true;
}
}

private void indexPoints() throws IOException {
Expand Down Expand Up @@ -151,13 +157,79 @@ private void indexShapes() throws IOException {
assertThat(response.getStatusLine().getStatusCode(), Matchers.equalTo(HttpStatus.SC_OK));
}

@After
public void deleteData() throws IOException {
final Request deleteRequest = new Request(HttpDelete.METHOD_NAME, INDEX_POINTS);
final Response response = client().performRequest(deleteRequest);
private void indexCollection() throws IOException {
final Request createRequest = new Request(HttpPut.METHOD_NAME, INDEX_COLLECTION);
Response response = client().performRequest(createRequest);
assertThat(response.getStatusLine().getStatusCode(), Matchers.equalTo(HttpStatus.SC_OK));
final Request mappingRequest = new Request(HttpPut.METHOD_NAME, INDEX_COLLECTION + "/_mapping");
mappingRequest.setJsonEntity(
"{\n"
+ " \"properties\": {\n"
+ " \"location\": {\n"
+ " \"type\": \"geo_shape\"\n"
+ " },\n"
+ " \"name\": {\n"
+ " \"type\": \"keyword\"\n"
+ " }\n"
+ " }\n"
+ "}"
);
response = client().performRequest(mappingRequest);
assertThat(response.getStatusLine().getStatusCode(), Matchers.equalTo(HttpStatus.SC_OK));

final Rectangle r = GeoTileUtils.toBoundingBox(x, y, z);
double x = (r.getMaxX() + r.getMinX()) / 2;
double y = (r.getMaxY() + r.getMinY()) / 2;
final Request putRequest = new Request(HttpPost.METHOD_NAME, INDEX_COLLECTION + "/_doc");
String collection = "GEOMETRYCOLLECTION (BBOX ("
+ r.getMinLon()
+ ", "
+ r.getMaxLon()
+ ","
+ r.getMaxLat()
+ ","
+ r.getMinLat()
+ "), POINT("
+ x
+ " "
+ y
+ "))";
putRequest.setJsonEntity(
"{\n"
+ " \"location\": \""
+ collection
+ "\""
+ ", \"name\": \"collection\""
+ ", \"value1\": "
+ 1
+ ", \"value2\": "
+ 2
+ "\n"
+ "}"
);
response = client().performRequest(putRequest);
assertThat(response.getStatusLine().getStatusCode(), Matchers.equalTo(HttpStatus.SC_CREATED));

final Request flushRequest = new Request(HttpPost.METHOD_NAME, INDEX_COLLECTION + "/_refresh");
response = client().performRequest(flushRequest);
assertThat(response.getStatusLine().getStatusCode(), Matchers.equalTo(HttpStatus.SC_OK));
}

@AfterClass
public static void deleteData() throws IOException {
try {
wipeAllIndices();
} finally {
// Clear the setup state
oneTimeSetup = false;
}
}

@Override
protected boolean preserveIndicesUponCompletion() {
return true;
}

public void testBasicGet() throws Exception {
final Request mvtRequest = new Request(getHttpMethod(), INDEX_POINTS + "/_mvt/location/" + z + "/" + x + "/" + y);
mvtRequest.setJsonEntity("{\"size\" : 100}");
Expand All @@ -168,6 +240,17 @@ public void testBasicGet() throws Exception {
assertLayer(tile, META_LAYER, 4096, 1, 14);
}

public void testIndexAllGet() throws Exception {
final Request mvtRequest = new Request(getHttpMethod(), INDEX_ALL + "/_mvt/location/" + z + "/" + x + "/" + y);
mvtRequest.setJsonEntity("{\"size\" : 100}");
final VectorTile.Tile tile = execute(mvtRequest);
assertThat(tile.getLayersCount(), Matchers.equalTo(3));
// 33 points, 1 polygon and two from geometry collection
assertLayer(tile, HITS_LAYER, 4096, 36, 1);
assertLayer(tile, AGGS_LAYER, 4096, 256 * 256, 1);
assertLayer(tile, META_LAYER, 4096, 1, 14);
}

public void testExtent() throws Exception {
final Request mvtRequest = new Request(getHttpMethod(), INDEX_POINTS + "/_mvt/location/" + z + "/" + x + "/" + y);
mvtRequest.setJsonEntity("{\"size\" : 100, \"extent\" : 256}");
Expand Down Expand Up @@ -346,7 +429,7 @@ public void testRuntimeFieldWithSort() throws Exception {
+ "}\n";
{
// desc order, polygon should be the first hit
final Request mvtRequest = new Request(getHttpMethod(), INDEX_ALL + "/_mvt/location/" + z + "/" + x + "/" + y);
final Request mvtRequest = new Request(getHttpMethod(), INDEX_POINTS_SHAPES + "/_mvt/location/" + z + "/" + x + "/" + y);
mvtRequest.setJsonEntity(
"{\n"
+ " \"size\" : 100,\n"
Expand All @@ -372,7 +455,7 @@ public void testRuntimeFieldWithSort() throws Exception {
}
{
// asc order, polygon should be the last hit
final Request mvtRequest = new Request(getHttpMethod(), INDEX_ALL + "/_mvt/location/" + z + "/" + x + "/" + y);
final Request mvtRequest = new Request(getHttpMethod(), INDEX_POINTS_SHAPES + "/_mvt/location/" + z + "/" + x + "/" + y);
mvtRequest.setJsonEntity(
"{\n"
+ " \"size\" : 100,\n"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public FeatureFactory(int z, int x, int y, int extent) {
}

public List<VectorTile.Tile.Feature> getFeatures(Geometry geometry, IUserDataConverter userData) {
TileGeomResult tileGeom = JtsAdapter.createTileGeom(
final TileGeomResult tileGeom = JtsAdapter.createTileGeom(
JtsAdapter.flatFeatureList(geometry.visit(builder)),
tileEnvelope,
clipEnvelope,
Expand Down Expand Up @@ -91,8 +91,11 @@ public org.locationtech.jts.geom.Geometry visit(Circle circle) {

@Override
public org.locationtech.jts.geom.Geometry visit(GeometryCollection<?> collection) {
// TODO: Geometry collections are not supported by the vector tile specification.
throw new IllegalArgumentException("GeometryCollection is not supported");
final org.locationtech.jts.geom.Geometry[] geometries = new org.locationtech.jts.geom.Geometry[collection.size()];
for (int i = 0; i < collection.size(); i++) {
geometries[i] = collection.get(i).visit(this);
}
return geomFactory.createGeometryCollection(geometries);
}

@Override
Expand Down Expand Up @@ -127,7 +130,7 @@ public org.locationtech.jts.geom.Geometry visit(Line line) {

@Override
public org.locationtech.jts.geom.Geometry visit(MultiLine multiLine) throws RuntimeException {
LineString[] lineStrings = new LineString[multiLine.size()];
final LineString[] lineStrings = new LineString[multiLine.size()];
for (int i = 0; i < multiLine.size(); i++) {
lineStrings[i] = buildLine(multiLine.get(i));
}
Expand All @@ -151,7 +154,7 @@ public org.locationtech.jts.geom.Geometry visit(Polygon polygon) throws RuntimeE

@Override
public org.locationtech.jts.geom.Geometry visit(MultiPolygon multiPolygon) throws RuntimeException {
org.locationtech.jts.geom.Polygon[] polygons = new org.locationtech.jts.geom.Polygon[multiPolygon.size()];
final org.locationtech.jts.geom.Polygon[] polygons = new org.locationtech.jts.geom.Polygon[multiPolygon.size()];
for (int i = 0; i < multiPolygon.size(); i++) {
polygons[i] = buildPolygon(multiPolygon.get(i));
}
Expand All @@ -163,7 +166,7 @@ private org.locationtech.jts.geom.Polygon buildPolygon(Polygon polygon) {
if (polygon.getNumberOfHoles() == 0) {
return geomFactory.createPolygon(outerShell);
}
org.locationtech.jts.geom.LinearRing[] holes = new org.locationtech.jts.geom.LinearRing[polygon.getNumberOfHoles()];
final org.locationtech.jts.geom.LinearRing[] holes = new org.locationtech.jts.geom.LinearRing[polygon.getNumberOfHoles()];
for (int i = 0; i < polygon.getNumberOfHoles(); i++) {
holes[i] = buildLinearRing(polygon.getHole(i));
}
Expand Down
Loading

0 comments on commit d0d86db

Please sign in to comment.