Почему в OpenLayers поведение useInterimTilesOnError отличается на переведенных слоях MVT? - PullRequest
0 голосов
/ 11 июня 2019

При рендеринге переведенного слоя MVT, если useInterimTilesOnError истинно, части некоторых плиток не отображаются.Однако полные листы отображаются, если либо (1) слой не переведен, либо (2) слой переведен, но useInterimTilesOnError имеет значение false.

Если вы запустите этот пример, третья карта показывает эти половинуоказанные плитки:

var proj3857 = ol.proj.get('EPSG:3857');

var center = ol.proj.fromLonLat([133.9789237, -23.6188074]);
var view = new ol.View({
  center: center,
  maxZoom: 23,
  zoom: 10,
  projection: proj3857
});

var raster = new ol.layer.Tile({
  opacity: .4,
  source: new ol.source.XYZ({
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    maxZoom: 23,
  })
});
createMap('untranslated', 0, true);
createMap('false', 20000, false);
createMap('true', 20000, true);

function createMap(id, dx, useInterimTilesOnError) {

  var map = new ol.Map({
    layers: [raster],
    target: id,
    view: view
  });

  let dy = 0;
  var extent = proj3857.getExtent();
  var offsetExtent = [extent[0] + dx, extent[1] + dy, extent[2] + dx, extent[3] + dy];

  var layer = new ol.layer.VectorTile({
    source: new ol.source.VectorTile({
      format: new ol.format.MVT(),
      wrapX: false,
      url: 'https://basemaps.arcgis.com/v1/arcgis/rest/services/World_Basemap/VectorTileServer/tile/{z}/{y}/{x}.pbf',
      tileGrid: ol.tilegrid.createXYZ({
        extent: offsetExtent,
        maxZoom: 18
      })
    }),
    useInterimTilesOnError: useInterimTilesOnError,
    style: new ol.style.Style({
      stroke: new ol.style.Stroke({
        width: 1,
        color: 'black'
      })
    })
  });

  map.addLayer(layer);

  map.addLayer(new ol.layer.Tile({
    source: new ol.source.TileDebug({
      projection: proj3857,
      tileGrid: ol.tilegrid.createXYZ({
        extent: offsetExtent,
        maxZoom: 18
      })
    })
  }));
}
.map {
  height: 400px;
  width: 100%;
  margin-bottom: 10px;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet"/>
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<div>
  <h4>Untranslated plus useInterimTilesOnError: true</h4>
  <div id="untranslated" class="map"></div>
</div>
<div>
  <h4>Translated plus useInterimTilesOnError: false</h4>
  <div id="false" class="map"></div>
</div>
<div>
  <h4>Translated plus useInterimTilesOnError: true</h4>
  <div id="true" class="map"></div>
</div>

Если есть проблема с плиткой, я ожидаю, что она будет неправильно нарисована и на первой, не переведенной карте.

[В качестве отступления ... Я также ожидал, что useInterimTilesOnError применяется только к плиткам, которые не могут быть восстановлены.Но, очевидно, эти плитки извлекаются.Я не уверен, какие еще ошибки могут происходить с ними?]

1 Ответ

1 голос
/ 11 июня 2019

С useInterimTilesOnError: true, похоже, возникает проблема, потому что экстент проекции вида не соответствует экстенту сетки листов, и плитки обрезаются на основе проекции вида.Векторные листы нельзя перепроецировать, поэтому причина в одинаковой проекции, но разной степени.Определение переведенного экстента и использование его для вида, по-видимому, исправляет его, и растровый слой можно «перепроецировать» (хотя, поскольку единственные различия между координатами будут близки к линии даты, маловероятно, что потребуется слишком много служебных данных).

Я добавил еще несколько сценариев к вашей демонстрации:

var proj3857 = ol.proj.get('EPSG:3857');

proj4.defs('EPSG:3857X', '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs');

if (ol.proj.proj4 && ol.proj.proj4.register) { ol.proj.proj4.register(proj4); }

var dx = 20000;
var dy = 0;

var extent = ol.proj.get('EPSG:3857').getExtent();
var offsetExtent = [extent[0] + dx, extent[1] + dy, extent[2] + dx, extent[3] + dy];

var proj3857X = ol.proj.get('EPSG:3857X');
proj3857X.setGlobal(true);
proj3857X.setExtent(offsetExtent);

var center = ol.proj.fromLonLat([133.9789237, -23.6188074]);
var view = new ol.View({
  center: center,
  maxZoom: 23,
  zoom: 10,
  projection: proj3857
});

var viewX = new ol.View({
  center: center,
  maxZoom: 23,
  zoom: 10,
  projection: proj3857X
});

  var sync = true;

  view.on(['change:center','change:resolution','change:rotation'], function() {
    if (sync) {
      var center = view.getCenter();
      var zoom = view.getZoom();
      var rotation = view.getRotation();
      sync = false;
      viewX.animate({
        center: center,
        zoom: zoom,
        rotation: rotation,
        duration: 0
      }, function() { sync = true; });
    }
  });

 viewX.on(['change:center','change:resolution','change:rotation'], function() {
    if (sync) {
      var center = viewX.getCenter();
      var zoom = viewX.getZoom();
      var rotation = viewX.getRotation();
      sync = false;
      view.animate({
        center: center,
        zoom: zoom,
        rotation: rotation,
        duration: 0
      }, function() { sync = true; });
    }
  });

var raster = new ol.layer.Tile({
  opacity: .4,
  source: new ol.source.XYZ({
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    maxZoom: 23,
  })
});
createMap('untranslated-false', 0, 0, false, view);
createMap('untranslated-true', 0, 0, true, view);
createMap('false', dx, dy, false, view);
createMap('true', dx, dy, true, view);
createMap('projected-false', dx, dy, false, viewX);
createMap('projected-true', dx, dy, true, viewX);

function createMap(id, dx, dy, useInterimTilesOnError, view) {

  var map = new ol.Map({
    layers: [raster],
    target: id,
    view: view
  });

  var extent = proj3857.getExtent();
  var offsetExtent = [extent[0] + dx, extent[1] + dy, extent[2] + dx, extent[3] + dy];

  var layer = new ol.layer.VectorTile({
    source: new ol.source.VectorTile({
      format: new ol.format.MVT(),
      //wrapX: false,
      projection: view.getProjection(),
      url: 'https://basemaps.arcgis.com/v1/arcgis/rest/services/World_Basemap/VectorTileServer/tile/{z}/{y}/{x}.pbf',
      tileGrid: ol.tilegrid.createXYZ({
        extent: offsetExtent,
        maxZoom: 18
      })
    }),
    useInterimTilesOnError: useInterimTilesOnError,
    style: new ol.style.Style({
      stroke: new ol.style.Stroke({
        width: 1,
        color: 'black'
      })
    })
  });

  map.addLayer(layer);

  map.addLayer(new ol.layer.Tile({
    source: new ol.source.TileDebug({
      projection: proj3857,
      tileGrid: ol.tilegrid.createXYZ({
        extent: offsetExtent,
        maxZoom: 18
      })
    })
  }));
}
.map {
  height: 400px;
  width: 100%;
  margin-bottom: 10px;
}
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet"/>
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div>
  <h4>Untranslated plus useInterimTilesOnError: false</h4>
  <div id="untranslated-false" class="map"></div>
</div>
<div>
  <h4>Untranslated plus useInterimTilesOnError: true</h4>
  <div id="untranslated-true" class="map"></div>
</div>
<div>
  <h4>Translated plus useInterimTilesOnError: false</h4>
  <div id="false" class="map"></div>
</div>
<div>
  <h4>Translated plus useInterimTilesOnError: true</h4>
  <div id="true" class="map"></div>
</div>
<div>
  <h4>Projected plus useInterimTilesOnError: false</h4>
  <div id="projected-false" class="map"></div>
</div>
<div>
  <h4>Projected plus useInterimTilesOnError: true</h4>
  <div id="projected-true" class="map"></div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...