9 Working with geometries

这一章和前面的地理处理等章节相比,可能更多的需要理解。

来源

9.1 介绍

本章介绍如何使用几何图形包括如何从现有要素中读取几何对象的属性以及如何根据坐标信息创建新几何对象。
单个要素,例如点、折线和多边形,可以分解为它们的顶点。
几何是通过从这些顶点的坐标列表创建几何对象来编写的。能够读取和写入几何图形提供了对要素类、要素以及构成要素的部分和顶点的详细控制。

9.2 使用几何对象与标注

要素类中的每个要素都由折点组成。顶点是一对 x,y 坐标。可以使用几何对象访问这些顶点,例如点、折线和多边形。您可以通过在要素类的几何字段(通常名为 Shape)上设置光标来处理几何对象及其属性。设置游标是通过使用几何标记而不是字段名称来完成的。以下示例说明了如何使用搜索光标通过标记 SHAPE@ 读取要素类的几何对象

import arcpy
fc = "C:/Data/roads.shp"
with arcpy.da.SearchCursor(fc, "SHAPE@") as cursor:
    <processing>

回想一下第 8 章,当使用游标释放任何潜在的数据锁时,最好使用 with 语句。或者,可以将相同的脚本编写如下:

import arcpy
fc = "C:/Data/roads.shp"
cursor = arcpy.da.SearchCursor(fc, "SHAPE@") as cursor:
<processing>

SHAPE@ 可以访问完整的几何对象及其所有属性。访问完整的几何对象可能很耗时。因此,使用大型数据集的完整几何对象的脚本可能会变得相对较慢。如果您只需要几何的特定属性,则可以使用特定几何标记作为访问这些几何属性的快捷方式。例如,SHAPE@XY 返回代表特征质心的 x,y 坐标元组,SHAPE@LENGTH 返回特征长度。使用这些通常比使用 SHAPE@ 访问完整的几何对象更快。以下示例确定折线要素类中所有要素的组合长度: 如果不使用 with 语句,光标对象通常会在脚本结尾处被删除 - 即 del cursor - 尽管搜索不需要删除游标,因为它不会导致排他锁

import arcpy
fc = "C:/Data/roads.shp"
with arcpy.da.SearchCursor(fc, "SHAPE@LENGTH") as cursor
    length = 0
    for row in cursor:
        length += row[0]
        print(length)

在此示例中,搜索光标使用 SHAPE@LENGTH 几何标记。当只需要特定属性时,使用几何标记就足够了。您可以将几何标记视为特定属性的快捷方式。更复杂的操作以及创建新几何体需要使用 SHAPE@ 使用完整的几何体对象。

9.3 理解几何对象

要素类中的每个要素都由一个或多个定义点、折线或面要素的折点组成。对于点要素类,每个点要素都由一个顶点组成。折线和面要素由多个折点组成。每个顶点是由一对 x,y 坐标定义的位置。该图说明了点、折线和多边形是如何由笛卡尔坐标空间中的顶点定义的。这些示例只是概念性的,并不代表真实世界的坐标系。
在这里插入图片描述
ArcPy 有几个类用于处理几何对象。首先,通用 arcpy.Geometry 类创建几何对象。 Geometry 类的一般语法如下:

arcpy.Geometry(geometry, inputs, {spatial_reference}, 
               {has_z}, {has_m})

几何参数将几何类型指定为字符串,即点、折线、多边形或多点。输入参数表示用于创建对象的坐标(即顶点)。
这些顶点可以是 Point 或 Array 对象的形式,本节稍后将对此进行解释。

几何对象通常用于在内存中执行任务,而不是创建新的临时要素类或修改现有要素类。考虑以下使用 Geometry 类来确定要素类中所有要素的总长度的示例代码:

import arcpy
fc = "C:/Data/roads.shp"
geoms = arcpy.CopyFeatures_management(fc, arcpy.Geometry())
length = 0
for geom in geoms:
    length += geom.length
print(length)

