arcgis三维球中加载2000坐标系出现错误(The tiling scheme of this layer is not supported by SceneView)
目前我们国家测绘地理信息的坐标体系基准是国家2000坐标系CGCS2000.各类地图组件如OpenLayers、Mapbox、Cesuim和ArcGIS Javascrip等都主要是支持WGS84(wkid=4326)和墨卡托投影坐标系(wkid=102100)两种,对CGCS2000坐标系基本上都不支持。特别是在三维地球展示中基本上都是以WGS84球面坐标系加载,因为三维球是个球,当然是要加载球面坐标系了。(但我知道以前科澜三维是平面的!)所以三维地球都加载不了国内的2000坐标系,要加载也是通过扩展和定制WebTileLayer类进行特殊处理。
ArcGIS Javascript Api 4.*系列一直在朝着二三维一体化的方向发展,其开发商ESRI一直专攻GIS领域,而且是全球头部GIS软件平台,特别是随着ArcGIS 10.1后,其软件产品迭代更新的速度极快。三维产品也是其重点发展对象之一。在今年中旬发布的ArcGIS Javascript Api 4.12版本,不仅性能提升,增加了一些牛逼的功能,更重要的是支持CGCS2000坐标系!!!支持CGCS2000坐标系!!!支持CGCS2000坐标系!!!重要的事情说三遍!
这正是一个喜大普奔的事情,可能是因为ESRI的三维软件开发团队在北京的缘故吧,爱国注意情怀和中国市场总得发挥点作用。但我看到这个信息后,一直想试试,因为我对他支持2000坐标系还是存有疑惑,加载应该没那么容易!咱天朝的标准规范永远是跟着参考国际标准,但必须在上面进行小幅修改,开发人员蛋疼的事情太多了!
1 2 var arcgisUrl = 'http://myserver.net/hserver/rest/services/imageserver2000/MapServer'; 3 4 Layer.fromArcGISServerUrl({ 5 url: arcgisUrl 6 7 }).then(function(layer){ 8 9 var customBasemap = new Basemap({ 10 baseLayers: [layer], 11 title: "ArcGIS REST Service", 12 id: "切片" 13 }); 14 15 var map = new Map({ 16 //basemap: "topo-vector" 17 basemap:customBasemap 18 }); 19 20 var view = new SceneView({ 21 container: "viewDiv", 22 map: map, 23 spatialReference: { 24 "wkid": 4490, 25 "latestWkid": 4490 26 } 27 }); 28 });
上述代码就是我想用我自己的影像地图作为三维球的底图,满怀期待,但最后还是出现我预料中的事情,没有那么简单!
球出来了,提示“The tiling scheme of this layer is not supported by SceneView”,当时没注意看这个信息,以为是坐标系统还是继续不支持,但官方明明说了支持2000坐标系啊,不能够啊!
继续发挥Chrome强大的调试功能,在SceneViewer.js文件中调试出三块关键代码行数,checkIfTileInfoSupportedForViewSR,makeGCSWithTileSize,ompatibleWith。经过调试和研究发现,2000坐标系确实是支持的,但是切片规则(Tiling Scheme)必须跟esri规定的要一样。
天地图切片规则
级别 |
比例尺 |
分辨率(度/像素) |
7 |
4617149.9776692898246525792559 |
0.010986328125 |
8 |
2308574.9888346449123262896279 |
0.0054931640625 |
9 |
1154287.494417322456163144814 |
0.00274658203125 |
10 |
577143.74720866122808157240698 |
0.001373291015625 |
11 |
288571.87360433061404078620349 |
0.0006866455078125 |
12 |
144285.93680216530702039310175 |
0.00034332275390625 |
13 |
72142.968401082653510196550873 |
0.000171661376953125 |
14 |
36071.484200541326755098275436 |
0.0000858306884765625 |
15 |
18035.742100270663377549137718 |
0.00004291534423828125 |
16 |
9017.871050135331688774568859 |
0.000021457672119140625 |
17 |
4508.9355250676658443872844296 |
0.0000107288360595703125 |
18 |
2254.4677625338329221936422148 |
0.00000536441802978515625 |
19 |
1127.2338812669164610968211074 |
0.000002682209014892578125 |
20 |
563.61694063345823054841055369 |
0.0000013411045074462890625 |
esri脚本代码里第一级分辨率固定了 res[0] = 0.703125,下面以及都是一半的比例尺进行处理。下面是两个切片规则的比较。
arcgis javascript api 规定的切片规则 天地图服务切片规则
可以看出我的服务的切片规则和arcgis的恰好错开一个层级,我怀疑是因为我们是从0级开始算,arcgis是从第1级开始算导致的吧。但仔细看看其实两个瓦片规则的分辨率还是有细微的差别的。
q.prototype.compatibleWith = function(a) { if (! (a instanceof q)) { if (q._checkUnsupported(a)) return ! 1; a = new q(a) } if (!a.spatialReference.equals(this.spatialReference) || a.pixelSize[0] !== this.pixelSize[0] || a.pixelSize[1] !== this.pixelSize[1]) return ! 1; var c = Math.min(this.levels.length, a.levels.length) - 1, f = this.levels[c].resolution, b = .5 * f; if (!e.floatEqualAbsolute(a.origin[0], this.origin[0], b) || !e.floatEqualAbsolute(a.origin[1], this.origin[1], b)) return ! 1; b = .5 * f / Math.pow(2, c) / Math.max(this.pixelSize[0], this.pixelSize[1]) * 12; return e.floatEqualAbsolute(f, a.levels[c].resolution, b) }
问题如何处理呢?我的服务是用的已有的缓存切片进行发布的啊!下一步就是操作ArcGIS Server 的信息了,强制去掉一个层级,让其从第1级开始算瓦片吧,这样我猜应该能加载了吧。
请听下会demo汇报......