二元谓词

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

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

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

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

object.contains(other)

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

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

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

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

In [3]:
LineString(coords).contains(Point(1.0, 1.0))
Out[3]:
False

注意:

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

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

object.crosses(other)

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

In [5]:
LineString(coords).crosses(LineString([(0, 1), (1, 0)]))
Out[5]:
True

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

In [6]:
LineString(coords).crosses(Point(0.5, 0.5)) 
Out[6]:
False

object.disjoint(other)

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

In [7]:
Point(0, 0).disjoint(Point(1, 1))
Out[7]:
True

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

object.equals(other)

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

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

In [8]:
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)
Out[8]:
True
In [9]:
b.equals(c)
Out[9]:
True

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

object.intersects(other)

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

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

object.touches( other)

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

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

In [10]:
a = LineString([(0, 0), (1, 1)])
b = LineString([(1, 1), (2, 2)])
a.touches(b)
Out[10]:
True

object.within(other)

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

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

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

In [11]:
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() 谓词。

In [12]:
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
In [13]:
Within(d) > Within(c)
Out[13]:
False

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

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

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个元素)。

In [15]:
from shapely.geometry import Point
Point(0, 0).relate(Point(1, 1))
Out[15]:
'FF0FFF0F2'
In [16]:
from shapely.geometry import LineString
Point(0, 0).relate(LineString([(0, 0), (1, 1)]))
Out[16]:
'F0FFFF102'

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

测试

In [17]:
LineString([(0, 0), (1, 1)]).relate(LineString([(0, 0), (1, 1)]))
Out[17]:
'1FFF0FFF2'
In [18]:
Point(0, 0).relate(Point(0, 0))
Out[18]:
'0FFFFFFF2'
In [19]:
Polygon([[0, 0], [0, 4], [4, 4], [4, 0]]).relate(Polygon([[0, 0], [0, 4], [4, 4], [4, 0]]))
Out[19]:
'2FFF1FFF2'

一元谓词

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

所有的例子将会被显示。

一般的一元谓词

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

In [20]:
from shapely.geometry import Point
Point(0, 0).has_z
Point(0, 0, 0).has_z
Out[20]:
True

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

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

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

In [21]:
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
Out[21]:
True

object.is_empty

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

In [22]:
from shapely.geometry import Point
Point().is_empty
Point(0, 0).is_empty
Out[22]:
False

注意:

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

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

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

In [24]:
from shapely.geometry import LineString
LineString([(0, 0), (1, 1), (1, -1)]).is_ring
Out[24]:
False
In [25]:
from shapely.geometry import LinearRing
LinearRing([(0, 0), (1, 1), (1, -1)]).is_ring
Out[25]:
True

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

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

In [26]:
from shapely.geometry import LineString
LineString([(0, 0), (1, 1), (1, -1), (0, 1)]).is_simple
Out[26]:
False

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

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

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

In [27]:
from shapely.geometry import MultiPolygon
MultiPolygon([Point(0, 0).buffer(2.0), Point(1, 1).buffer(2.0)]).is_valid   
Out[27]:
False

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

注意:

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


In [28]:
import helper; helper.info()
页面更新时间: 2019-02-28 18:43:10
操作系统/OS: Linux-4.9.0-8-amd64-x86_64-with-debian-9.8
Python: 3.5.3