当前位置: 首页 > 知识库问答 >
问题:

包含给定点集的边界

彭涵衍
2023-03-14

我现在使用的算法有点问题。我想让它划定界限。

下面是当前行为的一个例子:

以下是一个被通缉行为的示例:

C#中凸壳的当前代码:https://hastebin.com/dudejesuja.cs

我的问题是:

1) 这可能吗?

R:是的

2)这甚至被称为凸包吗?(我不这么认为)

R:不,这叫边界,link:https://www.mathworks.com/help/matlab/ref/boundary.html

3) 这会不会比传统的凸面船体对性能不那么友好?

R:据我研究,应该是相同的性能

4) 这个算法的例子是伪代码还是类似的?

R:还没有回答或者我还没有找到解决办法

共有3个答案

漆雕修能
2023-03-14

考虑使用阿尔法形状,有时称为凹壳。https://en.wikipedia.org/wiki/Alpha_shape

它可以通过Delaunay三角剖分在时间O(N logn)内建立。

索梓
2023-03-14

我会用不同的方法来解决这个问题。由于我们使用的是一组二维点,因此计算点区域的边界矩形很简单。然后我用水平线和垂直线将这个矩形分成“单元”,每个单元只需计算其边界内的像素数。由于每个单元只能有4个相邻单元(单元边相邻),因此边界单元将是至少有一个空相邻单元或单元边位于边界矩形边界的单元。然后沿着边界单元侧面构建边界。边界看起来像一个“楼梯”,但选择较小的单元大小将改善结果。事实上,细胞大小应该通过实验来确定;它不能太小,否则区域内可能会出现空细胞。点之间的平均距离可用作单元大小的下边界。

王英奕
2023-03-14

下面是一些计算alpha形状(凹形船体)并只保留外部边界的Python代码。这可能就是matlab的边界在里面做的事情。

from scipy.spatial import Delaunay
import numpy as np


def alpha_shape(points, alpha, only_outer=True):
    """
    Compute the alpha shape (concave hull) of a set of points.
    :param points: np.array of shape (n,2) points.
    :param alpha: alpha value.
    :param only_outer: boolean value to specify if we keep only the outer border
    or also inner edges.
    :return: set of (i,j) pairs representing edges of the alpha-shape. (i,j) are
    the indices in the points array.
    """
    assert points.shape[0] > 3, "Need at least four points"

    def add_edge(edges, i, j):
        """
        Add an edge between the i-th and j-th points,
        if not in the list already
        """
        if (i, j) in edges or (j, i) in edges:
            # already added
            assert (j, i) in edges, "Can't go twice over same directed edge right?"
            if only_outer:
                # if both neighboring triangles are in shape, it's not a boundary edge
                edges.remove((j, i))
            return
        edges.add((i, j))

    tri = Delaunay(points)
    edges = set()
    # Loop over triangles:
    # ia, ib, ic = indices of corner points of the triangle
    for ia, ib, ic in tri.vertices:
        pa = points[ia]
        pb = points[ib]
        pc = points[ic]
        # Computing radius of triangle circumcircle
        # www.mathalino.com/reviewer/derivation-of-formulas/derivation-of-formula-for-radius-of-circumcircle
        a = np.sqrt((pa[0] - pb[0]) ** 2 + (pa[1] - pb[1]) ** 2)
        b = np.sqrt((pb[0] - pc[0]) ** 2 + (pb[1] - pc[1]) ** 2)
        c = np.sqrt((pc[0] - pa[0]) ** 2 + (pc[1] - pa[1]) ** 2)
        s = (a + b + c) / 2.0
        area = np.sqrt(s * (s - a) * (s - b) * (s - c))
        circum_r = a * b * c / (4.0 * area)
        if circum_r < alpha:
            add_edge(edges, ia, ib)
            add_edge(edges, ib, ic)
            add_edge(edges, ic, ia)
    return edges
from matplotlib.pyplot import *