关于这个例子的一些观察是有序的。 Geometry 类有两个必需参数,但没有明确说明。相反,参数是隐式提供的,因为 arcpy.Geometry() 是地理处理工具的输出参数。因此,该代码适用于任何类型的几何图形。有点直观的是,名为 road.shp 的折线要素类具有长度属性,但相同的代码也适用于点和面要素。对于多边形,结果是多边形要素的周长之和。在点的情况下,结果为零。所有几何对象都具有相同的属性和方法,但有些不适用于特定类型,包括点要素的面积和长度。
尽管通用 Geometry 类可以创建任何类型的几何,但 ArcPy 有四个其他几何类:MultiPoint、PointGeometry、Polygon 和 Polyline。此外,ArcPy 使用另外两个类来帮助构建几何:Array 和 Point。这些类之间的关系需要一些解释。
最基本的对象是 Point 对象,它是使用 Point 类创建的。此对象等效于单个顶点,用于创建所有其他几何对象。 Point 类的一般语法是:

arcpy.Point({X}, {Y}, {Z}, {M}, {ID})

不需要任何参数,这允许您创建一个空的 Point 对象并稍后填充其属性。但是,从逻辑上讲,除非您至少有一个 x,y 坐标对,否则使用 Point 对象是没有意义的。以下示例创建一个 Point 对象:

point = arcpy.Point(4.900160, 52.378424)

如示例所示,Point 对象通常不超过一对 x,y 坐标。在此示例中,坐标表示荷兰阿姆斯特丹中央车站的纬度和经度,但重要的是要认识到空间参考不是 Point 类的一部分。
Point 对象不是几何对象,但它可以用来构造几何。这个任务可以使用 PointGeometry 类来完成。这个类的一般语法是

arcpy.PointGeometry(inputs, {spatial_reference}, {has_z}, {has_m})

请注意,除了几何参数之外,此语法与 Geometry 类的语法相同,几何参数隐含在此类的几何对象类型中,即点特征。 PointGeometry 类具有空间参考参数。以下代码说明了 Point 对象如何使用 PointGeometry 类构造几何对象:

point = arcpy.Point(4.900160, 52.378424)
pointgeo = arcpy.PointGeometry(point, 4326)

空间参考由具有 1984 年世界大地测量系统 (WGS84) 基准的地理坐标系 (GCS) 的工厂代码指示。作为替代方案,可以使用名称“GCS_WGS_1984”。创建几何对象后,可将其用于地理处理操作或在要素类中创建新要素。第 9.7 节和第 9.9 节讨论了这些示例。
识别 Point 和 PointGeometry 对象之间的区别很重要。 Point 对象仅由一对 x,y 坐标组成,并且具有有限数量的属性和方法。例如,无论坐标的性质如何,它都没有空间参考。 PointGeometry 对象是一个几何对象,因此具有更多的属性和方法,包括空间参考。

折线和面要素由多个顶点组成,并使用两个或多个 Point 对象构建。为了便于处理多个 Point 对象,ArcPy 使用 Array 类。此类专门用于构造折线和多边形几何对象。以下示例显示了如何使用两个 Point 对象来创建一个 Polyline 对象:

point1 = arcpy.Point(0, 0)
point2 = arcpy.Point(100, 100)
array = arcpy.Array([point1, point2])
polyline = arcpy.Polyline(array)
print(polyline.length)

在此示例中,Array 对象是使用两个 Point 对象的列表创建的。从概念上讲,Array 对象就像一个列表,但它专门用于存储 Point 对象而不是其他类型的元素。
Array 对象创建一个 Polyline 对象。因为它是一个几何对象,所以您可以使用它的属性,例如长度。由于未设置空间参考,因此未定义长度属性的单位。
您可以创建多个几何对象并直接使用几何对象的方法进行比较。例如,以下代码创建两个 Polyline 对象并确定它们是否相互交叉:

import arcpy
point1a = arcpy.Point(0,0)
point1b = arcpy.Point(100, 100)
point2a = arcpy.Point(100, 0)
point2b = arcpy.Point(0, 100)
array1 = arcpy.Array([point1a, point1b])
array2 = arcpy.Array([point2a, point2b])
polyline1 = arcpy.Polyline(array1)
polyline2 = arcpy.Polyline(array2)
print(polyline1.crosses(polyline2))

