GP服务的使用详解

2022/3/27 23:23:06

本文主要是介绍GP服务的使用详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

最近公司需要开发在线的WebGIS工具实现插值等功能,经过我的一番瞎几把研究,我发现目前只有ArcGIS Server发布GP工具可以实现这点(ps:应该是有其他的在线js可以用,只是我没发现)。于是乎就盯着GP服务去了,我为了完成这个功能,我在网上翻遍了博客和论坛,找到的有用的信息实在是太少太少,只能自己琢磨。上一篇已经把插值的代码贴出来了,这次我想把个人心得和另一个GP工具也分享一下。

废话不多说,开始正题:

GP工具:它是由ArcMap等桌面的GIS应用生成的,生成的方式是使用模型构建器将需要的工具和参数拖进去,然后把工具和参数进行关联,最后生成一个流程图。将流程图进行验证,如果成功了就可以进行发布,发布后就是GP工具了。

GP工具的具体制作过程就不赘述了,网上有着相关的教程。

                                                                                                     GP工具流程截图

在制作GP工具的时候有几个细节要注意,如果使用插值等工具,需要将插值范围给限定出来--右击IDW选择属性--选择处理范围

--选择你的矢量边界,这样他处理就以边界形状执行;还有要说的就是栅格计算器,在使用时需要注意值的选择,以及公式的使用(我发现数的次方和float类型的数不能相乘,会报错),GP工具在ArcGIS中能正常执行的话,基本上就没有什么问题,最后将需要的参数选为P就行。我这里的点数据是shp格式。

GP工具发布成功也就是成功了一半,剩下最难的就是如何在客户端调用GP工具进行值的传入和结果的返回。

开始上代码:

头文件的引用:

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet@1.0.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/esri-leaflet@2.2.1/dist/esri-leaflet.js" ></script>
<script src="js/JZGEOJson.js"></script>//边界数据
<script SRC="js/leaflet.ChineseTmsProviders.js"></script>//地图数据
<link rel="stylesheet" href="https://js.arcgis.com/3.17/esri/css/esri.css">
<script src="https://js.arcgis.com/3.17/"></script>
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>

我使用的是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 = '<div class="Lenged" style="z-index: 1000; position: absolute; bottom: 2px; float: right; right: 2px;  width: 120px; border: 1px solid #C0C0C0; font-size: 12px; font-weight: 600; border-radius: 3px; background-color: white; opacity: 1; margin-right: 20px; padding: 10px">';
                //添加图片注释
                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 += "<div><img src=" + image + " height='20' width='20' /> " + label + "</div>"
                }

                hmts += '</div>';


                //定义控件
                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。

最后奉上几个大佬博客传送门,我在其中学到了不少。

动态插值分析:基于ArcGIS API For JavaScript调用GP服务实现动态插值分析实现_特夜歌的博客-CSDN博客_arcgis js 调用gp服务

插值分析结果按指定多边形输出:ARCGIS10.1 插值分析结果按指定多边形输出_symoriaty的博客-CSDN博客

欢迎大家来讨论学习!!!

本文转自 https://jackie-sun.blog.csdn.net/article/details/81501684?spm=1001.2014.3001.5502,如有侵权,请联系删除。



这篇关于GP服务的使用详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程