# Constructing the input point data
np.random.seed(0)
x = 3.0 * np.random.rand(2000)
y = 2.0 * np.random.rand(2000) - 1.0
inside = ((x ** 2 + y ** 2 > 1.0) & ((x - 3) ** 2 + y ** 2 > 1.0)
points = np.vstack([x[inside], y[inside]]).T

# Computing the alpha shape
edges = alpha_shape(points, alpha=0.25, only_outer=True)

# Plotting the output
figure()
axis('equal')
plot(points[:, 0], points[:, 1], '.')
for i, j in edges:
    plot(points[[i, j], 0], points[[i, j], 1])
show()

编辑:根据注释中的请求,下面是一些将输出边集“缝合”为连续边序列的代码。

def find_edges_with(i, edge_set):
    i_first = [j for (x,j) in edge_set if x==i]
    i_second = [j for (j,x) in edge_set if x==i]
    return i_first,i_second

def stitch_boundaries(edges):
    edge_set = edges.copy()
    boundary_lst = []
    while len(edge_set) > 0:
        boundary = []
        edge0 = edge_set.pop()
        boundary.append(edge0)
        last_edge = edge0
        while len(edge_set) > 0:
            i,j = last_edge
            j_first, j_second = find_edges_with(j, edge_set)
            if j_first:
                edge_set.remove((j, j_first[0]))
                edge_with_j = (j, j_first[0])
                boundary.append(edge_with_j)
                last_edge = edge_with_j
            elif j_second:
                edge_set.remove((j_second[0], j))
                edge_with_j = (j, j_second[0])  # flip edge rep
                boundary.append(edge_with_j)
                last_edge = edge_with_j

            if edge0[0] == last_edge[1]:
                break

        boundary_lst.append(boundary)
    return boundary_lst

然后,可以浏览边界列表列表,并在每条边上附加与第一个索引对应的点,以获得边界多边形。

 类似资料:
  • 这是考试准备的一部分。我知道这和最大流量算法有关,但我很乐意给你一个提示: 设为无向连通图,为权函数,为边,。描述一种算法,该算法确定是否可以从图中最多删除边,以便属于新图的最小生成树。 我认为生成树是一种完美的匹配。但是,如何使它最小化,包含e和适当数量的其他边?

  • 我正在研究一个问题,基本上可以归结为以下几点: 给定: null 对于这样一个位置,有什么算法的想法吗?我最终将使用java实现,但我可以使用PsuedoCode。

  • 在加权无向图中,我需要找到一个包含给定边“e”的最小生成树,如果可能的话。我该怎么做呢?Kruskal从“e”开始?

  • 我在传单地图上有一组无组织的点,在我的实现中,这些点表示Minecraftarium.com/map上Minecraftarium.com/map上地图上的领土节点。目前,我的实现只获取点,并使用传单在点周围画一个圆来大致指示控制区域。 然而,这有点难看,也不代表期望的最终结果,即从给定一组数据的边缘点绘制多边形区域。然而,由于这些点的无组织性质,我没有简单的方法来宣布这些点上的“边缘点”,因为它

  • 问题内容: 在Android中,我有一个Path对象,我碰巧知道它定义了一条闭合路径,因此我需要弄清楚路径中是否包含给定点。我所希望的是一些类似的东西 但这似乎并不存在。 我要这样做的特定原因是因为我在屏幕上有一组形状定义为路径,并且我想弄清楚用户单击了哪个形状。如果有更好的方法来解决这一问题,例如使用不同的UI元素,而不是自己“艰难地”进行操作,我愿意提出建议。 如果需要的话,我愿意自己编写算法

  • 问题: 给定 N 个节点和 M 条边的图形,边的索引范围为 1 - 你需要为M条边分配权重。权重在[1...M],并且每个数字只能出现一次。 简而言之,答案应该是[1]的置换数组...M],其中arr[i] = x表示edge[i]的权重为x。 你得到了一个由n-1条边组成的集合。R保证是图的生成树。 找到一种分配权重的方法,使R是图的最小生成树,如果有多个答案,则打印具有最小字典顺序的答案。 约