结果打印为 True,因为两条折线在位置 (50, 50) 处相交。
虽然这两条折线很简单并且不使用真实世界的坐标系,但它们说明了几何对象的多功能性。无需将任何文件写入磁盘,也无需运行任何地理处理工具,即可确定几何对象之间的几何属性和关系
创建 Polygon 对象的语法类似,但一个有意义的多边形要素至少需要三个 Point 对象,如下所示:(三个点围一个面)

import arcpy
point1 = arcpy.Point(0,0)
point2 = arcpy.Point(100, 0)
point3 = arcpy.Point(50, 50)
array = arcpy.Array([point1, point2, point3, point1])
polygon = arcpy.Polygon(array)
print(polygon.area)

此示例中的 Array 对象由四个 Point 对象组成,因为重复起始顶点以确保正确闭合。这类似于在 ArcGIS Pro 中手动编辑要素时关闭面。
到目前为止的示例使用简单的特征,但它们说明了几何对象的关键点。
坐标值用于以 Point 对象的形式创建顶点。这些 Point 对象用于使用 PointGeometry 类构造几何对象。使用 Array 类组合多个 Point 对象,该类用于使用 Polyline 和 Polygon 类构造几何对象。到目前为止,一个简化的假设是几何对象仅由一个部分组成。 9.5 节讨论多部分对象。

使用几何对象有几个好处。首先,通过创建几何对象,您可以将要素写入要素类。一个典型的场景是从坐标值表中创建要素。
其次,几何对象可用于地理处理操作。您可以在内存中创建几何对象并直接在地理处理工具中使用它们,而不是创建临时要素类来保存几何。下一节将探讨如何利用对几何对象的理解来读取现有特征的属性;接下来是关于如何将新几何写入要素类的部分。

注意:本章的重点是使用 arcpy.da 游标处理几何对象,这使得处理单个要素的顶点成为可能。这种方法为读取和写入几何图形提供了细粒度的控制,但它可能很麻烦。您还可以使用其他格式处理几何图形。几何对象具有几个只读属性,可将几何转换为不同的格式,包括 JSON、知名二进制 (WKB) 和知名文本 (WKT)。这些格式被开源 Python 包广泛用于处理地理空间数据。可以使用这些格式创建几何图形。

9.4 读取几何对象

您对几何对象的理解有助于阅读几何。可以使用搜索光标访问现有要素类的几何对象(及其顶点)。搜索光标设置在几何字段上,可用于返回整个几何对象(即 SHAPE@)或通过几何标记(例如 SHAPE@LENGTH)返回特定属性。使用搜索光标时,点要素会返回由 Point 对象组成的 PointGeometry 对象。其他要素类型(例如,折线和多边形)为每个要素返回多个 Point 对象。由于要素可以有多个部分,因此将这些点对象组织成折线和多边形有些复杂。

读取点要素类

在以下示例中,搜索光标和 for 循环遍历点要素类的行。几何标记检索点特征的 x,y 坐标,然后将其打印出来。脚本如下:

import arcpy
fc = "C:/Data/Demo.gdb/marinas"
with arcpy.da.SearchCursor(fc, ["SHAPE@XY"]) as cursor:
    for row in cursor:
       x, y = row[0]
       print("{0}, {1}".format(x,y))

请注意,在此示例中,SHAPE@XY 标记返回坐标元组,这些坐标使用 x, y = row[0] 分配给变量 x 和 y。另一种方法是在设置光标时使用两个单独的标记——即,[“SHAPE@XY”,“SHAPE@”],然后使用 x = row[0] 和 y = row[1]。
要素类由点要素组成,每个点都有一对 x,y 坐标。在要素类上运行脚本会返回 x,y 坐标对列表,如下所示:

3069300.0599277616, 10129811.119859427
3047366.5099629313, 10121935.790137678
3047945.780129835, 10126083.489847511
3049913.8099864274, 10129118.71999751
3056989.9798891693, 10125885.980071917
3058335.0999023467, 10133584.949910179

点要素类相对简单,因为每个要素只有一个点对象。

折线和多边形由每个要素的多个 Point 对象组成。这些 Point 对象组织在一个 Array 对象中,如上一节所述。要使用这些 Array 对象,需要进行额外的迭代。在典型的脚本中,一个 for 循环遍历表中的行,第二个 for 循环遍历每个数组对象中的 Point 对象。

