• 在ArcGIS Earth中自动化的绘制复杂图形


    引言

    在地图中精确的绘制一系列的图形一直是一个让人头疼的问题,一个个的输入坐标烦不胜烦,而且绘制完毕之后,如何保存分享也是问题。
    这里我们将介绍一种简单的方法来解决这个问题:使用ArcGIS Earth 1.16版本AutomationAPI的drawings接口,可以在地图上精确的绘制一系列的图形。
    效果如下:(原图审核不过,我就用这幅图片代替)

    在这里插入图片描述

    ArcGIS Earth

    ArcGIS Earth作为一款免费的、轻量级的、易于使用的交互式三维地球平台,给非GIS专业的用户带来友好又便捷的使用体验。使用ArcGIS Earth不仅可以免费使用Esri提供的全球地形、影像服务,足不出户浏览探索地球;还可以添加自己数据,实现在三维空间内的数据展示,并满足用户绘制要素、量测、分享等需求。

    今天ArcGIS Earth Desktop 1.16 版本正好发布啦,从这个页面就能看到它的新特性:

    • New templates for drawing lines and polygons have been added to support creating predefined shapes.
    • Filter is supported to define expressions for determining which features are shown on the map.
    • Remember certificate for PKI portal
    • No Basemap option
    • Summary tab for layer properties
    • Automation API:support drawings
    • Save/Save as in combination

    这里就先暂时不翻译了,后面应该会有官方的介绍的。就先列一下相关的链接吧:

    Drawings API

    ArcGIS Earth Automation API就是在Earth运行的时候可以启动一个后台服务,用户可以以REST的方式和ArcGIS Earth Desktop通讯,在1.16版本里面新增了一个drawings功能,支持向ArcGIS Earth 发送POST DELETE等请求来绘制和删除图形。
    然后通过软件原本的分享和保存功能,可以将图形以KML的形式保存到本地,并且可以将KML文件通过Arcgis online或其他形式分享给其他用户。

    接口的详细说明在这个页面。添加图形的过程大致就是把一个json格式的点线面传给ArcGIS Earth。点图形的json格式示例如下:

    {
      "id": "4b75ea4a-e10f-d676-307d-aa945e2a0712",
      "visible": true,
      "title": "addPoint",
      "geometry": {
          "x": -100,
          "y": 40,
          "spatialReference": {"wkid": 4326}
          },
       "symbol": {
           "type": "picture-marker",
           "url":"https://static.arcgis.com/images/Symbols/Shapes/BlackStarLargeB.png",
           "size": "64px"
          },
       "labelSymbol":{
            "type":"text",
            "color": [76,115,0,255],
            "size":12
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    也是由geometrysymbol等字段组成的json。

    开启autoamtion api

    那么如何开启并使用drawings功能呢?这里简单介绍一下吧,需要打开ArcGIS Earth进行一下设置

    在这里插入图片描述

    1. 从工具栏点击设置
    2. 从设置面板选择高级
    3. 滑动滚动条到Automation API区域,并勾选Enable Automation API
    4. 从Sample页面和Help页面获取更多信息

    打开sample页面之后,可以用下面的方法进行绘制:

    在这里插入图片描述

    同样,打开helpe页面,可以使用swagger提供的功能了解API的详情或者Try it out。

    官方还有一个repo来提供了.NET的客户端,可以使用这个客户端来调用API。

    earth-api for python

    通过上面的介绍,我们已经简单的了解了ArcGISEarth Desktop的相关功能, ArcGIS Earth Automation API的基本原理和使用方法。

    但如果要高效的进行绘制,还是需要通过一些封装好的接口来实现的。这里介绍一下python的接口。

    在这个页面可以看到arcgis-earth-automation-api for python的基本的介绍。

    在我们完成了上面的步骤开启了automation api之后,我们可以使用earth-api for python来进行绘制。

    首先进行安装

    pip install earth-api
    
    • 1

    然后已获取相机位置为例:

    from earth_api import EarthAPI
    earth = EarthAPI()
    status_code, camera = earth.get_camera()
    
    • 1
    • 2
    • 3

    通过上述三行代码就能获取相机的基本信息了,是不是非常简单呢?下面对这三行代码做一个简单地说明:

    from earth_api import EarthAPI
    
    • 1

    这行代码是从earth_api这个库中引入了EarthAPI类,EarthAPI类中封装了所有的接口。

    earth = EarthAPI()
    
    • 1

    这行代码创建了earth api的对象,传入参数还支持api的版本号等。

    status_code, camera = earth.get_camera()
    
    • 1

    上面一行代码是通过api来获取相机位置,实际上是通过该PythonAPI向ArcGIS Earth发送了一个GET Camera的请求。然后返回了状态码和camera的对象,在此camera对象以dict的形式表现。

    稍复杂的绘制

    通过上面的介绍,想必大家已经对earth-api的使用有了基本的了解了。下面我们就以开头的图形为例来说明一下如何自动化的绘制图形。

    首先,我们需要从文章中复制出区域的基本信息。

     a1 = "北纬25°15′26″、东经120°29′20″,北纬24°50′30″、东经120°05′45″,北纬25°04′32″、东经119°51′22″,北纬25°28′12″、东经120°14′30″四点连线。"
        a2 = "北纬26°07′00″、东经121°57′00″,北纬25°30′00″、东经121°57′00″,北纬25°30′00″、东经121°28′00″,北纬26°07′00″、东经121°28′00″四点连线。"
        a3 = "北纬25°34′00″、东经122°50′00″,北纬25°03′00″、东经122°50′00″,北纬25°03′00″、东经122°11′00″,北纬25°34′00″、东经122°11′00″四点连线。"
        a4 = "北纬22°56′00″、东经122°40′00″,北纬23°38′00″、东经122°51′00″,北纬23°38′00″、东经123°23′00″,北纬22°56′00″、东经123°09′00″四点连线。"
        a5 = "北纬21°14′00″、东经121°33′00″,北纬21°33′00″、东经121°18′00″,北纬21°07′00″、东经120°43′00″,北纬20°48′00″、东经120°59′00″四点连线。"
        a6 = "北纬22°43′00″、东经119°14′00″,北纬22°10′00″、东经119°06′00″,北纬21°33′00″、东经120°29′00″,北纬22°09′00″、东经120°32′00″四点连线。"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后简单的提取出经纬度信息,由于上面的描述格式比较统一,我就用简单的方式来提取出经纬度信息吧。

    # get degress, minutes, seconds from string
    def get_degress_minutes_seconds(desc_string):
        # get degress
        degress = desc_string.split('°')[0][2:]
        # get minutes
        minutes = desc_string.split('°')[1].split('′')[0]
        # get seconds
        seconds = desc_string.split('°')[1].split('′')[1].split('″')[0]
        return degress, minutes, seconds
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接着把经纬度信息构建为多边形的几何体,这里面我就以rings作为基本的几何单元吧。

    首先将度分秒转换为度。

    # convert degress, minutes, seconds to decimal degree
    def convert_degress_minutes_seconds_to_decimal_degree(degress, minutes, seconds):
        decimal_degree = float(degress) + float(minutes) / 60 + float(seconds) / 3600
        return decimal_degree
    
    • 1
    • 2
    • 3
    • 4

    然后构建ring,ring是首尾相连的线段。

    def consturct_ring(lat_array, lon_array):
        ring = []
        for i in range(len(lat_array)):
            ring.append([lon_array[i], lat_array[i]])
        ring.append([lon_array[0], lat_array[0]])
        return ring 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    最后我们把这些代码组合起来,实现从句子中获取了ring的信息。

    # get location from string
    def get_location_from_string(desc_string):
        # split string by '、' and ','
        sections = re.split(',|、', desc_string)
    
        lat_array = []
        lon_array = []
    
        for s in sections:
            if '北纬' in s:
                degress, minutes, seconds = get_degress_minutes_seconds(s)
                lat = convert_degress_minutes_seconds_to_decimal_degree(degress, minutes, seconds)
                lat_array.append(lat)
            if '东经' in s:
                degress, minutes, seconds = get_degress_minutes_seconds(s)
                lon = convert_degress_minutes_seconds_to_decimal_degree(degress, minutes, seconds) 
                lon_array.append(lon)
        return consturct_ring(lat_array, lon_array)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    接着我们要创建一个arcgis earth automation api能识别的drawing对象,一会儿就把这个对象给传递给ArcGIS Earth。

    def generate_drawings_from_string(name, desc_string):
        ring = get_location_from_string(desc_string)
        drawing = {
            "visible": True,
            "title":name,
            "geometry":{
                "rings":[
                        ring 
                ],
                "spatialReference":{
                    "wkid":4326
                }
            }
        }
        return drawing
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    最后,我们需要调用earth-api将该对象添加到地图上。

    earth_api = EarthAPI()
    earth_api.add_drawing(drawing)
    
    • 1
    • 2

    然后就实现了文章开头的效果。完整代码在这个链接,大概81行代码吧(含空行)

    最后,使用earth-api给大家比个❤送给大家吧。

    使用earth-api绘制爱心

    今天就先到这里吧,更详细的介绍以后再慢慢展开。谢谢观看。

  • 相关阅读:
    C语言力扣刷题13——最大子数组和[线性动态规划]
    【OJ题目】选择客栈 | 公司新表
    【北大核心&CSCD期刊】生物特征识别论文投稿经历
    065:mapboxGL在一个图层中随机添加100个标记(marker)
    Linux-进程调度(CFS)
    会话固定攻击
    Flutter 小技巧之 3.16 升级最坑 M3 默认适配技巧
    【Linux】多路IO复用技术③——epoll详解&如何使用epoll模型实现简易的一对多服务器(附图解与代码实现)
    vue 常用开发父子组件的通信
    【运维工具】当你的老板站在你背后,看你处理故障......
  • 原文地址:https://blog.csdn.net/iuhsihsow/article/details/126173251