>>> from env_helper import info; info()
页面更新时间: 2023-06-24 11:31:07
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-9-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

7.2. Shapely 中几何要素的操作

7.2.1. 一般的属性与方法

object.area 返回对象的面积

object.bounds 返回一个元组(minx,miny,maxx,maxy),即对象的界限。

object.length 返回对象的长度。

object.geom_type 返回一个字符串,指定对象的几何类型,按照OpenGIS的格式进行。

>>> from shapely.geometry import Point
>>> Point(0,0).geom_type
'Point'

输出点(0,0)的几何类型。

object.distance(other) 返回到其他类型几何对象之间的浮点型最短距离。

>>> Point(0,0).distance(Point(1,1))
1.4142135623730951

object.representative_point() 返回一个在几何对象内的易得到的计算点。

注意:质点的不同, 这个点得到的是依照所需计算量最小而定的,只要在几何对象内部即可。

>>> donut = Point(0, 0).buffer(2.0).difference(Point(0, 0).buffer(1.0))
>>> donut.centroid.wkt
'POINT (0 0)'
>>> donut.representative_point().wkt
'POINT (1.4975923633360986 0.0490085701647802)'

7.2.2.

Point 的构造函数采用坐标位置值或点元组参数。

>>> from shapely.geometry import Point
>>> point = Point(0.0, 0.0)
>>> point.area
0.0
>>> point.length
0.0
>>> point.bounds
(0.0, 0.0, 0.0, 0.0)

一个点的面积为0,长度为0。 它的边界是一个元组(minx,miny,maxx,maxy)

坐标值通过xyz属性获得。

>>> list(point.coords)
[(0.0, 0.0)]
>>> point.x
0.0
>>> point.y
0.0

点的构造同样接受另一个点的实例,从而得到一个副本。

>>> Point(point)
_images/sec2_geometry_18_0.svg

7.2.3. 线

class LineString( coordinates)

LineString的构造采用线性序列,一般采用2个或者多个(x,y[,z])点元组。

构造的LineString对象代表点与点之间的一个或多个直线样条。 有序序列内的点是允许重复的,但可能产生性能损失,应该尽量避免。 一条线可能会自相交,是有效的。

>>> from shapely.geometry import LineString
>>> line = LineString([(0, 0), (1, 1)])
>>> print(line.area)
0.0
>>> print(line.length)
1.4142135623730951
>>> print(line.bounds)
(0.0, 0.0, 1.0, 1.0)
>>> len(line.coords)
2
>>> list(line.coords)
[(0.0, 0.0), (1.0, 1.0)]
>>> LineString(line)
_images/sec2_geometry_25_0.svg

它的边界是一个(minx, miny, maxx, maxy)元组。

定义的坐标属性值通过坐标的属性来获得。也可是坐标的切片。

线的构造同样接受另一个线的实例,从而使用另一个副本。

Point的实例序列不是一个有效的构造函数的参数。线由点来描述, 但不是由点的实例组成。

7.2.4.

class Polygon(exterior[,interiors=None])

多边形构造需要2个位置参数。 第一个位置参数是(x,y[,z])点元组的有序序列, 并且在LinearRing中被认为是准确的。 第二个位置参数是一个可选的、像ring的,无序序列,且位于要素内部, 指定边界或洞的环状序列。

一个有效的多边形的环不能相互交叉, 但可以在一个单点接触。

同样,Shapely不会阻止无效要素的创建, 但是当他们运行时,可能会有异常。

>>> from shapely.geometry import Polygon
>>>
>>> ext = [(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)]
>>> int = [(1, 0), (0.5, 0.5), (1, 1), (1.5, 0.5), (1, 0)][::-1]
>>> polygon = Polygon(ext, [int])
>>> polygon
_images/sec2_geometry_28_0.svg
>>> polygon.is_valid
True
>>> ext = [(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)]
>>> int = [(1, 0), (0, 1), (0.5, 1.5), (1.5, 0.5), (1, 0)][::-1]
>>> from shapely.geometry import Polygon
>>> polygon = Polygon(ext, [int])
>>> polygon
_images/sec2_geometry_32_0.svg
>>> polygon.is_valid
False
>>>
>>> ext = [(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)]
>>> int = [(0.5, 0), (1.5, 0), (1.5, 1), (0.5, 1), (0.5, 0)]
>>> polygon = Polygon(ext, [int])
>>> polygon
_images/sec2_geometry_35_0.svg
>>> polygon.is_valid
False