读取线要素

在以下示例代码中,for 循环遍历 shapefile 中的行。对于每一行,都会打印唯一标识符字段的值——没有它,您将无法分辨每个折线要素的起点和终点。对于每一行,获取一个几何对象**,getPart() 方法**为几何的第一(也是唯一)部分获取一个 Point 对象数组。下一节将更详细地讨论使用多个部件。 for 循环遍历 Array 对象中的所有 Point 对象并打印 x,y 坐标。代码如下:

import arcpy
arcpy.env.workspace = "C:/Data/Demo.gdb"
fc = "pipes"
with arcpy.da.SearchCursor(fc, ["OID@", "SHAPE@"]) as cursor:
for row in cursor:
print("Feature {0}: ".format(row[0]))
for point in row[1].getPart(0):
print("{0}, {1}".format(point.X, point.Y))

此示例代码假定没有多部分功能。

此外,请注意使用字符串“OID@”来引用唯一标识符字段。对于 shapefile,此字段通常称为 FID,对于地理数据库要素类,通常称为 OBJECTID。 “OID@”字符串不是确定正在使用的数据格式,而是用作指向唯一标识符的标记,而不考虑字段名称。例如,如果将字符串“FID”用于地理数据库要素类,则搜索光标会返回错误 RuntimeError:指定的列不存在。 OID@ 的使用使代码更加健壮。 shapefile 和地理数据库要素类之间的另一个区别是 FID 值以 0 开头,而 OBJECTID 值以 1 开头。此编号系统与此处的代码示例无关,但打印输出在所使用的数据格式的基础。

图中所示的管道要素类具有突出显示的顶点 - 这些顶点对于折线要素通常不可见。要素类由三条折线组成,它们在一个位置具有重合几何。
在这里插入图片描述
在管道要素类上运行上述脚本时,将打印三个要素中每个要素中顶点的 x,y 坐标列表。表示管道交叉点的重合顶点用阴影表示,强调如下:

Feature 1:
3114489.914429754, 10071031.541552678
3114455.196651429, 10071041.880114675
Feature 2:
3114457.9210554212, 10071051.170778498
3114455.196651429, 10071041.880114675
Feature 3:
3114455.196651429, 10071041.880114675
3114435.4978719205, 10071047.747557

关于此脚本,还应注意其他几件事。首先,getPart() 方法使用零 (0) 索引。该方法仅返回几何对象的第一部分,其索引为零 (0)。对于常规(即单部分)要素类,第一部分也是唯一的部分。其次,该脚本可用于折线和面要素类,但不能用于点要素类。

读取几何的最后一个示例是多边形要素类。

该脚本与之前的脚本基本相同,因为它适用于折线和面要素类。唯一的微小变化是打印输出的(可选)格式:

import arcpy
arcpy.env.workspace = "C:/Data/Demo.gdb"
fc = "parcels"
with arcpy.da.SearchCursor(fc, ["OID@", "SHAPE@"]) as cursor:
for row in cursor:
print("Feature {0}: ".format(row[0]))
for point in row[1].getPart(0):
print("{0:.2f}, {1:.2f}".format(point.X, point.Y))

打印格式使用格式代码来指定输出的精度。这里使用的格式代码是 (0:.2f) 和 (1:.2f),其中 2 表示精度的数字,f 表示浮点数。此格式代码将打印输出限制为两位小数,以使输出更易于阅读。
脚本中使用的要素类由单个地块组成,并在图中显示,并添加了顶点以进行强调。起始顶点以不同的颜色显示。
在这里插入图片描述
在宗地要素类上运行脚本时,将打印顶点的 x,y 坐标列表。

Feature 1:
427837.21, 5450864.65
427837.80, 5450898.34
427842.31, 5450898.89
427846.84, 5450899.18
427851.39, 5450899.24
427859.98, 5450899.11
427859.42, 5450867.42
427837.21, 5450864.65

第一个和最后一个 x,y 坐标对是相同的。对于面要素,起点和终点重合,因此它们的坐标相同。

接下来的两节回顾了使用要素几何时的两种复杂情况:多部分要素和带孔的多边形。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值