前言
前段时间实习工作期间,接到一个需求需要对一些地理数据做空间插值分析,当时想了两种解决方案,一种是直接在前端调用一些空间插值库来计算(如Kriging.js等),另一种就是用ArcGIS发布GP服务,再用ArcGIS APi for JS调用。因为要计算的数据量很大,最后决定用GP服务的方式来实现。现在总结一下当时实现的一些步骤和遇到的坑。
GP服务的发布
- 首先在ArcGIS中的Model Builder中建立一个模型,如图所示,为直接调用了克里金插值工具。其他的参数分别为:Mask 为掩膜提取图层,从环境获取;Extend为分析范围,从环境获取;Zvalue为插值字段,从参数获取;input为输入图层,从参数获取。标注为P的设置为模型参数,即为可选项。 完成后,点击验证模型并保存。
- 点击保存的模型文件,打开输入相关的参数,并运行。因为GP服务必须要先运行一次才能发布。
- 运行后结果如下图所示。注意:前端调用后GP服务显示的分类方法和图层颜色同ArcGIS中的是一样的。所以想显示特定的分类和颜色可以直接在最后一次运行的结果图层的属性中修改。 然后,点击打开地理处理—>结果窗口,在当前会话中右键刚才运行的模型,点击发布为服务。接下来同ArcGIS发布数据服务步骤一样。
- 编辑服务。先分析,然后根据提示编辑一下信息即可,无错误后发布。注意:执行模式中要将“以地图服务查看结果”选上才可以在前端显示结果图层。
- 在ArcGIS Server中查看和测试服务。
GP服务的调用
ArcGIS API for JavaScript 4.12调用GP服务,直接放代码
function doJob() {
require([
"esri/Map", "esri/views/MapView", "esri/layers/MapImageLayer", "esri/layers/FeatureLayer",
"esri/layers/CSVLayer", "esri/tasks/Geoprocessor", "esri/widgets/Legend", "esri/request"
], function (Map, MapView, MapImageLayer, FeatureLayer, CSVLayer, Geoprocessor, Legend, request) {
// 数据
testLayer = new FeatureLayer({
url: "https://localhost:6443/arcgis/rest/services/test/data/MapServer/0"
})
// 边界掩膜数据
maskLayer = new FeatureLayer({
url: 'https://localhost:6443/arcgis/rest/services/test/KrigingTestData/MapServer/2',
tranparent: 0.7
})
var KrigingGP = new Geoprocessor('https://localhost:6443/arcgis/rest/services/gp/Kriging/GPServer/Kriging') //实例化和调用克里金插值服务
// console.log('计算插值')
pattern = $('#patterns option:selected').val()
crop = $('#crops option:selected').val()
el = $('#NP option:selected').val()
var query = testLayer.createQuery() //要素服务中查询数据
query.where = "crop = '"+ crop +"' AND pattern = '"+pattern +"'"
testLayer.queryFeatures(query).then( re => {
console.log(JSON.stringify(re))
if (re.features.length == 0) {
alert('当前指标下无数据,请重新选取')
} else {
let params = {
Zvalue: el,
Input: re,
Extent: maskLayer,
Mask: maskLayer
}
KrigingGP.submitJob(params).then( result => {
if (result.jobStatus == 'job-failed') {
alert('计算插值失败')
// console.log(result)
} else if (result.jobStatus == 'job-succeeded') {
console.log('计算成功')
// console.log(result)
let resultLayer = KrigingGP.getResultMapImageLayer(result.jobId) // 获取插值计算结果图层
// console.log(resultLayer)
resultLayer.opacity = 0.9
resultLayer.title = '插值结果'
map.layers.pop()
map.layers.add(resultLayer) //结果图层添加到地图上显示
}
})
}
})
})
}