目录

上一个主题

5.2. Shapely 中几何要素的操作

下一个主题

5.4. 生成新几何对象的方法

关注公众号


常见问题

  1. Windows下的安装说明
  2. Jupyter免费在线实验环境
  3. 勘误与补充


>>> from helper import info; info()
页面更新时间: 2020-11-05 21:26:09
操作系统/OS: Linux-4.19.0-11-amd64-x86_64-with-debian-10.6 ;Python: 3.7.3

5.3. 谓词

谓词,用来描述或判定客体性质、特征或者客体之间关系的词项。根据《现代汉语》的定义,汉语的体词包括名词,数词,量词;汉语的谓词包括动词和形容词。

5.3.1. 一元谓词

标准的一元谓词被作为只读属性实施。

所有的例子将会被显示。

一般的一元谓词

object.has_z: 如果要素不仅有x和y,还有z,则返回为‘True’。

>>> from shapely.geometry import Point
>>> Point(0, 0).has_z
>>> Point(0, 0, 0).has_z
True

object.is_ccw : 如果坐标是逆时针的,返回为真 (用正面标记的面积来框定区域)。这种方法仅适用于线性对象。

LinearRing([(1,0), (1,1), (0,0)]).is_ccw

非预期方向的环可以像这样反转:

>>> from shapely.geometry import LinearRing
>>> ring = LinearRing([(0,0), (1,1), (1,0)])
>>> ring.is_ccw
>>> ring.coords = list(ring.coords)[::-1]
>>> ring.is_ccw
True

object.is_empty

如果要素的内部与边界(在点集方面)和空集相配合,则返回为真。

>>> from shapely.geometry import Point
>>> Point().is_empty
>>> Point(0, 0).is_empty
False

注意:

operator模块的attrgetter()函数的帮助,一元谓词例如 is_empty能够轻松地用作 filter()或者itertools.ifilter()内建的谓词。

>>> from operator import attrgetter
>>> empties = filter(attrgetter('is_empty'), [Point(), Point(0, 0)])
>>> # len(empties)

object.is_ring: 如果要素被闭合了,则返回为真。 一个关闭的要素的边界算是空集。

>>> from shapely.geometry import LineString
>>> LineString([(0, 0), (1, 1), (1, -1)]).is_ring
False
>>> from shapely.geometry import LinearRing
>>> LinearRing([(0, 0), (1, 1), (1, -1)]).is_ring
True

这属性适用于线(LineString)和线环(LinearRing)实例, 但是对于其它是毫无意义的。

object.is_simple : 如果要素不是自相交的,则返回为真。

>>> from shapely.geometry import LineString
>>> LineString([(0, 0), (1, 1), (1, -1), (0, 1)]).is_simple
False

Shapely完全支持线环(LineStrings)的操作。

object.is_valid: 如果一个要素是有效的,返回真。

一个有效的线环不能跨越它本身或者在一个单点接触。 一个有效的多边形可能拥有任何重叠的外部环或内部环。 一个有效的多元多边形可能不会搜集任何重叠的多边形。 基于无效要素进行的操作可能会失败。

>>> from shapely.geometry import MultiPolygon
>>> MultiPolygon([Point(0, 0).buffer(2.0), Point(1, 1).buffer(2.0)]).is_valid
False

以上2点接近,缓冲区操作产生的多边形将会重叠。(在下一节解释)

注意:

is_valid谓词可以用来写一个验证修饰, 可以确保唯一有效的对象从构造函数中返回。

5.3.2. 二元谓词

在Shapely中,标准的二元谓词通过Python的实现方法。这些谓词评估拓扑与集合论之间的关系。 在少数情况下,结果可能不是人们从不同假设中预期的那样。

所有二元谓词(方法)将另一个几何对象作为参数,且返回为真或为假。

object.almost_equals( other[, decimal=6])

如果对象的点在指定位精度上约等于另外对象的所有点, 则返回为真。

object.contains(other)

如果对象的内部包含另外一个对象的边界和内部, 并且两个对象的边界一点儿也不接触,则返回为真。

这种谓词适用于所有类型,并且逆于 a.contains(b) == b.within(a)的表达,常常被评定为真。

>>> from shapely.geometry import Point, LineString
>>> coords = [(0, 0), (1, 1)]
>>> LineString(coords).contains(Point(0.5, 0.5))
True
>>> from shapely.geometry import LineString
>>> Point(0.5, 0.5).within(LineString(coords))
True

线的端点是边界的一部分, 因此不包含。例如:

>>> LineString(coords).contains(Point(1.0, 1.0))
False

注意:

二元谓词可以直接用作filter()itertools.ifilter()的谓词。例如:

>>> line = LineString(coords)
>>> contained = filter(line.contains, [Point(), Point(0.5, 0.5)])
>>> # len(contained)

object.crosses(other)

如果对象的内部与另外对象的内部相交但并不包含它,并且相交的维数少于它本身或另一个维数,则返回为真。

>>> LineString(coords).crosses(LineString([(0, 1), (1, 0)]))
True

一条线不跨越它包含的点。

>>> LineString(coords).crosses(Point(0.5, 0.5))
False

object.disjoint(other)

如果对象的边界和内部与其它对象一点儿也不相交,则返回为真。

>>> Point(0, 0).disjoint(Point(1, 1))
True

这种谓词适用于所有类型并且逆于 intersects().

object.equals(other)

如果对象的集合论的边界、内部和外部与其它重合,则返回为真。

传递给对象构造的是这些集合, 并且决定它们,但是不是这些集的全部。 这对新用户来说是一个潜在的“疑难杂症”。 比如等值线,可以不这样被构造。

>>> from shapely.geometry import LineString
>>> a = LineString([(0, 0), (1, 1)])
>>> b = LineString([(0, 0), (0.5, 0.5), (1, 1)])
>>> c = LineString([(0, 0), (0, 0), (1, 1)])
>>> a.equals(b)
True
>>> b.equals(c)
True

这个谓词不应该被误认为是Python的==或者是构造。

object.intersects(other)

如果对象的边界和内部与其它的以任何形式相交,则返回真。

这个谓词不同于 contains()crosses()equals()touches()within()

object.touches( other)

如果对象的边界仅仅与另一个对象的边界相交,并且不与另一个的任何部分相交,则返回为真。

叠置要素不是touch, 另一个潜在的“疑难杂症”。 例如,下面的线在(1,1)相接触,但是并不重叠。

>>> a = LineString([(0, 0), (1, 1)])
>>> b = LineString([(1, 1), (2, 2)])
>>> a.touches(b)
True

object.within(other)

如果对象的边界和内部仅仅与另一个内部(不是边界或者外部)相交,则返回为真。

这适用于所有的类型并且逆于 contains().

用于sorted()的关键词, within() 使它很容易在空间上进行分类。 比方说,我们有4种定型的要素: 一个被一个多边形包含的点,这个多边形被另一个多边形包含 和一个不被其它点包含的点。

>>> from shapely.geometry import Point
>>> from shapely.geometry import Polygon
>>> a = Point(2, 2)
>>> b = Polygon([[1, 1], [1, 3], [3, 3], [3, 1]])
>>> c = Polygon([[0, 0], [0, 4], [4, 4], [4, 0]])
>>> d = Point(-1, -1)

和列表中收集到的副本

features = [c, a, d, b, c]

列表中,我们更喜欢按照(d, c, c, b, a)的反向遏制秩序。 正如在Python中解释的那样, Sorting HowTo, 我们可以定义一个运行在每一个列表上的关键要素, 返回一个值用于比较。我们的关键要素将是一个封装类 用Shapely的二进制谓词实施。

二进制 within() 谓词。

>>> from shapely.geometry import asShape
>>> class Within(object):
>>>     def __init__(self, o):
>>>         self.o = o
>>>     def __lt__(self, other):
>>>         return self.o.within(other.o)

正如howto所说的,小于比较的在排序中常被使用。 那正是我们空间排序中我们所依靠的东西, within() 和我们反向使用within() contains(). 而不是用contains()的原因。 在要素d和c上试验, 我们看到它工作了。

