怎么用Shapely检测共享边

编程语言 2026-07-12

一组三角形铺设一个区域

我有一组三角形,它们可以将一个区域铺成平整,包含的图片中显示了其中一种可能的配置。我想弄清楚每个三角形与相邻三角形共享了多少条边。

因此,单独一个三角形只会共享零条边,而被完全包围的三角形将共享全部三条边。在图中,中心三角形的顶边与上方的三角形共有边,但它在另外两边没有邻居。

因此我需要一个方法来检测它只与一个邻居共享一条边。

我已经用shapely将每个三角形定义为一个多边形,然后把三角形多边形的列表输入到一个SRTtree中。

随后尝试了 "touches" 与 "intersects" 两个谓词。

两者都会输出在任意一个顶点处相接触的所有邻近三角形。首选的结果是只输出共享边的三角形。

我也尝试使用覆盖运算来识别没有邻居的边。不幸的是,未有效边的检测对于每个三角形都返回一个空集合。

尽管中心三角形的两条边旁边没有任何对象,它似乎仍然满足覆盖要求,没有出现无效边。

下面的最小可重复示例(MRE)仅包含图中的四个三角形:中心三角形、与其共享一条边的上方三角形、一个与中心三角形共享一个顶点的三角形,以及一个不与初始三角形接触的三角形。

import shapely

triangles.append=shapely.Polygon(shell=((-0.5,0.866),(0.5,0.866),(0,0)),holes=None))
triangles.append=shapely.Polygon(shell=((-0.5,0.866),(0.5,0.866),(0,1.732)),holes=None))
triangles.append=shapely.Polygon(shell=((0.5,0.866),(1.5,0.866),(1,0)),holes=None))
triangles.append=shapely.Polygon(shell=((1,0),(2,0),(1.5,0.866)),holes=None))

tree=shapely.STRtree(triangles)

touching_triangles=tree.query(triangles[0], predicate="touches")
intersecting_triangles=tree.query(triangles[0], predicate="intersects")
identified_edges=shapely.coverage_invalid_edges(triangles)

那么在排除共享顶点的前提下,如何识别共享边?

解决方案

只需求三角形的交集,并从 intersection 获得 geom_type。丢弃为空或不是线的解。由于可能有多于两个三角形共享同一条边,我还在 edges 中以任意方向对已存在的边进行检查(不确定这对你是否必要,但我可以想到此问题下的复杂情况)。

def shared_edges(triangle, all_triangles):
    count = 0
    edges = []

    # Loop through all other triangles to find shared edges
    for other in all_triangles:
        if triangle is other:
            continue

        # Find the intersection of the boundaries of the two triangles
        intersection = triangle.boundary.intersection(other.boundary)

        # If the intersection is a LineString (i.e., a shared edge) and is not empty, add it to the list of edges
        if intersection.geom_type == 'LineString' and not intersection.is_empty:

            # Check if this edge is already in the list of edges (considering both orientations)
            if not any(intersection.equals(e) or intersection.equals(shapely.reverse(e)) for e in edges):
                edges.append(intersection)
                count += 1

    return count, edges

对于你的简化示例,这将得到

Triangle 0 shares 1 edge with neighbors:
  - LINESTRING (-0.5 0.866, 0.5 0.866)

我还在你的示例中再添加了一条三角形,使其不那么简单,并遍历了所有三角形:

Triangle 0 shares 2 edges with neighbors:
  - LINESTRING (-0.5 0.866, 0.5 0.866)
  - LINESTRING (0.5 0.866, 0 0)
Triangle 1 shares 1 edge with neighbors:
  - LINESTRING (-0.5 0.866, 0.5 0.866)
Triangle 2 shares 2 edges with neighbors:
  - LINESTRING (1.5 0.866, 1 0)
  - LINESTRING (1 0, 0.5 0.866)
Triangle 3 shares 1 edge with neighbors:
  - LINESTRING (1.5 0.866, 1 0)
Triangle 4 shares 2 edges with neighbors:
  - LINESTRING (0 0, 0.5 0.866)
  - LINESTRING (0.5 0.866, 1 0)
Triangle 5 shares 0 edges with neighbors.

带有共享边标记的三角形

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章