图片[fig:valinvalpoly]:左边, 是一个有效的内部环和一个外部环接触于一点;右边, 是无效的多边形,因为它的内部环与外部环在多于一个点接触,描述环的点表现为灰色。

图片[fig:twoinval]:左边,多边形是无效的, 因为它的外部环和内部环相触于一条线;右边,是无效的多边形,因为 它的内部环相触于一条线。

多边形的面积不为0,长度不为0。

>>> from shapely.geometry import  Polygon
>>> from shapely.geometry import LinearRing
>>> polygon = Polygon([(0, 0), (1, 1), (1, 0)])
>>> polygon
_images/sec2_geometry_40_0.svg
>>> polygon.area
>>> polygon.length
>>> polygon.bounds
>>> list(polygon.exterior.coords)
>>> list(polygon.interiors)
>>> coords = [(0, 0), (1, 1), (1, 0)]
>>> r = LinearRing(coords)
>>> r
_images/sec2_geometry_43_0.svg
>>> s = Polygon(r)
>>> s.area
0.5
>>> s
_images/sec2_geometry_45_0.svg
>>> t = Polygon(s.buffer(1.0).exterior, [r])
>>> t.area
6.5507620529190325
>>> t
_images/sec2_geometry_47_0.svg

它的x-y边界是一个(minx, miny, maxx, maxy)元组。

组成的环通过内部环和外部环的属性获得。多边形的构件同样接受线和环的实例。 矩形多边形出现,可以方便地使用shapely.geometry.box()函数构建。

shapely.geometry.box(minx,miny,maxx,maxy,ccw=True)

通过提供的边界值来构造矩形多边形, 默认使用逆时针顺序。

例如:

>>> from shapely.geometry import Polygon, box
>>> b = box(0.0, 0.0, 1.0, 1.0)
>>> list(b.exterior.coords)
[(1.0, 0.0), (1.0, 1.0), (0.0, 1.0), (0.0, 0.0), (1.0, 0.0)]

这是在Shapely多边形中惯用的,且第一次出现。

为获得一个已知方向的多边形,用shapely.geometry.polygon.orient()函数:

shapely.geometry.polygon.orient(polygon,sign=1.0)

返回一个给定多边形正式方向的副本。 有符面积(使用正负号的面积)将会有给定的符号。符号1.0表示 产品外部环的坐标将被逆时针导出。

7.2.5. 对线状shapefile进行缓冲操作

对线状shapefile进行缓冲操作与上一节的对点状shapefile进行缓冲类似,本节我们来看一下如何对线进行缓冲操作。

注意看上面的结果。原始的线状shapefile是复杂线的类型。它由三段构成,但却是一个实体。 而结果却是分段生成的。 这样的结果对某些情况是有用的,比如说制图(不能显示边界), 是常用的情况,我们希望生成的结果也是一个多边形, 譬如说面积统计(总面积可不是分段面积的和)。 这个部分当然可以对上面的代码进行修改,但是在后面,我们会介绍shapely的另一个功能。

7.2.6. 线环(LinearRings)

LinearRing 的构造需要一个有序序列 (x, y[, z]) 的点元组。

序列可以通过第一个和最后一个指标的相同值显式关闭。 否则,该序列将通过第一个元组复制到最后一个指数来隐形关闭。与在 LineString 中一样,重复点在有序序列中是被允许的,但可能导致性能损失,应该尽量避免。 一条线环不能跨越它本身,并且不能在一个单点接触。

上图:左边是一条有效线,右边是一个无效的 自接触线。描述环的点显示为灰色。环的边界是空的。

注意:

Shapely不会阻止这种环的创建,但是当他们运行的时候可能会产生异常。

线环的面积为0,但长度不为0。

它的 x-y 边界框是一个 (minx, miny, maxx, maxy) 元组。

定义坐标系值通过坐标属性来获得。

