Reputation: 51
We are trying to incorporate vector tile endpoints into a back-end framework using mapbox-vector-tile-java to encode geographic features into Vector Tiles. We have it all mostly working except for some odd behavior where the rendered features are placed at latitudes way higher than they should be. When zooming in the features will jump to lower latitudes until finally getting to pretty good accuracy at really low zoom levels. For example, my data is of New Mexico counties. On initial page load the counties all render in Canada. When I zoom in to zoom level 2 they will jump down to Southern Canada. The more I zoom in the more close they get to where New Mexico actually is. Does anyone know why I'm seeing this behavior?
https://localhost:8443/app/location/data?x=0&y=0&z=0&config={some:json}
Envelope tileEnvelope = this.getTileBounds(x, y, zoom);
GeometryFactory geomFactory = new GeometryFactory();
IGeometryFilter acceptAllGeomFilter = geometry -> true;
MvtLayerParams layerParams = new MvtLayerParams();
TileGeomResult tileGeom = JtsAdapter.createTileGeom(geometries, tileEnvelope, geomFactory, layerParams, acceptAllGeomFilter);
final VectorTile.Tile.Builder tileBuilder = VectorTile.Tile.newBuilder();
// Create MVT layer
final MvtLayerProps layerProps = new MvtLayerProps();
final IUserDataConverter ignoreUserData = new UserDataConverter();
// MVT tile geometry to MVT features
final List<VectorTile.Tile.Feature> features = JtsAdapter.toFeatures(tileGeom.mvtGeoms, layerProps, ignoreUserData);
final VectorTile.Tile.Layer.Builder layerBuilder = MvtLayerBuild.newLayerBuilder(layerName, layerParams);
layerBuilder.addAllFeatures(features);
MvtLayerBuild.writeProps(layerBuilder, layerProps);
// Build MVT layer
final VectorTile.Tile.Layer layer = layerBuilder.build();
// Add built layer to MVT
tileBuilder.addLayers(layer);
/// Build MVT
Tile mvt = tileBuilder.build();
return mvt.toByteArray();
public Envelope getTileBounds(int x, int y, int zoom)
{
return new Envelope(this.getLong(x, zoom), this.getLong(x + 1, zoom), this.getLat(y, zoom), this.getLat(y + 1, zoom));
}
public double getLong(int x, int zoom)
{
return ( x / Math.pow(2, zoom) * 360 - 180 );
}
public double getLat(int y, int zoom)
{
double r2d = 180 / Math.PI;
double n = Math.PI - 2 * Math.PI * y / Math.pow(2, zoom);
return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)));
}
A URL with x=0,y=0,z=1 results in Env[-180.0 : 0.0, 0.0 : 85.0511287798066] which is a tile that covers north america as expected (We determined validity with this web-site: www.maptiler.org/google-maps-coordinates-tile-bounds-projection ).
Upvotes: 1
Views: 1688
Reputation: 51
Of course this turned out to be an obvious solution that somehow we didn't catch earlier. We just needed to project the JTS features to EPSG 3857 before encoding the Vector Tiles.
Upvotes: 0