【问题标题】:Crop function that slices triangles instead of removing them (open3d)裁剪三角形而不是删除它们的裁剪功能(open3d)
【发布时间】:2023-01-12 01:50:01
【问题描述】:

我在 open3d 中有一个 TriangleMesh,我想使用边界框裁剪它。

Open3d 有 crop function,如果三角形完全或部分在边界框之外,它会删除它们。

如果三角形部分位于边界框之外,是否有一个函数可以对三角形进行切片?

这是一个简单的 2D 示例(见下图)。给定边界框和输入三角形,open3d 裁剪函数将简单地删除三角形。我想要一个函数,它采用与边界框重叠的三角形并将其切片。有这样的功能吗?

【问题讨论】:

    标签: python open3d


    【解决方案1】:

    我构建了一个可以裁剪 AxisAlignedBoundingBox 的解决方案(这是我需要的):

    输入网格:

    使用以下代码清理作物:

    Open3d裁剪:

    import open3d as o3d
    import numpy as np
    
    def sliceplane(mesh, axis, value, direction):
        # axis can be 0,1,2 (which corresponds to x,y,z)
        # value where the plane is on that axis
        # direction can be True or False (True means remove everything that is
        # greater, False means less
        # than)
    
        vertices = np.asarray(mesh.vertices)
        triangles = np.asarray(mesh.triangles)
        new_vertices = list(vertices)
        new_triangles = []
    
        # (a, b) -> c
        # c refers to index of new vertex that sits at the intersection between a,b
        # and the boundingbox edge
        # a is always inside and b is always outside
        intersection_edges = dict()
    
        # find axes to compute
        axes_compute = [0,1,2]
        # remove axis that the plane is on
        axes_compute.remove(axis)
    
        def compute_intersection(vertex_in_index, vertex_out_index):
            vertex_in = vertices[vertex_in_index]
            vertex_out = vertices[vertex_out_index]
            if (vertex_in_index, vertex_out_index) in intersection_edges:
                intersection_index = intersection_edges[(vertex_in_index, vertex_out_index)]
                intersection = new_vertices[intersection_index]
            else:
                intersection = [None, None, None]
                intersection[axis] = value
                const_1 = (value - vertex_in[axis])/(vertex_out[axis] - vertex_in[axis])
                c = axes_compute[0]
                intersection[c] = (const_1 * (vertex_out[c] - vertex_in[c])) + vertex_in[c]
                c = axes_compute[1]
                intersection[c] = (const_1 * (vertex_out[c] - vertex_in[c])) + vertex_in[c]
                assert not (None in intersection)
                # save new vertice and remember that this intersection already added an edge
                new_vertices.append(intersection)
                intersection_index = len(new_vertices) - 1
                intersection_edges[(vertex_in_index, vertex_out_index)] = intersection_index
    
            return intersection_index
    
        for t in triangles:
            v1, v2, v3 = t
            if direction:
                v1_out = vertices[v1][axis] > value
                v2_out = vertices[v2][axis] > value
                v3_out = vertices[v3][axis] > value
            else: 
                v1_out = vertices[v1][axis] < value
                v2_out = vertices[v2][axis] < value
                v3_out = vertices[v3][axis] < value
    
            bool_sum = sum([v1_out, v2_out, v3_out])
            # print(f"{v1_out=}, {v2_out=}, {v3_out=}, {bool_sum=}")
    
            if bool_sum == 0:
                # triangle completely inside --> add and continue
                new_triangles.append(t)
            elif bool_sum == 3:
                # triangle completely outside --> skip
                continue
            elif bool_sum == 2:
                # two vertices outside 
                # add triangle using both intersections
                vertex_in_index = v1 if (not v1_out) else (v2 if (not v2_out) else v3)
                vertex_out_1_index = v1 if v1_out else (v2 if v2_out else v3)
                vertex_out_2_index = v3 if v3_out else (v2 if v2_out else v1)
                # print(f"{vertex_in_index=}, {vertex_out_1_index=}, {vertex_out_2_index=}")
                # small sanity check if indices sum matches
                assert sum([vertex_in_index, vertex_out_1_index, vertex_out_2_index]) == sum([v1,v2,v3])
    
                # add new triangle 
                new_triangles.append([vertex_in_index, compute_intersection(vertex_in_index, vertex_out_1_index), 
                    compute_intersection(vertex_in_index, vertex_out_2_index)])
    
            elif bool_sum == 1:
                # one vertice outside
                # add three triangles
                vertex_out_index = v1 if v1_out else (v2 if v2_out else v3)
                vertex_in_1_index = v1 if (not v1_out) else (v2 if (not v2_out) else v3)
                vertex_in_2_index = v3 if (not v3_out) else (v2 if (not v2_out) else v1)
                # print(f"{vertex_out_index=}, {vertex_in_1_index=}, {vertex_in_2_index=}")
                # small sanity check if outdices sum matches
                assert sum([vertex_out_index, vertex_in_1_index, vertex_in_2_index]) == sum([v1,v2,v3])
    
                new_triangles.append([vertex_in_1_index, compute_intersection(vertex_in_1_index, vertex_out_index), vertex_in_2_index])
                new_triangles.append([compute_intersection(vertex_in_1_index, vertex_out_index), 
                    compute_intersection(vertex_in_2_index, vertex_out_index), vertex_in_2_index])
    
            else:
                assert False
    
        # TODO remap indices and remove unused 
    
        mesh = o3d.geometry.TriangleMesh()
        mesh.vertices = o3d.utility.Vector3dVector(np.array(new_vertices))
        mesh.triangles = o3d.utility.Vector3iVector(np.array(new_triangles))
        return mesh
    
    def clean_crop_xy(mesh, min_corner, max_corner):
        min_x = min(min_corner[0], max_corner[0])
        min_y = min(min_corner[1], max_corner[1])
        max_x = max(min_corner[0], max_corner[0])
        max_y = max(min_corner[1], max_corner[1])
    
        # mesh = sliceplane(mesh, 0, min_x, False)
        mesh_sliced = sliceplane(mesh, 0, max_x, True)
        mesh_sliced = sliceplane(mesh_sliced, 0, min_x, False)
        mesh_sliced = sliceplane(mesh_sliced, 1, max_y, True)
        mesh_sliced = sliceplane(mesh_sliced, 1, min_y, False)
        # mesh_sliced = mesh_sliced.paint_uniform_color([0,0,1])
    
        return mesh_sliced
    
    knot_mesh = o3d.data.KnotMesh()
    mesh = o3d.io.read_triangle_mesh(knot_mesh.path)
    v = np.asarray(mesh.vertices)
    
    mesh_cropped = clean_crop_xy(mesh, (-200, 0), (0, -200))
    bounding_box = o3d.geometry.AxisAlignedBoundingBox((-200, 0, -1000), (0,200,1000))
    mesh_crop_bad = mesh.crop(bounding_box)
    
    o3d.visualization.draw_geometries([mesh], mesh_show_back_face=True, mesh_show_wireframe=True)
    o3d.visualization.draw_geometries([mesh_crop_bad], mesh_show_back_face=True, mesh_show_wireframe=True)
    o3d.visualization.draw_geometries([mesh_cropped], mesh_show_back_face=True, mesh_show_wireframe=True)
    

    【讨论】:

      猜你喜欢
      • 2013-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 2016-02-11
      • 1970-01-01
      • 2015-01-04
      • 1970-01-01
      相关资源
      最近更新 更多