4.12ArcGIS JS API在全球场景加载CGCS2000天地图叠加CGCS2000模型

6
分享 2019-07-11
前情提要:
4.11API在三维加载wkid4490天地图http://zhihu.esrichina.com.cn/article/3942
1.本文是上一篇文章方式1重写BasetileLayer类的方法的沿用,详细解析这一方法技术细节。
2.4.12版本上一篇文章方式2以WebTileLayer加载天地图在Global场景。只需设置webTileLayer属性spatialReference,即可继续使用。

正文:
首先先Po出截图,展示4.12能够直接在Global场景中使用CGCS2000坐标系加载三维并叠加CGCS2000天地图的能力。这是全球场景对CGCS2000坐标系的全面支持。4.11以及之前版本的API全球场景只支持WGS84和web墨卡托坐标系。
412示例图片1.jpg

412示例图片2.jpg

关键技术点有
1.扩展BaseTileLayer类。重写getTileUrl、fetchTile等方法。添加subDomains属性
        // *******************************************************
// Custom tile layer class code
// Create a subclass of BaseTileLayer
// *******************************************************

var TdtLayer = BaseTileLayer.createSubclass({
properties: {
urlTemplate: null,
subDomains: null
},
// generate the tile url for a given level, row and column
getTileUrl: function(level, row, col) {...},

// This method fetches tiles for the specified level and size.
// Override this method to process the data returned from the server.
fetchTile: function(level, row, col) {...}
});
 
2.实现subDomain,利用天地图子域名从t0-t7随机请求切片。
          // generate the tile url for a given level, row and column
getTileUrl: function(level, row, col) {

return this.urlTemplate
.replace("{level}", level)
.replace("{col}", col)
.replace("{row}", row)
.replace("{subDomain}",this.subDomains[Math.round(Math.random() * (this.subDomains.length-1))]);
},

3.请求切片时需要level+1。var url = this.getTileUrl(level+1, row, col);
          // This method fetches tiles for the specified level and size.
// Override this method to process the data returned from the server.//加入options参数解决乱片问题。
fetchTile: function(level, row, col, options) {
// call getTileUrl() method to construct the URL to tiles
// for a given level, row and col provided by the LayerView
var url = this.getTileUrl(level+1, row, col);

// request for tiles based on the generated url
return esriRequest(url, {
responseType: "image",
  //新增下面两句,解决乱片问题
  allowImageDataAccess: true,
  signal: options.signal

}).then(
function(response) {
// when esri request resolves successfully
// get the image from the response
var image = response.data;
var width = this.tileInfo.size[0];
var height = this.tileInfo.size[0];

// create a canvas with 2D rendering context
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
context.drawImage(image, 0, 0, width, height);
return canvas;
}.bind(this)
);
}

4.定义瓦片结构TileInfo。
定义瓦片结构tileInfo.jpg

切片方案的来源是ArcGIS Pro2.4安装目录下D:\Program Files\ArcGIS\Pro\Resources\TilingSchemes\CGCS2000_Geographic_Coordinate_System.xml

5.实例化TdtLayer对象,并作为底图,tk最好用每位开发者自己的。
      var tiledLayer = new TdtLayer({
urlTemplate: "http://{subDomain}.tianditu.com/vec_c/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=vec&STYLE=default&FORMAT=tiles&TILEMATRIXSET=c&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=2137cbbc03b648fedff037ba326b3ab8",
subDomains: ["t0","t1","t2","t3","t4","t5","t6","t7"],
tileInfo:tileInfo,
});
var tdtzjLayer =new TdtLayer({
urlTemplate: "http://{subDomain}.tianditu.com/cva_c/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=cva&STYLE=default&FORMAT=tiles&TILEMATRIXSET=c&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=2137cbbc03b648fedff037ba326b3ab8",
subDomains: ["t0","t1","t2","t3","t4","t5","t6","t7"],
tileInfo:tileInfo,
});
var map = new Map({
spatialReference:{
wkid:4490
},
basemap:{
baseLayers:[tiledLayer],
referenceLayers:[tdtzjLayer]
}
});



注意:
1.发布CGCS2000的场景图层,必须使用ArcGIS Pro2.4版本以上、ArcGIS Enterprise10.7.1以上 或 6月份之后的ArcGIS Online。示例代码调用的Online上的三维服务可能过期了,建议自己发布一个4490的场景使用。
2.ArcGIS Pro2.4安装目录下的切片方案D:\Program Files\ArcGIS\Pro\Resources\TilingSchemes\CGCS2000_Geographic_Coordinate_System.xml使用这个切片方案创建的切片图层TileLayer可以在CGCS2000的全球场景中进行使用。
3.使用webTileLayer方式时,如不指定WebTileLayer的spatialReference在4.11是好用的,而在4.12会报坐标系不一致错误,因为4.12严格按照WebTileLayer默认坐标系为102100,如果不是这个坐标系例如4326和4490,都需要手动指定一下WebTileLayer的spatialReference,代码
附件:
示例代码

9 个评论

学习了!
esri/layers/support/TileInfo 没有找到这个api啊
https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-support-TileInfo.html
请问ArcGIS Enterprise10.6升级到ArcGIS Enterprise10.7.1的话,之前发到10.6的服务怎么迁移呢?
提前备份,然后覆盖安装升级。服务不会受到影响。
好的,谢谢
感谢分享!很有用,膜拜大神><
更正一下,方式1代码如果在4.12或4.13使用,可能会出现切片顺序混乱的情况。
这是因为fetchTile()中的abort signal处理不正确。 最好的方法是将其传递给esriRequest()。
如果在4.11之后的版本使用此代码修改fetchTile下面的内容。主要添加了options并在Request的时候指定 allowImageDataAccess: true,signal: options.signal

fetchTile: function(level, row, col, options) {

var url = this.getTileUrl(level, row, col);

return esriRequest(url, {

responseType: "image",

allowImageDataAccess: true,

signal: options.signal

})

.then(function(response) {

...
继续更正一下:如果是4.15使用webTileLayer方式。需增加fullExtent属性,才能加载出来:
var tiledLayer = new WebTileLayer("http://{subDomain}.tianditu.gov.cn/vec_c/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=vec&STYLE=default&FORMAT=tiles&TILEMATRIXSET=c&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=ac0daf56728bbb77d9514ba3df69bcd3", {
subDomains: ["t0","t1","t2","t3","t4","t5","t6","t7"],
tileInfo: tileInfo,
spatialReference:{wkid: 4490},
fullExtent:{
xmin: -180,
ymin: -90,
xmax: 180,
ymax: 90,
spatialReference: 4490
}

});

要回复文章请先登录注册