首页Python【Shapely矢量数据空...

【Shapely矢量数据空间分析】8.Shapely中的谓词和关系——二元谓词(方法)


本系列文章是根据Shapely官方文档翻译整理,学习任何一个Python第三方库,其官方文档都是最好的学习资料。相比网络搜索得到的一些资料,官方文档是权威的一手资料,其内容全面、准确可靠。通过官方文档入手,能够保证学习认知不会有大偏差。在学习完官方文档后,可以在寻找其他资料进一步学习。

点击“阅读原文”或者直接访问下方链接,查看翻译整理的“Shapely 2.0.0 中文文档”。

https://www.mizhushare.com/docs/shapely-2-0-0-%e4%b8%ad%e6%96%87%e6%96%87%e6%a1%a3/
本系列文章配套代码获取有以下两种途径:
  • 可以通过百度网盘获取,需要在本地配置代码运行环境:
链接:https://pan.baidu.com/s/1iWGGhB4kra9V7bUj-CWR0w?pwd=mnsj 提取码:mnsj
  • 前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Shapely




Shapely中标准的二元谓词通过方法实现。这些谓词评估拓扑与集合论的关系。所有的方法都以另一个几何对象作为参数,并返回True 或 False
方法
说明
object.__eq__(other) 如果两个对象的几何类型相同,并且两个对象的坐标精确匹配,则返回True
object.equals(other)
如果对象的集合边界、内部和外部与另一个对象的边界、内部和外部重合,则返回True
object.equals_exact(other, tolerance) 如果对象在所有点上都近似等于另一个对象,并达到指定的小数位精度,则返回True
object.contains(other) 如果对象的内部包含另外一个对象的边界和内部,并且两个对象的边界不接触,则返回True
object.covers(other) 如果对象的内部包含另外一个对象的边界和内部,则返回True。这与object.contains(other)相似,只是其没有对内部点的要求。
object.covered_by(other) 如果对象的每一个点都是其他对象的内部或边界上的一个点,则返回真。其等价于other.covers(object)
object.crosses(other)  如果该对象的内部与另一对象的内部相交但不包含该对象,并且相交处的维数其本身或另一个维度,则返回True
object.disjoint(other) 如果该对象的边界和内部与其他对象不相交(按集合论,没有任何同样的元素),则返回True
object.intersects(other) 如果该对象的边界或内部以任何方式与另一对象的边界或内部相交,则返回True
object.overlaps(other)
如果几何要素有一个以上但不是所有的共同点,具有相同的维数,并且几何要素内部的交点与几何要素本身具有相同的维数,则返回True
object.touches(other)  如果对象的边界仅与另一个对象的边界相交,并且不与另一个对象的其他部分相交,则返回True
object.within(other)  如果对象的边界和内部仅与另一个对象的内部相交(而不是其边界或外部),则返回True

需要注意的是,在少数情况下,结果可能不是人们所期望的那样。这就需要多练习和查看官方文档。

  • object.__eq__(other)

如果两个对象的几何类型相同,并且两个对象的坐标精确匹配,则返回True

1>>> a = LineString([(00), (11)])
2>>> b = LineString([(0.00.0), (1.01.0)])
3
4>>> a.__eq__(b)
5True
  • object.equals(other):

如果对象的集合边界、内部和外部与另一个对象的边界、内部和外部重合,则返回True

因为传递给对象构造函数的坐标可以有多种方式,因此这可能会对用户造成一个潜在的 “麻烦”。

例如,相同的线,可以用不同的方式构造。

 1>>> a = LineString([(00), (11)])
2>>> b = LineString([(00), (0.50.5), (11)])
3>>> c = LineString([(00), (00), (11)])
4
5>>> a.equals(b)
6True
7>>> a == b
8False
9
10>>> b.equals(c)
11True
12>>> b == c
13False
  • object.equals_exact(other, tolerance):

如果对象在所有点上都近似等于另一个对象,并达到指定的小数位精度,则返回True

1>>> a = LineString([(00), (11)])
2>>> b = LineString([(0.10.1), (1.11.1)])
3
4>>> a.equals_exact(b , tolerance=0.2)
5True
6
7>>> a.equals_exact(b , tolerance=0.1)
8False
  • object.contains(other):

如果对象的内部包含另外一个对象的边界和内部,并且两个对象的边界不接触,则返回True,适用于所有类型,并且与后续介绍的within()相反。表达式a.contains(b) == b.within(a)结果总为True

1>>> LineString([(0, 0), (1, 1)]).contains(Point(0.5, 0.5))
2True
3
4>>> Point(0.5, 0.5).within(LineString([(0, 0), (1, 1)]))
5True

需要注意的是,一条线的端点是其边界的一部分,因此不包含在内。

1>>> LineString([(0, 0), (1, 1)]).contains(Point(1.0, 1.0))
2False