线环的构建同样接受另一条线或线环为实例,因而可以得到另一个副本。

在线环中,点的实例序列不是一个有效的构建参数。

7.2.7. 集合(Collections)

Shapely的一些操作可能会出现多相几何对象的集合导致影响一些Shapely操作。

例如,2条线沿着一条线和一个点相交。 为了表示这类结果,Shapely提供了几何对象的不变集合。 集合可能是同质(多元点等)也可能是异质的。

>>> from shapely.geometry import LineString
>>> a = LineString([(0, 0), (1,1), (1,2), (2,2)])
>>> b = LineString([(0, 0), (1,1), (2,1), (2,2)])
>>> x = a.intersection(b)
>>> from pprint import pprint
>>> len(x)
/tmp/ipykernel_65127/1232873787.py:6: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the geoms property instead to get the  number of parts of a multi-part geometry.
  len(x)
2
>>> type(x)
shapely.geometry.collection.GeometryCollection
image

图 7.1 image

a)是指一条绿色和黄色的线沿着一条线和一个点相交;

b)是指交点(蓝色)是一个包含一条线和一个点的集合。

几何集合的成员通过访问 (geoms)属性, 或通过枚举接口,用inlist()来获得。

>>> from pprint import pprint
>>> pprint(list(x))
>>> from shapely.geometry import MultiPoint
>>> m = MultiPoint([(0, 0), (1, 1), (1,2), (2,2)])
>>> m[:1].wkt
>>> m[3:].wkt
>>> m[4:].wkt
[<shapely.geometry.linestring.LineString object at 0x7f1c28166890>,
 <shapely.geometry.point.Point object at 0x7f1c28154f50>]
/tmp/ipykernel_65127/3428894420.py:2: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the geoms property to access the constituent parts of a multi-part geometry.
  pprint(list(x))
/tmp/ipykernel_65127/3428894420.py:2: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the geoms property instead to get the  number of parts of a multi-part geometry.
  pprint(list(x))
/tmp/ipykernel_65127/3428894420.py:5: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the geoms property to access the constituent parts of a multi-part geometry.
  m[:1].wkt
/tmp/ipykernel_65127/3428894420.py:6: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the geoms property to access the constituent parts of a multi-part geometry.
  m[3:].wkt
/tmp/ipykernel_65127/3428894420.py:7: ShapelyDeprecationWarning: __getitem__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the geoms property to access the constituent parts of a multi-part geometry.
  m[4:].wkt
'GEOMETRYCOLLECTION EMPTY'

同质集合可以被分为好几部分, 带来同一个类型的新对象。

注意:

当可能的话,最好用同质集合类型中的一个来描述下面的。

Collections of Points

class MultiPoint( points)

多元点的构建需要点元组(x,y[,z])序列。

多元点面积为0,长度为0.

>>> from shapely.geometry import MultiPoint
>>> points = MultiPoint([(0.0, 0.0), (1.0, 1.0)])
>>> points.area
>>> points.length
>>> points.bounds
(0.0, 0.0, 1.0, 1.0)

它的x-y边界框是一个(minx, miny, maxx, maxy)元组。

一个多元点集合的成员通过geoms获得或者通过用in或者list()来枚举接口。

>>> import pprint
>>> pprint.pprint(list(points.geoms))
>>> pprint.pprint(list(points))
[<shapely.geometry.point.Point object at 0x7f1c11d4f990>,
 <shapely.geometry.point.Point object at 0x7f1c2cc00ed0>]
[<shapely.geometry.point.Point object at 0x7f1c11df7ed0>,
 <shapely.geometry.point.Point object at 0x7f1c11dda1d0>]
/tmp/ipykernel_65127/253965190.py:3: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the geoms property to access the constituent parts of a multi-part geometry.
  pprint.pprint(list(points))
/tmp/ipykernel_65127/253965190.py:3: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the geoms property instead to get the  number of parts of a multi-part geometry.
  pprint.pprint(list(points))

构件同样需要另一个(多元点) 实例或者点实例的无序序列,从而使用副本。

MultiPoint([Point(0, 0), Point(1, 1)])

Collections of Lines(多元线)

class MultiLineString( lines)

多元线的构建需要 线性元组序列或对象。

