>>> from env_helper import info; info()
页面更新时间: 2023-04-15 20:02:57
运行环境:
Linux发行版本: Debian GNU/Linux 12 (bookworm)
操作系统内核: Linux-6.1.0-7-amd64-x86_64-with-glibc2.36
Python版本: 3.11.2
6.3. 谓词¶
谓词,用来描述或判定客体性质、特征或者客体之间关系的词项。根据《现代汉语》的定义,汉语的体词包括名词,数词,量词;汉语的谓词包括动词和形容词。
6.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
/usr/lib/python3/dist-packages/shapely/geometry/base.py:250: ShapelyDeprecationWarning: Setting the 'coords' to mutate a Geometry in place is deprecated, and will not be possible any more in Shapely 2.0
super().__setattr__(name, value)
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
谓词可以用来写一个验证修饰,
可以确保唯一有效的对象从构造函数中返回。
6.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)
6.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个目标边界的内部和外部。
该方法是有局限性,需要运用维数扩展法进行扩展:
空间关系¶
下面是几个预定义的空间关系:
两个几何对象完全相同,则表示为DE-9IM即
TFFFTFFFT
两个对象的边界和内部都没有任何公共部分,则表示为DE-9IM即
FF*FF****
Disjoint
取反简单地说Touches表示两个对象的边缘相接触, 这个关系是以下几类几何对象间特有的:A/A, L/L, L/A, P/A ,P/L。 用DE-9IM表示为
FT*******
,F**T*****
或“F***T****”Crosses表示一个对象穿过另一个对象,它应用于P/L, P/A, L/L和L/A之间。 用DE-9IM表示为:“T*T******”(P/L, P/A,L/A),“0********”(L/L)
包含于。用DE-9IM表示为:“T*F**F***”
相叠,应用于A/A, L/L 和P/P之间。用DE-9IM表示为:“T*T***T**”(A/A, P/P),“1*T***T**”(L/L)
包含,对立于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'