另外,二元谓词可以直接作为filter()itertools.ifilter()的谓词使用。

1>>> line = LineString([(00), (11)])
2>>> line
3<LINESTRING (0 01 1)>
4
5>>> contained = list(filter(line.contains, [Point(), Point(1.01.0) , Point(0.50.5)]))
6>>> contained
7[<POINT (0.5 0.5)>]
  • object.covers(other):

如果对象的内部包含另外一个对象的边界和内部,则返回True。这与object.contains(other)相似,只是其没有对内部点的要求。

1>>> LineString([(0, 0), (1, 1)]).covers(Point(1.0, 1.0))
2True
  • object.covered_by(other):

如果对象的每一个点都是其他对象的内部或边界上的一个点,则返回True。其等价于other.covers(object)


  • object.crosses(other):

如果该对象的内部与另一对象的内部相交但不包含该对象,并且相交处的维数少于其本身或另一个对象的维度,则返回True

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

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

1>>> LineString([(0, 0), (1, 1)]).crosses(Point(0.5, 0.5))
2False
  • object.disjoint(other):

如果该对象的边界和内部与其他对象不相交(按集合论,没有任何同样的元素),则返回True,适用于所有类型,可以视为下面介绍的intersects()的逆向。

 1# 点要素
2>>> Point(00).disjoint(Point(11))
3True
4
5# 线要素
6>>> line1 = LineString([(00), (11)])
7>>> line2 = LineString([(02), (20)])
8
9>>> line1.disjoint(line2)
10False

两个线要素的相对关系图如下所示:

  • object.intersects(other):

如果该对象的边界或内部以任何方式与另一对象的边界或内部相交,则返回True。换句话说,如果几何对象有任何边界或内部的共同点,它们就会相交。

以上面的线要素为例,两者disjoint结果为Falseintersects结果为True

1>>> line1 = LineString([(00), (11)])
2>>> line2 = LineString([(02), (20)])
3
4>>> line1.intersects(line2)
5True
  • object.overlaps(other):

如果几何要素有一个以上但不是所有的共同点,具有相同的维数,并且几何要素内部的交点与几何要素本身具有相同的维数,则返回True

也就是两个对象的intersects()Ture,但是相互之间的within()False,则返回Ture

1>>> line1 = LineString([(00), (11)])
2>>> line2 = LineString([(01), (10)])
3>>> line3 = LineString([(01), (0.50.5), (11), (20)])
4
5>>> line1.overlaps(line2)
6False
7
8>>> line1.overlaps(line3)
9True

三个线要素的相对关系图如下所示:

  • object.touches(other):

如果对象的边界仅与另一个对象的边界相交,并且不与另一个对象的其他部分相交,则返回True

重叠(Overlapping )的要素不会接触(touch),这是另一个潜在的 “麻烦”。例如,下面的线条在(1,1)处接触(touches)和相交(intersects),但不重叠(overlaps)。

1>>> a = LineString([(00), (11)])
2>>> b = LineString([(11), (22)])
3>>> a.touches(b) , a.intersects(b) , a.overlaps(b)
4(True, True, False)
  • object.within(other):

如果对象的边界和内部仅与另一个对象的内部相交(而不是其边界或外部),则返回True。适用于所有类型,是contains()的逆运算。

sorted()键中使用,within()使对象的空间排序变得容易。假设我们有4个要素:一个被一个多边形所包含的点,而这个多边形本身又被另一个多边形所包含,以及一个没有被包含的自由点。

1>>> a = Point(22)
2>>> b = Polygon([[1, 1], [1, 3], [3, 3], [3, 1]])
3>>> c = Polygon([[0, 0], [0, 4], [4, 4], [4, 0]])
4>>> d = Point(-1-1)

这些对象的相对关系图若下所示:

然后将这些对象收集到一个列表中:

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

我们倾向于将其排序为 [d, c, c, b, a] 的反向包含顺序。正如在 Python Sorting HowTo 中所解释的,我们可以定义一个键函数,对每个列表元素进行操作,并返回一个值进行比较。我们的键函数将是一个包装类,它使用 Shapely 的二进制 within() 谓词实现 。

1>>class Within:
2...     def __init__(self , o):
3...         self.o = o
4...     def __lt__(self , other)# python内置的比较运算符 __lt__(self, other) --> 定义小于号的行为:x < y 调用 x.__lt__(y)
5...         return self.o.within(other.o)
6...

正如Python Sorting HowTo 中所解释的,小于的比较是保证在排序中使用的。这就是我们要依靠的空间排序。在特征d和c上试了一下,我们发现它是有效的。

1>>> Within(d) < Within(c) # 调用 d.__lt__(c) --> d.within(c)
2False

它也在功能列表上工作,产生我们想要的顺序。

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


END


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments