python之arcgis Query空间查询(点线面取交集)

需求:通过arcgisserver根据绘制的几何图形区域(点、线、面)进行空间查询,返回的结果需要与绘制的几何图形区域进行裁剪取交集。

1.python代码

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
# 作者:zy
import json
import requests
import operator
from osgeo import ogr
from osgeo import osr


def arcgisQuery(request, folder, serviceName, layerId):
    # 判断是否是GET请求
    print(request.path)
    global spatialRel, where
    if request.method == 'GET':
        datas = request.GET
        where = datas.get('where')  # 属性查询条件
        geometry = datas.get('geometry')  # 空间查询集合
        geometryType = datas.get('geometryType')  # 空间类型
        spatialRel = datas.get('spatialRel')  # 空间关系
        outFields = datas.get('outFields')  # 输出字段
        returnGeometry = datas.get('returnGeometry')  # 返回几何图形
        returnCountOnly = datas.get('returnCountOnly')  # 返回总数
        pageNum = datas.get('pageNum')  # 页面返回大小
        pageSize = datas.get('pageSize')  # 页面返回大小
        orderByFields = datas.get('orderByFields')  # 排序字段


    # 初始化参数
    if pageNum is None:
        pageNum = 1
    if pageSize is None:
        pageSize = 10
    # mapserver空间关系转esri空间关系
    if spatialRel == 'Intersects':
        spatialRel = 'esriSpatialRelIntersects'
    elif spatialRel == 'Overlaps':
        spatialRel = 'esriSpatialRelOverlaps'
    elif spatialRel == 'Within':
        spatialRel = 'esriSpatialRelWithin'
    else:
        spatialRel = ''
	
	# geometry 入参这里是按照mapserver的传参格式,所以下面需要转换成arcgis支持的格式
    # mapserver几何图形转esri几何图形
    if geometryType == 'Point' and geometry is not None:
        geometry = geometry.replace(' ', ',')
        geometryType = 'esriGeometryPoint'
    elif geometryType == 'Polyline' and geometry is not None:
        split = geometry.split(',')
        outterlist = []
        innerlist = []
        for x in split:
            co = x.split()
            itlist = []
            itlist.append(float(co[0]))
            itlist.append(float(co[1]))
            innerlist.append(itlist)
        outterlist.append(innerlist)
        geometry = {
            "paths": outterlist
        }
        geometryType = 'esriGeometryPolyline'
    elif geometryType == 'Polygon' and geometry is not None:
        split = geometry.split(',')
        outterlist = []
        innerlist = []
        for x in split:
            co = x.split()
            itlist = []
            itlist.append(float(co[0]))
            itlist.append(float(co[1]))
            innerlist.append(itlist)
        outterlist.append(innerlist)
        geometry = {
            "rings": outterlist
        }
        geometryType = 'esriGeometryPolygon'
    else:
        pass

    # 设置url
    url = 'http://192.168.1.9:6080/arcgis/rest/services/' + folder + '/' + serviceName + '/MapServer/' + layerId + '/query'
    print(json.dumps(geometry))

    # 设置查询参数
    params = {
        "f": "json",
        "where": "1=1" if where is None else where,
        "geometryType": geometryType,
        "spatialRel": spatialRel,
        "geometry": json.dumps(geometry),
        "outFields": "*" if outFields is None else outFields,
        "returnGeometry": "true" if returnGeometry == "false" else returnGeometry
    }

    # 将GET请求发送到ArcGIS REST服务并获取响应
    response = requests.get(url, params=params)

    # 处理响应
    if response.status_code == 200 and 'error' not in response.json():
        count = 0
        total = 0
        newfeatures = []
        # 将响应解析为JSON
        data = response.json()
        # 从响应中获取要素
        features = data["features"]
        # print(data)
        mapLayer = {}
        # 创建列表以存储交叉点几何图形
        intersection_geometries = []
        # esri的几何图形转成geojson的几何图形
        geom = params['geometry']
        # 缓冲查询
        # if geometryType == 'esriGeometryPoint' or geometryType == 'esriGeometryPolyline':
        #     geom = geom.Buffer(0.00001)
        # 202305051559修改
        geom_of_geojson = esrijson_2_geojson(json.loads(geom), geometryType)
        wkid = data["spatialReference"]["wkid"]

        # 迭代要素并找到它们与矩形几何图形的交点
        for feature in features:
            fields = []
            intersectionArea = 0
            # 从要素中提取几何图形
            # geometry_json = json.dumps(feature["geometry"])
            geometry = feature["geometry"]
            # print('--', json.dumps(feature), '--')
            # 几何图形的esrijson转geojson
            geojson_geometry = esrijson_2_geojson(geometry, "esriGeometryPolygon")

            # 将 GeoJSON 字符串转换成 OGR Geometry 对象(几何对象),可以用于在 GIS 软件中进行空间分析、地理处理等操作
            geometry = ogr.CreateGeometryFromJson(str(geojson_geometry))

            # 定义feature
            newfeature = {"attributes": feature['attributes']}
            # 裁剪
            if geometry is not None:
                # 创建用于相交的矩形几何图形
                # rect_geometry_json = '{"type": "Polygon", "coordinates": [[[-123, 47], [-122, 47], [-122, 46], [-123, 46], [-123, 47]]]}'

                rect_geometry = ogr.CreateGeometryFromJson(json.dumps(geom_of_geojson))
                # 执行要素几何图形和矩形几何图形的相交
                # print(geometry)
                intersection_geometry = rect_geometry.Intersection(geometry)

                # 如果找到交叉点,请将其几何图形添加到交叉点几何图形阵列中
                if intersection_geometry is not None:
                    intersectionArea = get_intersection_area(intersection_geometry, wkid)
                    intersection_geometries.append(intersection_geometry.ExportToJson())
                    newfeature["geometry"] = intersection_geometry.ExportToJson()
                else:
                    intersectionArea = 0
                newfeature["intersectionArea"] = intersectionArea
                # 加入到features 中
                newfeatures.append(newfeature)
            else:
                print('rect_geometry is None')
        # 分页
        total = len(newfeatures)
        if pageNum is not None and pageSize is not None:
            newfeatures = pagination(int(pageNum), int(pageSize), newfeatures)

        # 封装图层对象
        mapLayer = {"fields": data['fields'], "features": newfeatures,
                    "geometryType": str.replace(geometryType, 'esriGeometry', ''), "total": total,
                    "pageNum": pageNum, "pageSize": pageSize}
        return mapLayer
    else:
        print("Error: request failed.")
        return response.json()


