确定分裂形状几何体的 "left" 和 "right" 侧

Determine the "left" and "right" side of a split shapely geometry

我的问题是:如何确定 an already split rotated rectangular geometryAsideBside 边中的哪一个是 "left" 和 "right" 边任意 LineString 分割那个几何?

为了这个问题的目的,当 "walking" 来自节点到节点,按顺序。

我创建了这个函数来将 any 任意 shapely 几何体(非集合)分成两侧 - "left" 和 "right":

import shapely.geometry as geo
import shapely.ops as ops

def splitLR(geom, splitter):
    """Split a geometry into a 'left' and 'right' side using the shapely API"""
    if not isinstance(splitter, geo.LineString):
        raise TypeError("The splitter must be a LineString")
    if not splitter.is_simple:
        raise ValueError("Only simple splitter objects allowed")
    if hasattr(geom, "__iter__"):
        raise ValueError("Geometry collections not allowed")
    geom_extents = geo.GeometryCollection([geom, splitter]).minimum_rotated_rectangle
    sides = ops.split(geom_extents, splitter)
    try:
        Aside, Bside = sides
    except TypeError:
        # only 1 result - rotated rectangle wasn't split
        if len(ops.split(geom,splitter)) == 1:
            # geom isn't split by splitter
            raise ValueError("the splitter does not appear to split the geometry")
        else:
            # splitter too small for algorithm
            raise ValueError("the splitter must extend beyond minimum_rotated_rectangle "
                             "of the combined geometry")
    # determine which is Lside and Rside here
    Lside,Rside = get_LRsides(Aside, Bside, splitter)
    return tuple(side.intersection(geom) for side in (Lside, Rside))

上面的想法在 linked here 的笔记本中有说明(与上面相同 link):

http://nbviewer.jupyter.org/urls/dl.dropbox.com/s/ll3mchnx0jwzjnf/determine%20left-right%20split.ipynb

总而言之:A边和B边是minimum_rotated_rectangle包围geom几何体和splitter线串在一起的两侧。当执行 side.intersection(geom) 时,结果是包含在该边中的最初给定几何 geom 的部分。

备注:

目前我对get_LRsides的调用只是执行了这个函数,显然是没有价值的:

def get_LRsides(Aside, Bside, splitter):
    """Determine the 'left' and 'right' sides of an already split geometry"""
    return Aside,Bside

如何才能成功将 A 和 B 标记为 "left" 和 "right"?

这可行:

  1. 用分离器的端点和Aside
  2. 中的一个点形成一个LinearRing
  3. 应用object.is_ccw
  4. 如果是returns True,Aside在分离器的左边。

https://shapely.readthedocs.io/en/stable/manual.html#object.is_ccw

我不是工具箱中最敏锐的 GIS 工具,并且一直在努力弄清楚如何在已接受的答案中向 LinearRing“添加一个点”。这是我可以用的技巧。

我将相交拆分线串的两个点投影到第一个多边形的外部,这为我提供了沿该外部线串的距离。如果该距离增加,则第一个多边形是拆分的“右侧”。

这是一个示例代码:

from shapely.ops import split
from shapely.geometry import Polygon, LineString, Point


def rhs_split(poly, splitter):
    intersect_splitter = splitter.intersection(poly)
    geomcollect = split(poly, splitter)
    polya, polyb = geomcollect.geoms[0], geomcollect.geoms[1]
    # Test directionality
    pt0 = Point(intersect_splitter.coords[0])
    pt1 = Point(intersect_splitter.coords[1])
    start_dist = polya.exterior.project(pt0)
    end_dist = polya.exterior.project(pt1)
    return polya if end_dist > start_dist else polyb


print(
    rhs_split(
        Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)]),
        LineString([(0.5, -0.1), (0.5, 1.1)]),
    )
)
# POLYGON ((0.5 1, 1 1, 1 0, 0.5 0, 0.5 1))
print(
    rhs_split(
        Polygon([(0, 0), (0, 1), (1, 1), (1, 0), (0, 0)]),
        LineString([(0.5, 1.1), (0.5, -0.1)]),
    )
)
# POLYGON ((0 0, 0 1, 0.5 1, 0.5 0, 0 0))