最近公司需要开发在线的WebGIS工具实现插值等功能,经过我的一番瞎几把研究,我发现目前只有ArcGIS Server发布GP工具可以实现这点(ps:应该是有其他的在线js可以用,只是我没发现)。于是乎就盯着GP服务去了,我为了完成这个功能,我在网上翻遍了博客和论坛,找到的有用的信息实在是太少太少,只能自己琢磨。上一篇已经把插值的代码贴出来了,这次我想把个人心得和另一个GP工具也分享一下。
废话不多说,开始正题:
GP工具:它是由ArcMap等桌面的GIS应用生成的,生成的方式是使用模型构建器将需要的工具和参数拖进去,然后把工具和参数进行关联,最后生成一个流程图。将流程图进行验证,如果成功了就可以进行发布,发布后就是GP工具了。
GP工具的具体制作过程就不赘述了,网上有着相关的教程。
GP工具流程截图
在制作GP工具的时候有几个细节要注意,如果使用插值等工具,需要将插值范围给限定出来--右击IDW选择属性--选择处理范围
--选择你的矢量边界,这样他处理就以边界形状执行;还有要说的就是栅格计算器,在使用时需要注意值的选择,以及公式的使用(我发现数的次方和float类型的数不能相乘,会报错),GP工具在ArcGIS中能正常执行的话,基本上就没有什么问题,最后将需要的参数选为P就行。我这里的点数据是shp格式。
头文件的引用:
//边界数据
//地图数据
我使用的是lealeaflet的开源js加上arcgis api for js,刚开始以为两个不通用,后来发现竟然是一家的东西,好吧果然是相爱一家亲。
地图加载部分js:
/**
* 智图地图内容
*/
var normalm1 = L.tileLayer.chinaProvider('Geoq.Normal.Map', {
maxZoom: 18,
minZoom: 5
});
var normalm2 = L.tileLayer.chinaProvider('Geoq.Normal.Color', {
maxZoom: 18,
minZoom: 5
});
var normalm3 = L.tileLayer.chinaProvider('Geoq.Normal.PurplishBlue', {
maxZoom: 18,
minZoom: 5
});
var normalm4 = L.tileLayer.chinaProvider('Geoq.Normal.Gray', {
maxZoom: 18,
minZoom: 5
});
var normalm5 = L.tileLayer.chinaProvider('Geoq.Normal.Warm', {
maxZoom: 18,
minZoom: 5
});
var normalm6 = L.tileLayer.chinaProvider('Geoq.Normal.Cold', {
maxZoom: 18,
minZoom: 5
});
/**
* 天地图内容
*/
var normalm = L.tileLayer.chinaProvider('TianDiTu.Normal.Map', {
maxZoom: 18,
minZoom: 5
}),
normala = L.tileLayer.chinaProvider('TianDiTu.Normal.Annotion', {
maxZoom: 18,
minZoom: 5
}),
imgm = L.tileLayer.chinaProvider('TianDiTu.Satellite.Map', {
maxZoom: 18,
minZoom: 5
}),
imga = L.tileLayer.chinaProvider('TianDiTu.Satellite.Annotion', {
maxZoom: 18,
minZoom: 5
});
var normal = L.layerGroup([normalm, normala]),
image = L.layerGroup([imgm, imga]);
/**
* 谷歌
*/
var normalMap = L.tileLayer.chinaProvider('Google.Normal.Map', {
maxZoom: 18,
minZoom: 5
}),
satelliteMap = L.tileLayer.chinaProvider('Google.Satellite.Map', {
maxZoom: 18,
minZoom: 5
});
/**
* 高德地图
*/
var Gaode = L.tileLayer.chinaProvider('GaoDe.Normal.Map', {
maxZoom: 18,
minZoom: 5
});
var Gaodimgem = L.tileLayer.chinaProvider('GaoDe.Satellite.Map', {
maxZoom: 18,
minZoom: 5
});
var Gaodimga = L.tileLayer.chinaProvider('GaoDe.Satellite.Annotion', {
maxZoom: 18,
minZoom: 5
});
var Gaodimage = L.layerGroup([Gaodimgem, Gaodimga]);
var baseLayers = {
"智图地图": normalm1,
"智图多彩": normalm2,
"智图午夜蓝": normalm3,
"智图灰色": normalm4,
"智图暖色": normalm5,
"智图冷色": normalm6,
"天地图": normal,
"天地图影像": image,
"谷歌地图": normalMap,
"谷歌影像": satelliteMap,
"高德地图": Gaode,
"高德影像": Gaodimage,
}
var map = L.map("map", {
center: [31.5, 115.9],
zoom: 11,
layers: [image],
zoomControl: false
})
L.control.layers(baseLayers, null).addTo(map);
L.control.zoom({
zoomInTitle: '放大',
zoomOutTitle: '缩小'
}).addTo(map);
//加载镇级地图
var JZmap= L.geoJson(statesData, {
style: function (feature) {
switch (feature.properties.name) {
//case '关庙乡': return { color: "#0000ff" };
default: return { color: "#ff0000" };
}
}
}).addTo(map);
这里实现了可更换地图的功能
接下来是重头戏:实现GP工具的代码
/**
* 调用GP服务
*/
var gpUrl = "http://localhost:6080/arcgis/rest/services/JZtext/CZTR/GPServer/CZTR";//定义GP工具的url
var mapServer="http://localhost:6080/arcgis/rest/services/JZtext/CZTR/MapServer";//该URL需要在ArcGIS server中使用异步的执行模式开启含查看地图服务的结果,位置在该服务的参数中
map.on("click", function (e) {
var query = new esri.tasks.Query();//定义查询对象
//采样点查询地址
var queryTask = new esri.tasks.QueryTask("http://localhost:6080/arcgis/rest/services/JZtext/30points/MapServer/0");
//返回几何对象
query.returnGeometry = true;
//判断条件,必须,一般选择FID >-1即可
query.where = "FID >-1";
//查询出来的字段,用于插值的,要保证是数字类型
query.outFields = ["有效磷"];
//查询出来的时候空间参考定义
query.outSpatialReference = { "wkid": 4326 };
//执行采样点查询方法,query是参数,function是成功后调用的方法
//alert(query);
queryTask.execute(query, function (fs) {
//将返回的几何点数据传输给featureSet
//将数据的格式转换为json
var featureSet = JSON.stringify(fs);
//创建GP服务的参数
var params = {
points: featureSet, //Points是GP的输入参数名称,要和GP服务一直
pointvalue: 10,//插值的字段,名称要和GP一致
};
submitJob1(params);//改函数为异步执行函数,用于执行长时间的服务
})
})
//GP服务调用
function submitJob1(params) {
//使用post的方法向GP服务送请求,并将数据传入进去
/**
* async. 默认是true,即为异步方式,如果是false这个ajax请求为同步请求,success之后打印日志。
* cache:true 如果当前请求有缓存的话,直接使用缓存。如果该属性设置为 false,则每次都会向服务器请求
*/
//由该GP工具每次请求生成的结果都有一个新的文件,所以不使用缓存,以下是ajax的常用请求结果
$.ajax({
type: 'POST',
cache: false,
url: gpUrl+'/submitJob?f=json',//异步请求的样式
dataType: 'json',
async: true,
data: params,
success: function (result) {
var jobId = result.jobId;
//alert(jobId);
if (jobId) {//jobId是ArcGIS给添加上去的工作编号,每次向服务器发送请求的时候就会生成
Getresult1(jobId);//获取结果
}
}
});
}
//获取结果
function Getresult1(jobId) {//将jobId传入方法
//alert(22);
$.ajax({
type: "POST",
cache: false,
url: gpUrl + "/jobs/" + jobId + "?f=json",//判断是否生成结果
async: true,
success: function (result1) {
result1 = eval("(" + result1 + ")");
if (result1.jobStatus === "esriJobSucceeded") {//如果发送请求后的返回值的状态为esriJobSucceeded,说明已经完成操作并生成了结果
showResult1(jobId);//展示结果
}
else {
Getresult1(jobId);
}
}
});
}
//展示地图结果
function showResult1(jobId) {
alert("运算成功!进行渲染");
var mapurl = mapServer + "/jobs/" + jobId;//这里是结果所放置的位置
var envLayer = new L.esri.dynamicMapLayer({ url: mapurl, opacity: 0.75, useCors: false });//新建动态图层
map.addLayer(envLayer);//加入地图
var lenUrl=mapurl+"/legend?f=pjson";//图例的URL
GetLegend(lenUrl);//加载图例
}
function GetLegend(LengendUrl) {
$.ajax({
type: "POST",
cache: false,
url: LengendUrl,
async: true,
success: function (result1) {
//字符串转换为数组
result1 = eval("(" + result1 + ")");
//使用拼接的方法,将图片和数值放入div中
var hmts = '';
//添加图片注释
for (var i = 0; i < result1.layers["0"].legend.length; i++) {
//图片
var image ="data:image/png;base64," +result1.layers["0"].legend[i].imageData;
//标注
var label = result1.layers["0"].legend[i].label
hmts += " " + label + ""
}
hmts += '';
//定义控件
var legend = L.control({ position: 'bottomright' });//将图例的位置放置在右下角
//对图例进行判断,如果已经存在,将先移除之前的图例,避免图上出现多个图例
if ($(".info_legend_div").length > 0) {
$(".info_legend_div").remove();
}
legend.onAdd = function (map) {
var div = L.DomUtil.create('div', 'info_legend_div');//给div赋info_legend_div属性
div.innerHTML += hmts;
return div;
};
legend.addTo(map);//将legend添加进地图
}
})
}
注释我已经写得非常详细了,就不多解释。
我想说一下关于GP传值的问题,我们虽然生成好了GP工具,但我们还需要去知道需要给GP工具传什么参数才是有效值,我使用的json和post的方法。想要验证GP的输入值是否有效可以使用GP工具自带的submitJob来进行测试,将你的数据格式放入其中然后验证其是否正确,如果正确的话会有返回值的。
如果你取到的数据在这里可以正常得到结果,那就是没有问题的,你可以放心大胆的在web端使用。
在进行web端的传值调试时,我走了不少弯路,最后在前辈的帮助下完成了该功能,我得好好去学会ajax和json。
最后奉上几个大佬博客传送门,我在其中学到了不少。
动态插值分析:https://blog.csdn.net/zhoutaotao0509/article/details/52346659?locationNum=7
插值分析结果按指定多边形输出:https://blog.csdn.net/symoriaty/article/details/70145391
欢迎大家来讨论学习!!!