在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)

准备工作:

以本机为例

  1. 安装Cesium1.4.5,并配置服务(添加地形需要开启Cesium服务)
  2. 安装ArcMap10.4,对应Arcpy为2.7
  3. 安装配置ArcServer(计算结果为server服务)
  4. 安装Flask框架(可以直接在Pycharm里面安装Flask插件)

正文:

1 数据准备

使用工具:arcmap,arcserver,tif转terrain工具;

准备数据:地形数据点云.shp

1.1 地形数据处理

地形数据点云.shp —> 地形.tin  —>  地形.tif  —> 地形.terrain (具体方法就不细说了)

把“地形.terrain”文件夹放到..\Cesium1.45\Apps\mapserver目录下,以备后续使用

在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第1张图片

1.2 发布LOS服务

P.S.在磁盘跟目录新建文件夹ARCGISDATA,存放所有arcmap用到的文件

在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第2张图片

(1)3D分析工具 —> 可见性 —> 通视分析工具 —> 输入“分析路径line.shp”(line不能超出地形.tif范围)

得到通视分析结果(两个.shp文件,一条线,一个点)

在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第3张图片

(2)发布

勾选需要发布的要素

在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第4张图片

发布结果

在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第5张图片

Buffer同理

2 构建前端页面

使用工具:vscode或pycharm(IDE随意),Cseium,ArcServer

2.1加载地形

先启动Cesium服务,以后使用是一定要记得开启Cesium服务,不然地图不会加载的。

在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第6张图片

Cesium使用方法不细说了,这里附上地形加载代码

查看地形是否加载

 2.2加载通视分析,缓冲区分析结果

通视分析和缓冲区分析结果采用异步加载的方式,代码如下

HTML

    
  分析结果加载 




: (经度,纬度)

: (经度,纬度)  


CSS

    .shell {
        position: fixed;
        background-color: rgba(216, 207, 207, 1);
        left: 5%;
        top: 10%;
        width: auto;
        height: auto;
        border: #080202 solid 5px;
    }
    .shell3{
        position: fixed;
        background-color:rgba(216, 207, 207, 1);
        right: 5%;
        bottom: 12%;
        width: auto;
        height: auto;
        border: #080202 solid 3px;
     } 

JS

