Vector Tiles из mapbox-vector-tile-java приводит к отображению объектов в mapbox-gl на аномально высоких широтах

Мы пытаемся включить конечные точки векторных листов во внутреннюю структуру, используя mapbox-vector-tile -java для кодирования географических объектов в векторные плитки. У нас все это в основном работает, за исключением некоторого странного поведения, когда визуализированные объекты размещаются на широтах намного выше, чем они должны быть. При увеличении масштаба объекты будут переходить на более низкие широты, пока, наконец, не достигнут довольно хорошей точности при действительно низких уровнях масштабирования. Например, мои данные относятся к округам Нью-Мексико. На начальной странице загрузите все графства Канады. Когда я увеличиваю масштаб до уровня 2, они перепрыгивают в Южную Канаду. Чем больше я увеличиваю масштаб, тем ближе они становятся к тому месту, где на самом деле находится Нью-Мексико. Кто-нибудь знает, почему я наблюдаю такое поведение?

Некоторые подробности высокого уровня:

  1. Географические объекты из базы данных находятся в EPSG: 4326.
  2. JTS используется вместе с mapbox-vector-tile-java для обработки кодирования данных.
  3. Преобразование позиций плитки xyz на основе URL в границы плитки использует точное уравнение, которое Mapbox использует для таких преобразований, как указано в TileBelt MapBox.

Пример URL

https://localhost:8443/app/location/data?x=0&y=0&z=0&config= {some: json}

Внутренний код 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)));
}

Результаты преобразования мозаичной сетки

URL-адрес с x = 0, y = 0, z = 1 приводит к Env [-180.0: 0.0, 0.0: 85.0511287798066], который представляет собой плитку, покрывающую Северную Америку, как и ожидалось (мы определили достоверность с помощью этого веб-сайта: www.maptiler .org / Google-карты-координаты-плитки-границы-проекция).

У нас есть пара догадок (просто догадываюсь)

  1. Преобразование между положением мозаичной сетки в векторную мозаичную сетку mapbox-gl отличается от приведенного выше уравнения, несмотря на то, что мы использовали уравнение, которое они также используют в TileBelt.
  2. mapbox-vector-tile-java предоставляет некорректно закодированные плитки.
  3. Мы неправильно устанавливаем границы геометрии JTS.

person jmapping    schedule 07.02.2017    source источник


Ответы (1)


Конечно, это оказалось очевидным решением, которое мы почему-то не заметили раньше. Нам просто нужно было спроецировать функции JTS на EPSG 3857 перед кодированием векторных листов.

person jmapping    schedule 14.02.2017
comment
Как сделать конверт при проецировании признаков на 3857? - person Mahdi Nameghi; 22.05.2017