d > c
>>> Within(d) > Within(c)
False

它对列表上的要素同样有效,并产生我们想要的顺序。

>>>  # [d, c, c, b, a] == sorted(features, key=Within, reverse=True)

5.3.3. DE九交空间(DE-9IM)关系

DE九交空间关系运算是用于检验2个几何对象的特定的拓扑空间关系的逻辑方法。 两个几何对象的拓扑空间关系在GIS中是一个重要的研究主题。 2个几何对象的拓扑空间关系的判断主要是通过几何对象的内部、边界和外部的交集。 在二维空间中,几何体的边界是比几何体更低一维的集合。 如点和多点的边界为空集。线的边界为线的2个端点, 当线是闭合时,则线的边界为空集。多边形(面)的边界是组成它的线。

有两个简单实体A与B B(A) 和B(B) 表示A 和B 的边界(border) I(A) 和I(B) 表示A 和B 的内部(inside) E(A) 和E(B) 表示A 和B 的外部。 从数学上来讲,该模型可以表示29 = 512 种可能的关系,但实际 上有些关系是不存在的。

上面的9交模型是通过空和非空来区分2个目标边界的内部和外部。

该方法是有局限性,需要运用维数扩展法进行扩展:

空间关系

下面是几个预定义的空间关系:

  1. 两个几何对象完全相同,则表示为DE-9IM即 TFFFTFFFT

  2. 两个对象的边界和内部都没有任何公共部分,则表示为DE-9IM即 FF*FF****

  3. Disjoint 取反

  4. 简单地说Touches表示两个对象的边缘相接触, 这个关系是以下几类几何对象间特有的:A/A, L/L, L/A, P/A ,P/L。 用DE-9IM表示为 FT******* , F**T***** 或“F***T****”

  5. Crosses表示一个对象穿过另一个对象,它应用于P/L, P/A, L/L和L/A之间。 用DE-9IM表示为:“T*T******”(P/L, P/A,L/A),“0********”(L/L)

  6. 包含于。用DE-9IM表示为:“T*F**F***”

  7. 相叠,应用于A/A, L/L 和P/P之间。用DE-9IM表示为:“T*T***T**”(A/A, P/P),“1*T***T**”(L/L)

  8. 包含,对立于Within。

JTS的Geometry类实现了上面的所有方法,由于这些方法不能表示全部的空间位置关系, 因此OGC的Simple Feature Specification和JTS都提供了一个relate方法, 用来测试指定的DE-9IM关系。

relate()方法测试了对象之间的所有DE九交空间关系。

object.relate(other) 返回在一个对象和另一个几何对象的内部、 边界和外部之间的DE九交空间关系。

命名关系谓词contains() 等通常被当作relate()的封装实现。

两个不同的点在它们的矩阵中主要有假值(F,False)属性; 它们的外部交集 (第九个元素)是一个2维对象平面的其余部分。 一个对象的内部和另一个 外部的交集是0维对象(矩阵中的第3与第7个元素)。

>>> from shapely.geometry import Point
>>> Point(0, 0).relate(Point(1, 1))
'FF0FFF0F2'
>>> from shapely.geometry import LineString
>>> Point(0, 0).relate(LineString([(0, 0), (1, 1)]))
'F0FFFF102'

一条线和线上点的矩阵有更多真元素,而不是假元素。

测试

>>> LineString([(0, 0), (1, 1)]).relate(LineString([(0, 0), (1, 1)]))
'1FFF0FFF2'
>>> Point(0, 0).relate(Point(0, 0))
'0FFFFFFF2'
>>> Polygon([[0, 0], [0, 4], [4, 4], [4, 0]]).relate(Polygon([[0, 0], [0, 4], [4, 4], [4, 0]]))
'2FFF1FFF2'

页面运行信息


>>> from helper import info; info()
页面更新时间: 2020-11-05 21:26:09
操作系统/OS: Linux-4.19.0-11-amd64-x86_64-with-debian-10.6 ;Python: 3.7.3