计算模块:

    //获取鼠标位置
    function getPosition() {
        //得到当前三维场景
        var scene = viewer.scene;
        //得到当前三维场景的椭球体
        var ellipsoid = scene.globe.ellipsoid;
        //设置样式
        var entity = viewer.entities.add({
            label: {
                show: false,
                font: '24px Helvetica',
                fillColor: Cesium.Color.SKYBLUE,
                outlineColor: Cesium.Color.BLACK,
                outlineWidth: 2,
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                pixelOffset: new Cesium.Cartesian2(200, -50)
            }
        });
        var longitudeString = null;
        var latitudeString = null;
        var cartesian = null;
        // 定义当前场景的画布元素的事件处理
        var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
        //设置鼠标移动事件的处理函数,这里负责监听x,y坐标值变化

        handler.setInputAction(function (movement) {
            //通过指定的椭球或者地图对应的坐标系,将鼠标的二维坐标转换为对应椭球体三维坐标
            cartesian = viewer.camera.pickEllipsoid(movement.endPosition, ellipsoid);
            if (cartesian) {
                //将笛卡尔坐标转换为地理坐标
                var cartographic = ellipsoid.cartesianToCartographic(cartesian);
                // //将弧度转为度的十进制度表示
                longitudeString = Cesium.Math.toDegrees(cartographic.longitude).toFixed(6);
                latitudeString = Cesium.Math.toDegrees(cartographic.latitude).toFixed(6);
                //获取地理坐标和高度
                // lonunit_m = cartesian.longitude;
                // latunit_m = cartesian.latitude;
                height = scene.globe.getHeight(cartographic);
                entity.position = cartesian;
                entity.label.show = true;
                // entity.label.text = cartesia + '(' + cartographic.longitude + ', ' + cartographic.latitude + "," + height + ')';
                entity.label.text =
                    'Cartesian: ' + cartesian + '\u00B0' +
                    '\nLon: ' + longitudeString +
                    '\nLat: ' + latitudeString +
                    '\nHeight: ' + height + '\n' + '\n' + '\n' + '\n';
            } else {
                entity.label.show = false;
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
        // 坐标输出
        $(function () {
            $(".No1point").click(function (event) {
                $(window).unbind("dblclick");
                $(window).dblclick(function (event) {
                    $("#aa").html(longitudeString);
                    $("#bb").html(latitudeString);
                    var lon = $("#aa").html();
                    var lat = $("#bb").html();
                    var entity = viewer.entities.add({
                        name: 'start point',
                        position: Cesium.Cartesian3.fromDegrees(lon, lat, height),
                        point: {
                            color: Cesium.Color.YELLOW,
                            pixelSize: 30
                        }
                    });
                });
            });
            $(".No2point").click(function (event) {
                $(window).unbind("dblclick");
                $(window).dblclick(function (event) {
                    $("#cc").html(longitudeString);
                    $("#dd").html(latitudeString);
                    var lon = $("#cc").html();
                    var lat = $("#dd").html();
                    var entity = viewer.entities.add({
                        name: 'end point',
                        position: Cesium.Cartesian3.fromDegrees(lon, lat, height),
                        point: {
                            color: Cesium.Color.RED,
                            pixelSize: 30
                        }
                    });
                });
            });
            $(".No3point").click(function (event) {
                $(window).unbind("dblclick");
                // $(window).dblclick(function (event) {
                //     console.log("结束");
                // });
                $("#result02").html("

 正在计算LOS,请等待...

"); $.ajax({ // url: 'http://localhost:5000/oneLinetoLOS', url: '/oneLinetoLOS02', // url: '/LinestoLOS', data: { a2: $('#aa').html(), b2: $('#bb').html(), c2: $('#cc').html(), d2: $('#dd').html() }, dataType: 'JSON', type: 'GET', success: function () { $("#result02").html("

 计算完成,LOSline03查看

"); } }); }); $(".No4point").click(function (event) { $(window).unbind("dblclick"); $("#result02").html("

 正在计算Buffer,请等待...

"); $.ajax({ url: '/Buffer01', data: { a3: $('#aa').html(), b3: $('#bb').html(), c3: $('#cc').html(), d3: $('#dd').html() }, dataType: 'JSON', type: 'GET', success: function (responseText, status, xhr) { if (responseText != '') { $("#result02").html("

 计算完成,Buffer01查看

"); } else { $('#result02').html("

 error

"); } } }); }); }); } getPosition();

ArcServer服务加载模块:

在F:\ARCGISDATA\python\templates目录下新建3个txt文件

LOSlineremove.txt;Buffer01.txt; 80LOSline01.txt

LOSlineremove.txt

    

Buffer01.txt 

    

80LOSline01.txt 

    

展示模块:

    $(function () {
        $('button#buttonLOS03').click(function (event) {
            $.ajax({
                url: "/80LOSline01.txt",
                success: function (responseText, status, xhr) {
                    if (responseText != '') {
                        $('.LOSscri').html(responseText);
                    } else {
                        $('.LOSscri').html("
  • 没有搜索到
  • "); } } }) }); $('button#buttonBuffer01').click(function (event) { $.ajax({ url: "/Buffer01.txt", success: function (responseText, status, xhr) { if (responseText != '') { $('.LOSscribuffer').html(responseText); } else { $('.LOSscribuffer').html("
  • 没有搜索到
  • "); } } }) }); $('button#LOSCLEAR').click(function (event) { //alert("键盘键松开触发,HTML: " + $('#search').val()); $.ajax({ url: "/LOSlineremove.txt", // 请求路径 // type: "GET", //请求方式 // data: $("form").serialize(),//请求参数 success: function (responseText, status, xhr) {//异步执行成功执行的回调函数 $('.LOSscri').html(responseText);//地图上打标志 } }) }); });

    2.3成果

    3后端Python框架搭建

    FLASK框架教程:http://docs.jinkan.org/docs/flask/quickstart.html

    ArcPy帮助文档:http://desktop.arcgis.com/zh-cn/arcmap/latest/analyze/arcpy/what-is-arcpy-.htm

    3.1地理分析功能编写——通视分析,缓冲区分析,高斯投影

    通视分析

    新建run.py文件,写入以下代码

    #coding:utf-8
    from flask import Flask, render_template, request, jsonify
    import arcpy
    from arcpy import env
    # 自定义函数
    from LonLat2XYpy2 import lonlat2xy
    from Buffer_anatest import buffertest
    
    /////////////////
    
    # 鼠标点击地图,通视分析
    @app.route('/oneLinetoLOS02')
    def oneLinetoLOS02():
        print("LOSana start")
        # point_start = [93342.212,4308755.437]
        # point_end = [93325.940, 4308611.767]
        aa = request.args.get("a2", 0, type=float)
        # print('aa: %s '%aa)
        bb = request.args.get("b2", 0, type=float)
        cc = request.args.get("c2", 0, type=float)
        dd = request.args.get("d2", 0, type=float)
        pointstart = lonlat2xy(aa, bb)
        pointend = lonlat2xy(cc, dd)
        # print('point_start: %s ' % (pointstart,))
        # print('point_end: %s ' % (pointend,))
        line01 = [pointstart, pointend]
        line02 = [pointstart, pointend]
        feature_info = [line01, line02]
        # print('line01: %s '%line01)
        features = []
        for feature in feature_info:
            features.append(
                arcpy.Polyline(
                    arcpy.Array([arcpy.Point(*coords) for coords in feature])))
        # Set workspace
        env.workspace = "F:/ARCGISDATA"
        # Execute Delete
        LOSline01 = "80LOSline01.shp"
        arcpy.Delete_management(LOSline01)
        LOSposition = "80LOSposition01.shp"
        arcpy.Delete_management(LOSposition)
        insurface01 = "alltif1.tif"
        inline01 = features
        outlos01 = "80LOSline01.shp"
        outobs01 = "80LOSposition01.shp"
        # print('in_line01: %s '%inline01)
        arcpy.LineOfSight_3d(insurface01, inline01, outlos01, outobs01)
        print("LOSana end")
        return jsonify(result=line02)

    缓冲区分析

    新建Buffer_anatest.py

    # Import system modules
    import arcpy
    from arcpy import env
    
    def buffertest(p1,p2):
        print("buffertest start")
        env.workspace = "F:/ARCGISDATA"
        line01 = [p1, p2]
        line02 = [p2, p1]
        feature_info = [line01, line02]
        # print('line01: %s ' % line01)
        features = []
        for feature in feature_info:
                features.append(
                    arcpy.Polyline(
                        arcpy.Array([arcpy.Point(*coords) for coords in feature])))
        # Set local variables
        infeatures = features
        outfeatures = "bufferana2.shp"
        bufferDistance = 30
        # Execute Buffer
        arcpy.Buffer_analysis(infeatures, outfeatures, bufferDistance)
        print("buffertest end")
        return 1

    高斯投影函数:(由于在arcmap处理地图时,使用的Xian_80投影坐标系,所以这里需要做经纬度坐标转投影坐标)

    LatLon2XYpy2.py

    # coding:utf-8
    # 参考文献《基于高斯投影的经纬度距离参数修正方法》
    import math
    
    def lonlat2xy(longitude, latitude):
        # WGS-84
        # b = 6356752.3142
        # c = 6399593.6258
        # alpha = 1 / 298.257223563
        # e2 = 0.0066943799013
        # epep = 0.00673949674227
    
        # 80
        a = 6378140.0
        # b = 6356755.288157528
        e1 = 0.00669438499959 
        e2 = 0.00673950181947 
        # alpha = 1 / 298.2570
        B = (math.pi / 180.0) * latitude
        Lcm = 126.0 # Central_Meridian: 126.0
        tsin = math.sin(B)
        tcos = math.cos(B)
        t = math.tan(B)
        A = (math.pi / 180.0) * (longitude - Lcm) * tcos
        C = e2 * pow(tcos, 2)
        M = a * ((1 - e1 / 4.0 - pow(e1, 2) * 3.0 / 64.0 - pow(e1, 3) * 5.0 / 256.0) * B
            - (pow(e1, 2) * 3.0 / 8.0 + pow(e1, 2) * 3.0 / 32.0 + pow(e1, 3) * 45.0 / 1024.0) * math.sin(2.0 * B)
            + (pow(e1, 2) * 15.0 / 256.0 + pow(e1, 3) * 45.0 / 1024.0) * math.sin(4.0 * B)
            - pow(e1, 3) * 35.0 / 3072.0 * math.sin(6 * B))
        N = a / math.sqrt(1 - e1 * pow(tsin, 2))
        # zi dai pian yi - 15535.6 i dont know
        y = - 15535.6 + M + N * t * (0.5 * pow(A, 2) + (5.0 - pow(t, 2) + 9.0 * C + 4 * pow(C, 2)) * pow(A, 4) / 24.0
            + (61.0 - 58.0 * pow(t, 2) + pow(t, 4) + 270 * C -330 * pow(t, 2) * C) * pow(A, 6) / 720.0)
        x = 500000.0 + N * (A + (1.0 - pow(t, 2) + C) * pow(A, 3) / 6.0
            + (5.0 - 18.0 * pow(t, 2) + pow(t, 4) + 14.0 * C - 58.0 * C * pow(t, 2)) * pow(A, 5) / 120.0)
        # x0 = 4309134.741- x
        # y0 = 92760.635 - y
        # return x0, y0,x ,y
        return x, y

    3.2 Flask服务主文件编写

    在run.py中加入以下代码,下面展示完整run.py文件

    #coding:utf-8
    from flask import Flask, render_template, request, jsonify
    import arcpy
    from arcpy import env
    # 自定义函数
    from LonLat2XYpy2 import lonlat2xy
    from Buffer_anatest import buffertest
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello():
        return '

    Hello World

    ' @app.route('/80LOSline01.txt') def txt01(): return render_template('80LOSline01.txt') @app.route('/Buffer01.txt') def txt02(): return render_template('Buffer01.txt') @app.route('/LOSlineremove.txt') def txt03(): return render_template('LOSlineremove.txt') # 地图主界面 @app.route('/Intro_Cesium_python.html') def los(): return render_template('Cesium_python.html') # 鼠标点击地图,通视分析 @app.route('/oneLinetoLOS02') def oneLinetoLOS02(): print("LOSana start") # point_start = [93342.212,4308755.437] # point_end = [93325.940, 4308611.767] aa = request.args.get("a2", 0, type=float) # print('aa: %s '%aa) bb = request.args.get("b2", 0, type=float) cc = request.args.get("c2", 0, type=float) dd = request.args.get("d2", 0, type=float) pointstart = lonlat2xy(aa, bb) pointend = lonlat2xy(cc, dd) # print('point_start: %s ' % (pointstart,)) # print('point_end: %s ' % (pointend,)) line01 = [pointstart, pointend] line02 = [pointstart, pointend] feature_info = [line01, line02] features = [] for feature in feature_info: features.append( arcpy.Polyline( arcpy.Array([arcpy.Point(*coords) for coords in feature]))) # Set workspace env.workspace = "F:/ARCGISDATA" # Execute Delete LOSline01 = "80LOSline01.shp" arcpy.Delete_management(LOSline01) LOSposition = "80LOSposition01.shp" arcpy.Delete_management(LOSposition) insurface01 = "alltif1.tif" inline01 = features outlos01 = "80LOSline01.shp" outobs01 = "80LOSposition01.shp" arcpy.LineOfSight_3d(insurface01, inline01, outlos01, outobs01) print("LOSana end") return jsonify(result=line02) # 鼠标点击地图-缓冲区分析 @app.route('/Buffer01') def Buffer01(): print("Buffer01 start") aa = request.args.get("a3", 0, type=float) bb = request.args.get("b3", 0, type=float) cc = request.args.get("c3", 0, type=float) dd = request.args.get("d3", 0, type=float) pointstart = lonlat2xy(aa, bb) pointend = lonlat2xy(cc, dd) Bufline01 = "bufferana2.shp" arcpy.Delete_management(Bufline01) print("jieguo start") jieguo = buffertest(pointstart, pointend) print("jieguo end") return jsonify(result=jieguo) if __name__ == '__main__': app.run(debug = True)

    3.3 运行run.py

    使用Pycharm打开F:\ARCGISDATA\文件夹

    点击File —> Default Settings... —> 添加Flask模块,添加Python2.7路径

    在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第7张图片

     右击run.py,点击Run‘run’,结果如下

    在前端实现地理分析功能——Cesium,ArcPy,Flask实现通视分析(LOS)与缓冲区分析(Buffer)_第8张图片

     在浏览器输入http://127.0.0.1:5000/Intro_Cesium_python.html

    即可访问网页

    你可能感兴趣的:(学习,总结)