# esrijson转geojson的geometry
def esrijson_2_geojson(geometry, geometryType):
    if "esriGeometryPoint" == geometryType:
        coords = _get_coordinates1(geometry)
        geojson_geometry = {
            'type': 'Point',
            'coordinates': coords
        }
        return geojson_geometry
    elif "esriGeometryPolyline" == geometryType:
        coordinates = geometry['paths'][0]
        geojson_geometry = {
            'type': 'LineString',
            'coordinates': coordinates
        }
        return geojson_geometry
    elif "esriGeometryPolygon" == geometryType:
        coordinates = []
        for ring in geometry['rings']:
            ring_coords = _get_coordinates([ring])[0]
            # 将 "rings" 中的坐标顺序从逆时针方向转换为顺时针方向
            if _is_ccw(ring_coords):
                ring_coords.reverse()
            coordinates.append(ring_coords)
        geojson_geometry = {
            'type': 'Polygon',
            'coordinates': coordinates
        }
        return geojson_geometry


def _get_coordinates(paths):
    """将路径列表转换为坐标列表"""
    coordinates = []
    for path in paths:
        coord_list = [[x, y] for x, y in path]
        coordinates.append(coord_list)
    return coordinates

def _get_coordinates1(geometry):
    coordinates = []
    for s in geometry.split(','):
        coordinates.append(float(s))
    return coordinates

def _is_ccw(coords):
    """判断点集坐标顺序是否为逆时针方向"""
    area = sum(coords[i][0] * coords[i + 1][1] - coords[i + 1][0] * coords[i][1] for i in range(-1, len(coords) - 1))
    return area < 0


def pagination(pageNum, page_size, data_list):
    """
    :param pageNum: 当前页码
    :param page_size: 每页数据量
    :param data_list: 总数据列表
    :return: 当前页码对应的数据列表
    """
    start = (pageNum - 1) * page_size
    end = start + page_size
    return data_list[start:end]


def get_geometry_type(coordinates):
    """
    根据 coordinates 来判断几何对象的类型
    """
    if isinstance(coordinates, list) and len(coordinates) > 0:
        if all(isinstance(c, (float, int)) for c in coordinates):
            # 点类型
            return "Point"
        elif all(isinstance(p, list) and len(p) >= 2 and all(isinstance(c, (float, int)) for c in p) for p in
                 coordinates):
            # 线类型
            return "LineString"
        elif all(isinstance(ring, list) and len(ring) >= 4 and all(
                isinstance(p, list) and len(p) >= 2 and all(isinstance(c, (float, int)) for c in p) for p in ring) for
                 ring in coordinates):
            # 面类型
            return "Polygon"
    return None


# 交集面积
def get_intersection_area(intersection, eosg):
    # 使用 WGS 1984 空间参考计算面积
    spatial_ref = osr.SpatialReference()
    spatial_ref.ImportFromEPSG(eosg)
    intersection.AssignSpatialReference(spatial_ref)
    area = intersection.GetArea()
    # print('intersection--', float(area))
    return area


# 获取arcgis图例
def get_legend(request, floder, serviceName):
    # 获取参数
    if request.method == 'GET':
        # 设置请求 URL 和参数
        url = "http://192.168.1.9:6080/arcgis/rest/services/" + floder + "/" + serviceName + "/MapServer/legend"
        params = {
            "f": "json",  # 返回 JSON 格式
            "dpi": 96,  # 指定 DPI 像素密度
            "dynamicLayers": "",  # 默认情况下,将使用所有动态图层
        }
        # print(floder, serviceName)
        # 发送 GET 请求并处理响应
        response = requests.get(url, params=params)
        if response.status_code == 200:
            legend_json = response.json()  # 获取 JSON 数据
            # 处理JSON数据,例如获取图例符号、标签等信息
            # print(legend_json)
            return legend_json
        else:
            print("Failed to retrieve legend.")
            return None


2.实现效果

注:裁剪前后对比的图形绘制的不一样,仅供查看效果

1. 点

在这里插入图片描述
裁剪前
在这里插入图片描述

裁剪后

在这里插入图片描述

2. 线

在这里插入图片描述

裁剪前
在这里插入图片描述

裁剪后
在这里插入图片描述

3. 面

在这里插入图片描述
裁剪前
在这里插入图片描述

裁剪后
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: b'arcgis engine c#\xe7\x94\xbb\xe7\x82\xb9\xe7\xba\xbf\xe9\x9d\xa2' 是一个基于 C# 的 ArcGIS Engine 应用程序开发框架,可用于创建点、线、面等图形元素来表示地图数据。 ### 回答2: ArcGIS Engine是一款由美国Esri公司开发的软件开发工具包,它可以帮助开发人员将ArcGIS技术集成到自己开发的桌面应用程序和服务器应用程序中。通过ArcGIS Engine,开发人员能够访问和操作地图、空间数据、地理处理和地图服务等GIS资源。 ArcGIS Engine提供了一套完整的GIS工具箱,包括地图浏览、地图查询空间分析、数据编辑、地理编码、网络分析等功能模块,这些模块可以让开发人员快速构建出功能齐全的GIS应用程序。同时,ArcGIS Engine还提供了各种编程接口,包括COM、.NET和Java等,使得开发人员能够使用自己熟悉的编程语言进行开发。 除此之外,ArcGIS Engine还支持多种开发环境,包括Visual Studio、Eclipse、Delphi等,这样使得开发人员可以在自己习惯的开发环境中进行开发。而且,ArcGIS Engine还具备完善的文档和示例库,这些资源可以帮助开发人员更快地了解和掌握如何使用ArcGIS Engine进行开发。 总的来说,ArcGIS Engine是一款非常优秀的GIS软件开发工具包,它可以帮助开发人员快速构建出功能强大的GIS应用程序,提高开发效率和开发质量。如果您是一位GIS开发人员,认真学习和使用ArcGIS Engine将会是您不错的选择。 ### 回答3: ArcGIS Engine C++ ArcGIS Engine是由Esri开发的一个软件平台,可以用于创建和部署专业级GIS应用程序。ArcGIS Engine C++是ArcGIS Engine平台上的一种编程语言,也是一种面向对象的编程语言。它使用C++语言作为主要的开发语言,可以利用ArcObjects来访问和管理地理空间数据,并将它们用于地图制作、空间分析等任务。 ArcGIS Engine C++提供给开发者一个底层的GIS编程框架,可以利用该框架自定义地理空间应用程序的各种组件,比如地图工具,地图符号,地图导航器等等。它可以让开发者自由组合各种地理空间组件,以达到用户所需的功能和体验,从而满足各种地理空间应用的需求。 ArcGIS Engine C++可以采用多种不同的方法开发,包括使用Esri提供的API和开发工具,或使用第三方的开发工具。当开发ArcGIS Engine C++应用程序时,可以使用ArcGIS Desktop应用程序中所使用的相同的技术和工具。同时,它可以与多种编程语言和开发工具集成,可以使开发者与其他编程领域的开发人员进行协同作业,同时也可以轻松地实现外部与内部应用程序之间的交互和数据共享。 总之,ArcGIS Engine C++是一个功能强大的GIS开发框架,可以支持多种应用程序开发模式以及多种编程语言和工具,并提供完整的GIS解决方案。它可以让开发人员轻松快捷地开发出符合用户需求的GIS应用程序,以及实现与其他应用程序无缝衔接的数据共享和交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值