【问题标题】:How can I tessellate the boundary of a point cloud?如何细分点云的边界?
【发布时间】:2013-10-24 13:18:08
【问题描述】:

我有一堆顶点。我想只使用云中的顶点在顶点云周围镶嵌一个“壳”,这样壳大致符合顶点云的形状。

有没有简单的方法来做到这一点?我想我可以对点云进行球面参数化,然后“走”最外层的顶点来镶嵌云,但我不确定这是否可行。

我想添加顶点是可以接受的,但是“壳”的一般形状应该与顶点云的形状相匹配。

【问题讨论】:

    标签: opengl graphics


    【解决方案1】:

    我有一个适用于二维情况的算法。这很棘手,但可以将其推广到 3D 空间。基本思想是从最小曲面(2D 中的三角形或 3D 中的四面体)开始,并在遍历点数组时分割每个边(面)。

    2D 算法(python。FULL SOURCE/DEMO HERE:http://pastebin.com/jmwUt3ES

    编辑:这个演示很有趣:http://pastebin.com/K0WpMyA3

    def surface(pts):
    center = pt_center(pts)
    tx = -center[0]
    ty = -center[1]
    pts = translate_pts(pts, (tx, ty))
    # tricky part: initialization
    # initialize edges such that you have a triangle with the origin inside of it
    # in 3D, this will be a tetrahedron.
    ptA, ptB, ptC = get_center_triangle(pts)
    print ptA, ptB, ptC
    # tracking edges we've already included (triangles in 3D)
    edges = [(ptA, ptB), (ptB, ptC), (ptC, ptA)]
    # loop over all other points
    pts.remove(ptA)
    pts.remove(ptB)
    pts.remove(ptC)
    for pt in pts:
        ptA = (0,0)
        ptB = (0,0)
        # find the edge that this point will be splitting
        for (ptA, ptB) in edges:
            if crossz(ptA, pt) > 0 and crossz(pt, ptB) > 0:
                break
        edges.remove((ptA, ptB))
        edges.append((ptA, pt))
        edges.append((pt, ptB))
    # translate everything back
    edges = [((ptA[0] - tx, ptA[1] - ty), (ptB[0] - tx, ptB[1] - ty)) for (ptA, ptB) in edges]
    return edges
    

    结果:

    泛化到 3D

    • 你有三角形而不是边。
    • 初始化是一个围绕原点的四面体
    • 找到分割面涉及投影一个三角形,并检查 pt 是否在该三角形的内部
    • 分割涉及添加 3 个新面,而 2D 是 2 个新边
    • 需要注意面部的方向(在我的二维码中,我很容易保证 A->B 是 CCW 方向)

    根据您的点云大小和速度要求,您可能需要更聪明地了解数据结构以更快地添加/删除。

    【讨论】:

      【解决方案2】:

      我会考虑一个“度量”函数 f(x, y, z),它返回 3D 空间中任意点的标量值。该函数的构造方式应考虑给定点 (x, y, z) 是在云的“内部”还是“外部”。例如,这可以是从 (x, y, z) 到云中每个点的平均向量的长度,也可以是 (x, y, z) 某个附近范围内的多个云点。函数的选择会影响最终结果。

      有了这个 f(x, y, z),您就可以使用marching cubes algorithm 来执行细分,基本上是为某个值构建 f(x, y, z) 的等值面。

      【讨论】:

        【解决方案3】:

        3D 凸包 (convex hull algorithm for 3d surface z = f(x, y))。

        然后,对于每个最大面上的点,搜索云上最近的点,并重新对该面进行三角测量以包含该点。

        根据与每个剩余面的最近云点的最大距离或剩余最大面的大小(长度/面积?)重复直到它“足够接近”

        【讨论】:

          【解决方案4】:

          你应该试试3d Delaunay Triangulation。这将镶嵌点云,同时确保三网格仅具有来自点云的顶点。 CGAL 有两种对点云进行三角剖分的实现——delaunayregular。常规版本使用here 描述的想法对点进行三角测量。

          如果您使用的是 C++,则可以使用它们的实现。如果没有,您仍然可以查看他们的代码来自己实现它(虽然它非常复杂)。

          【讨论】:

            【解决方案5】:

            听起来您正在寻找“concave hull”。这提供了围绕一组点的“合理”边界,“合理”意味着将设置拟合到给定的容差。它不是像凸包那样的几何属性,而是许多“现实世界”问题的良好近似,比如在城市周围寻找一个紧密拟合的边界。

            您可以在Point Cloud Library 中找到实现。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-01-20
              • 2021-03-17
              • 2021-08-18
              • 2013-06-03
              • 1970-01-01
              • 2017-03-11
              • 2015-07-31
              • 2017-11-11
              相关资源
              最近更新 更多