如何检测分割多边形何时可能是多边形
How to detect when split polygon could have been multipolygon
当我分割一个多边形使得有两个断开连接的部分时,我得到一个 MultiPolygon。但是当它们在一条线上相切时,它会给我一个多边形,就像这个例子。
'POLYGON ((0 0.5, 0 0.95, 2 1.95, 2 1.1, 1.5 1.1, 1.5 1.5, 1.1 1.5, 1.1 1.1, 1 1.1, 1 1.2, 0.5 1.2, 0.5 0.5, 0 0.5))'
我原以为很容易检测到它们,因为它们会有交点。我天真地希望查看外部坐标以查找重复项。但是,它可以在两点之间的线上相交,例如示例多边形(它是用 shapely.ops.split(poly, line)
和对角线分割产生的两个几何图形之一):
在我看来,这应该产生了一个多面体。事实上,我相信在这种情况下我应该将它转换成一组正多边形,所以除了检测这些形状之外,如果你也有一种动态的方式将它分割成一个多多边形(或多边形列表),那就太棒了.我希望检测可以比查看点和由每对点组成的线串之间的交点更快,因为那会很慢:
def remove_self_tangents(S: Polygon) -> Polygon:
"""sketch approach to remove self tangents"""
for i, (a,b) in enumerate(zip(S.exterior.coords, S.exterior.coords[1:])):
for c in S.exterior.coords:
if c == a or c == b:
continue
if c.touches(LineString([a, b])):
S = Polygon(S.exterior.coords[:-1].insert(i+1,c)).simplify(TOLERANCE) # don't actually expect simplify will do it but, ...
return S
编辑:
我现在有我的过程,上面的样本永远不会生成,但仍然会生成非常接近的未命中,例如:
'POLYGON ((0.5 0.5, 1 0.5, 1 1.110223024625157e-16, 0 0.9999999999999998, 0 2, 1 2, 1 1.2, 0.5 1.2, 0.5 0.5))'
解决这个问题的简单算法是四舍五入到一定的精度..但是.simplify
在这里不起作用,我必须手动完成吗?
这是我使用的解决方案
# TOLERANCE = 1e-14 or something
def polygon_has_no_self_tangents(S: Polygon) -> Polygon:
for a,b in zip(S.exterior.coords, S.exterior.coords[1:]):
for c in S.exterior.coords:
if c == a or c == b:
continue
np = nearest_points(LineString([a, b]), Point(c))
if np[0].distance(np[1]) < TOLERANCE:
return False
return True
当我分割一个多边形使得有两个断开连接的部分时,我得到一个 MultiPolygon。但是当它们在一条线上相切时,它会给我一个多边形,就像这个例子。
'POLYGON ((0 0.5, 0 0.95, 2 1.95, 2 1.1, 1.5 1.1, 1.5 1.5, 1.1 1.5, 1.1 1.1, 1 1.1, 1 1.2, 0.5 1.2, 0.5 0.5, 0 0.5))'
我原以为很容易检测到它们,因为它们会有交点。我天真地希望查看外部坐标以查找重复项。但是,它可以在两点之间的线上相交,例如示例多边形(它是用 shapely.ops.split(poly, line)
和对角线分割产生的两个几何图形之一):
在我看来,这应该产生了一个多面体。事实上,我相信在这种情况下我应该将它转换成一组正多边形,所以除了检测这些形状之外,如果你也有一种动态的方式将它分割成一个多多边形(或多边形列表),那就太棒了.我希望检测可以比查看点和由每对点组成的线串之间的交点更快,因为那会很慢:
def remove_self_tangents(S: Polygon) -> Polygon:
"""sketch approach to remove self tangents"""
for i, (a,b) in enumerate(zip(S.exterior.coords, S.exterior.coords[1:])):
for c in S.exterior.coords:
if c == a or c == b:
continue
if c.touches(LineString([a, b])):
S = Polygon(S.exterior.coords[:-1].insert(i+1,c)).simplify(TOLERANCE) # don't actually expect simplify will do it but, ...
return S
编辑:
我现在有我的过程,上面的样本永远不会生成,但仍然会生成非常接近的未命中,例如: 'POLYGON ((0.5 0.5, 1 0.5, 1 1.110223024625157e-16, 0 0.9999999999999998, 0 2, 1 2, 1 1.2, 0.5 1.2, 0.5 0.5))'
解决这个问题的简单算法是四舍五入到一定的精度..但是.simplify
在这里不起作用,我必须手动完成吗?
这是我使用的解决方案
# TOLERANCE = 1e-14 or something
def polygon_has_no_self_tangents(S: Polygon) -> Polygon:
for a,b in zip(S.exterior.coords, S.exterior.coords[1:]):
for c in S.exterior.coords:
if c == a or c == b:
continue
np = nearest_points(LineString([a, b]), Point(c))
if np[0].distance(np[1]) < TOLERANCE:
return False
return True