图:左边,是一个简单的,不连接的 多元线,右边,是一个不简单的多元线环。定义对象的点 显示为灰色,对象的边界是黑色。 多元环的面积为0,长度不为0。

>>> from shapely.geometry import MultiLineString
>>> coords = [((0, 0), (1, 1)), ((-1, 0), (1, 0))]
>>> lines = MultiLineString(coords)
>>> lines.area
>>> lines.length
>>> lines.bounds
>>> len(lines.geoms)
2

它的x-y边界框是一个(minx, miny, maxx, maxy)元组。

它的成员是线的实例,可以通过geoms得到, 也可以用in或list()命令来迭代协议获得。

>>> pprint.pprint(list(lines.geoms))
>>> pprint.pprint(list(lines))
[<shapely.geometry.linestring.LineString object at 0x7f1c11dba990>,
 <shapely.geometry.linestring.LineString object at 0x7f1c11de8090>]
[<shapely.geometry.linestring.LineString object at 0x7f1c11df7e50>,
 <shapely.geometry.linestring.LineString object at 0x7f1c11debb50>]
/tmp/ipykernel_65127/654406357.py:2: ShapelyDeprecationWarning: Iteration over multi-part geometries is deprecated and will be removed in Shapely 2.0. Use the geoms property to access the constituent parts of a multi-part geometry.
  pprint.pprint(list(lines))
/tmp/ipykernel_65127/654406357.py:2: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the geoms property instead to get the  number of parts of a multi-part geometry.
  pprint.pprint(list(lines))

构造函数可以接受另一个多元线(MultiLineString)的实例, 也可以接受线(LineString)实例的无序序列, 从而得到一个副本。

>>> MultiLineString(lines)
>>> MultiLineString(lines.geoms)
_images/sec2_geometry_68_0.svg

Collection of Polygons(多元多边形)

class MultiPolygon( polygons)

多元多边形的构建需要外部环和洞元组序列元组: [((a1, ..., aM), [(b1, ..., bN),...]), ...]

更清楚地说,构件同样接受线实例的无序序列,从而得到一个副本。

>>> polygon = [(0, 0), (1,1), (1,2), (2,2),(0,0)]
>>> s = [(10, 0), (21,1), (31,2), (24,2),(10,0)]
>>> t = [(0, 50), (1,21), (1,22), (32,2),(0,50)]
>>> from shapely.geometry import Polygon
>>> p_a, s_a, t_a = [Polygon(x) for x in  [polygon, s, t]]
>>> from shapely.geometry import MultiPolygon
>>> polygons = MultiPolygon([p_a, s_a, t_a])
>>> len(polygons.geoms)
>>>
>>> len(polygons)
>>>
>>> polygons.bounds
/tmp/ipykernel_65127/223419790.py:10: ShapelyDeprecationWarning: __len__ for multi-part geometries is deprecated and will be removed in Shapely 2.0. Check the length of the geoms property instead to get the  number of parts of a multi-part geometry.
  len(polygons)
(0.0, 0.0, 32.0, 50.0)
>>> p_a
_images/sec2_geometry_71_0.svg
>>> s_a
_images/sec2_geometry_72_0.svg
>>> t_a
_images/sec2_geometry_73_0.svg
>>> polygons
_images/sec2_geometry_74_0.svg
>>> uu = polygons.geoms
>>> uu[0]
_images/sec2_geometry_76_0.svg

它的x-y边界框是一个(minx, miny, maxx, maxy)元组。

7.2.8. 其他问题

空要素

一个空值要素是指一个点集里恰巧是空集,不是None,如同 set([]) 。 空值要素能够通过调用不带参数的各种构造。

空值要素几乎不支持任何操作。

>>> from shapely.geometry import LineString
>>> line = LineString()
>>> line.is_empty
>>> line.length
>>> line.bounds
>>> line.coords
<shapely.coords.CoordinateSequence at 0x7f1c11db3a50>

可以设置一个空值要素的坐标,在这之后几何坐标不再是空的。

>>> line.coords = [(0, 0), (1, 1)]
>>> line.is_empty
>>> line.length
>>> line.bounds
(0.0, 0.0, 1.0, 1.0)