确定分裂形状几何体的 "left" 和 "right" 侧
Determine the "left" and "right" side of a split shapely geometry
我的问题是:如何确定 an already split rotated rectangular geometry 的 Aside
和 Bside
边中的哪一个是 "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):
总而言之:A边和B边是minimum_rotated_rectangle
包围geom
几何体和splitter
线串在一起的两侧。当执行 side.intersection(geom)
时,结果是包含在该边中的最初给定几何 geom
的部分。
备注:
- 对于形状奇特的 "potato" 类型的对象,此交叉点可能会在一侧或两侧产生多个对象(参见 nbviewer 示例)
- 我在这里创建了自己的函数(而不是使用
ops.split
),因为 ops.split
函数只是 returns 一个 "bag" 分割对象,并且没有'无法确定他们站在哪一边(据我所知)
目前我对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"?
这可行:
- 用分离器的端点和Aside
中的一个点形成一个LinearRing
- 应用
object.is_ccw
- 如果是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))
我的问题是:如何确定 an already split rotated rectangular geometry 的 Aside
和 Bside
边中的哪一个是 "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):
总而言之:A边和B边是minimum_rotated_rectangle
包围geom
几何体和splitter
线串在一起的两侧。当执行 side.intersection(geom)
时,结果是包含在该边中的最初给定几何 geom
的部分。
备注:
- 对于形状奇特的 "potato" 类型的对象,此交叉点可能会在一侧或两侧产生多个对象(参见 nbviewer 示例)
- 我在这里创建了自己的函数(而不是使用
ops.split
),因为ops.split
函数只是 returns 一个 "bag" 分割对象,并且没有'无法确定他们站在哪一边(据我所知)
目前我对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"?
这可行:
- 用分离器的端点和Aside 中的一个点形成一个
- 应用
object.is_ccw
- 如果是returns
True
,Aside在分离器的左边。
LinearRing
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))