来自mapbox-vector-tile-java的矢量平铺导致在异常高纬度的mapbox-gl中呈现的特征

时间:2017-02-07 23:20:20

标签: mapbox mapbox-gl mapbox-gl-js vector-tiles

我们正在尝试使用mapbox-vector-tile-java将矢量切片端点合并到后端框架中,以将地理要素编码为矢量切片。除了一些奇怪的行为之外,我们所有这些都在工作,其中渲染的特征被放置在比它们应该更高的纬度。当放大特征时,将跳到较低纬度,直到最终在非常低的缩放级别达到相当好的准确度。例如,我的数据来自新墨西哥州。在初始页面加载时,所有县都在加拿大呈现。当我放大到缩放级别2时,它们会跳到加拿大南部。我越放大,他们就越接近新墨西哥州。有谁知道我为什么会看到这种行为?

一些高级细节:

  1. 数据库的地理特征在EPSG:4326。
  2. JTS与mapbox-vector-tile-java结合使用来处理数据编码。
  3. 将基于URL的xyz切片位置转换为切片边界使用Mapbox用于MapBox的TileBelt中引用的此类转换的确切等式。
  4. 示例网址

    https://localhost:8443/app/location/data?x=0&y=0&z=0&config= {一些:JSON}

    构建Vector Tiles的后端Java代码

      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)));
    }
    

    平铺网格转换结果

    x = 0,y = 0,z = 1的网址会产生Env [-180.0:0.0,0.0:85.0511287798066],这是一个覆盖北美的图块(我们确定此网站的有效性: www.maptiler.org/google-maps-coordinates-tile-bounds-projection)。

    我们有几次预感(只是猜测)

    1. 尽管我们使用了他们在TileBelt中使用的等式,但是tile网格位置到mapbox-gl矢量图块网格之间的转换与上面的等式不同。
    2. mapbox-vector-tile-java提供编码错误的图块。
    3. 我们错误地设置了JTS几何的边界。

1 个答案:

答案 0 :(得分:0)

当然,事实证明这是一个明显的解决方案,我们之前没有抓到。在编码Vector Tiles之前,我们只需要将JTS功能投影到EPSG 3857。