Example #1
0
def main():
    args = parse_args()
    mesh = pymesh.load_mesh(args.input_mesh)

    f_indices = pymesh.get_degenerated_faces(mesh)
    if (len(f_indices) == 0):
        print("mesh does not have any degenerated faces")
        return

    v_indices = mesh.faces[f_indices].ravel()
    degenerated_faces = np.zeros(mesh.num_faces)
    degenerated_faces[f_indices] = 1.0
    degenerated = np.zeros(mesh.num_vertices)
    degenerated[v_indices] = 1.0
    mesh.add_attribute("degenerated_faces")
    mesh.set_attribute("degenerated_faces", degenerated_faces)
    mesh.add_attribute("degenerated")
    mesh.set_attribute("degenerated", degenerated)

    print("{} degenerated faces, consisting of {} vertices.".format(
        len(f_indices), np.count_nonzero(degenerated)))
    if args.verbose:
        print("Degenerated faces indices: {}".format(f_indices))

    pymesh.save_mesh(args.output_mesh, mesh, "degenerated",
                     "degenerated_faces")

    if args.extract_region is not None:
        region = pymesh.submesh(mesh, f_indices, 0)
        pymesh.save_mesh(args.extract_region, region,
                         *region.get_attribute_names())
def main():
    args = parse_args();
    mesh = pymesh.load_mesh(args.input_mesh);

    f_indices = pymesh.get_degenerated_faces(mesh);
    if (len(f_indices) == 0):
        print("mesh does not have any degenerated faces");
        return;

    v_indices = mesh.faces[f_indices].ravel();
    degenerated_faces = np.zeros(mesh.num_faces);
    degenerated_faces[f_indices] = 1.0;
    degenerated = np.zeros(mesh.num_vertices);
    degenerated[v_indices] = 1.0;
    mesh.add_attribute("degenerated_faces");
    mesh.set_attribute("degenerated_faces", degenerated_faces);
    mesh.add_attribute("degenerated");
    mesh.set_attribute("degenerated", degenerated);

    print("{} degenerated faces, consisting of {} vertices.".format(
        len(f_indices), np.count_nonzero(degenerated)));
    if args.verbose:
        print("Degenerated faces indices: {}".format(f_indices));

    pymesh.save_mesh(args.output_mesh, mesh, "degenerated", "degenerated_faces");

    if args.extract_region is not None:
        region = pymesh.submesh(mesh, f_indices, 0);
        pymesh.save_mesh(args.extract_region, region,
                *region.get_attribute_names());
Example #3
0
def repousse(mesh, logger):
    cell_ids = mesh.get_attribute("cell").ravel().astype(int);
    mesh.add_attribute("edge_length");
    tol = np.amax(mesh.get_attribute("edge_length")) * 0.1;

    bbox_min, bbox_max = mesh.bbox;
    scaling = 2.0 / norm(bbox_max - bbox_min);

    start_time = time();
    num_cells = np.amax(cell_ids)+1;
    results = [];
    for i in range(num_cells):
        to_keep = np.arange(mesh.num_faces, dtype=int)[cell_ids == i];
        if not np.any(to_keep):
            continue;

        cut_mesh = pymesh.submesh(mesh, to_keep, 0);
        pymesh.save_mesh("debug.msh", cut_mesh);
        cut_mesh, __ = pymesh.remove_degenerated_triangles(cut_mesh, 100);
        cut_mesh, __ = pymesh.split_long_edges(cut_mesh, tol);

        dof = cut_mesh.num_vertices;
        assembler = pymesh.Assembler(cut_mesh);
        L = assembler.assemble("laplacian");
        M = assembler.assemble("mass");

        L_rhs = M * np.ones(dof) * -0.5;
        bd_indices = cut_mesh.boundary_vertices;
        n = len(bd_indices);
        C = scipy.sparse.coo_matrix((np.ones(n),
            (np.arange(n, dtype=int), bd_indices)), shape=(n, dof));
        C_rhs = np.zeros(n);

        A = scipy.sparse.bmat([
            [-L, C.T],
            [C, None]
            ]);
        rhs = np.concatenate((L_rhs.ravel(), C_rhs));

        solver = pymesh.SparseSolver.create("SparseLU");
        solver.compute(A);
        x = solver.solve(rhs);

        z = x[:dof].reshape((-1, 1));

        vertices = np.hstack((cut_mesh.vertices, z));
        out_mesh = pymesh.form_mesh(vertices, cut_mesh.faces);
        results.append(out_mesh);

    finish_time = time();
    t = finish_time - start_time;
    logger.info("Repousse running time: {}".format(t));

    mesh = pymesh.merge_meshes(results);

    vertices = mesh.vertices[:,:2];
    mesh_2d = pymesh.form_mesh(vertices, mesh.faces);
    pymesh.save_mesh("out_2d.msh", mesh_2d)
    return mesh;
Example #4
0
def repousse(mesh, logger):
    cell_ids = mesh.get_attribute("cell").ravel().astype(int)
    mesh.add_attribute("edge_length")
    tol = np.amax(mesh.get_attribute("edge_length")) * 0.1

    bbox_min, bbox_max = mesh.bbox
    scaling = 2.0 / norm(bbox_max - bbox_min)

    start_time = time()
    num_cells = np.amax(cell_ids) + 1
    results = []
    for i in range(num_cells):
        to_keep = np.arange(mesh.num_faces, dtype=int)[cell_ids == i]
        if not np.any(to_keep):
            continue

        cut_mesh = pymesh.submesh(mesh, to_keep, 0)
        pymesh.save_mesh("debug.msh", cut_mesh)
        cut_mesh, __ = pymesh.remove_degenerated_triangles(cut_mesh, 100)
        cut_mesh, __ = pymesh.split_long_edges(cut_mesh, tol)

        dof = cut_mesh.num_vertices
        assembler = pymesh.Assembler(cut_mesh)
        L = assembler.assemble("laplacian")
        M = assembler.assemble("mass")

        L_rhs = M * np.ones(dof) * -0.5
        bd_indices = cut_mesh.boundary_vertices
        n = len(bd_indices)
        C = scipy.sparse.coo_matrix(
            (np.ones(n), (np.arange(n, dtype=int), bd_indices)),
            shape=(n, dof))
        C_rhs = np.zeros(n)

        A = scipy.sparse.bmat([[-L, C.T], [C, None]])
        rhs = np.concatenate((L_rhs.ravel(), C_rhs))

        solver = pymesh.SparseSolver.create("SparseLU")
        solver.compute(A)
        x = solver.solve(rhs)

        z = x[:dof].reshape((-1, 1))

        vertices = np.hstack((cut_mesh.vertices, z))
        out_mesh = pymesh.form_mesh(vertices, cut_mesh.faces)
        results.append(out_mesh)

    finish_time = time()
    t = finish_time - start_time
    logger.info("Repousse running time: {}".format(t))

    mesh = pymesh.merge_meshes(results)

    vertices = mesh.vertices[:, :2]
    mesh_2d = pymesh.form_mesh(vertices, mesh.faces)
    pymesh.save_mesh("out_2d.msh", mesh_2d)
    return mesh
Example #5
0
def bevel(wires, logger, remove_holes, dist):
    bbox_min, bbox_max = wires.bbox

    #wires = uniform_sampling(wires);
    mesh = constrained_triangulate(wires, logger, remove_holes)

    cell_ids = mesh.get_attribute("cell").ravel().astype(int)
    num_cells = np.amax(cell_ids) + 1

    comps = []
    for i in range(num_cells):
        to_keep = np.arange(mesh.num_faces, dtype=int)[cell_ids == i]
        if not np.any(to_keep):
            continue

        cut_mesh = pymesh.submesh(mesh, to_keep, 0)
        bd_edges = cut_mesh.boundary_edges
        vertices, edges, __ = pymesh.remove_isolated_vertices_raw(
            cut_mesh.vertices, bd_edges)
        bd_wires = pymesh.wires.WireNetwork.create_from_data(vertices, edges)

        offset_dir = np.zeros((bd_wires.num_vertices, 2))
        for ei in edges:
            v0 = ei[0]
            v1 = ei[1]
            adj_vts = bd_wires.get_vertex_neighbors(v0)
            if len(adj_vts) == 2:
                if adj_vts[0] == v1:
                    vp = adj_vts[1]
                else:
                    vp = adj_vts[0]
                e0 = vertices[v1] - vertices[v0]
                e1 = vertices[vp] - vertices[v0]
                e0 /= norm(e0)
                e1 /= norm(e1)
                theta = math.atan2(e0[0] * e1[1] - e0[1] * e1[0], e0.dot(e1))

                if abs(theta) > 0.99 * math.pi:
                    offset = np.array([-e0[1], e0[0]])
                    scale = 1.0
                else:
                    if theta > 0:
                        offset = e0 + e1
                        scale = math.sin(theta / 2)
                    else:
                        offset = -e0 - e1
                        scale = math.cos(math.pi / 2 + theta / 2)
                    offset /= norm(offset)
                offset_dir[v0] = offset * dist / scale

        offset_vertices = vertices + offset_dir
        vertices = np.vstack((vertices, offset_vertices))
        edges = np.vstack((edges, edges + bd_wires.num_vertices))

        vertices, edges, __ = pymesh.remove_duplicated_vertices_raw(
            vertices, edges, dist / 2)

        comp_wires = pymesh.wires.WireNetwork.create_from_data(
            vertices, edges)
        comp = constrained_triangulate(comp_wires, logger, True)
        comps.append(comp)

    mesh = pymesh.merge_meshes(comps)
    bd_vertices = mesh.boundary_vertices
    is_inside = np.ones(mesh.num_vertices, dtype=bool)
    is_inside[bd_vertices] = False

    vertices = np.hstack((mesh.vertices, np.zeros((mesh.num_vertices, 1))))
    vertices[is_inside, 2] = dist
    mesh = pymesh.form_mesh(vertices, mesh.faces)
    return mesh
Example #6
0
def main():
    args = parse_args();
    mesh = pymesh.load_mesh(args.input_mesh);
    mesh = pymesh.submesh(mesh, args.face_indices, args.n_ring)
    pymesh.save_mesh(args.output_mesh, mesh, *mesh.get_attribute_names());
Example #7
0
def bevel(wires, logger, remove_holes, dist):
    bbox_min, bbox_max = wires.bbox;

    #wires = uniform_sampling(wires);
    mesh = constrained_triangulate(wires, logger, remove_holes);

    cell_ids = mesh.get_attribute("cell").ravel().astype(int);
    num_cells = np.amax(cell_ids) + 1;

    comps = [];
    for i in range(num_cells):
        to_keep = np.arange(mesh.num_faces, dtype=int)[cell_ids == i];
        if not np.any(to_keep):
            continue;

        cut_mesh = pymesh.submesh(mesh, to_keep, 0);
        bd_edges = cut_mesh.boundary_edges;
        vertices, edges, __ = pymesh.remove_isolated_vertices_raw(
                cut_mesh.vertices, bd_edges);
        bd_wires = pymesh.wires.WireNetwork.create_from_data(vertices, edges);

        offset_dir = np.zeros((bd_wires.num_vertices, 2));
        for ei in edges:
            v0 = ei[0];
            v1 = ei[1];
            adj_vts = bd_wires.get_vertex_neighbors(v0);
            if len(adj_vts) == 2:
                if adj_vts[0] == v1:
                    vp = adj_vts[1];
                else:
                    vp = adj_vts[0];
                e0 = vertices[v1] - vertices[v0];
                e1 = vertices[vp] - vertices[v0];
                e0 /= norm(e0);
                e1 /= norm(e1);
                theta = math.atan2(e0[0]*e1[1] - e0[1]*e1[0], e0.dot(e1));

                if abs(theta) > 0.99 * math.pi:
                    offset = np.array([-e0[1], e0[0]]);
                    scale = 1.0;
                else:
                    if theta > 0:
                        offset = e0 + e1;
                        scale = math.sin(theta/2);
                    else:
                        offset = -e0 - e1
                        scale = math.cos(math.pi/2 + theta/2);
                    offset /= norm(offset);
                offset_dir[v0] = offset * dist / scale;

        offset_vertices = vertices + offset_dir;
        vertices = np.vstack((vertices, offset_vertices));
        edges = np.vstack((edges, edges + bd_wires.num_vertices));

        vertices, edges, __ = pymesh.remove_duplicated_vertices_raw(
                vertices, edges, dist/2);

        comp_wires = pymesh.wires.WireNetwork.create_from_data(vertices, edges);
        comp = constrained_triangulate(comp_wires, logger, True);
        comps.append(comp);

    mesh = pymesh.merge_meshes(comps);
    bd_vertices = mesh.boundary_vertices;
    is_inside = np.ones(mesh.num_vertices, dtype=bool);
    is_inside[bd_vertices] = False;

    vertices = np.hstack((mesh.vertices, np.zeros((mesh.num_vertices, 1))));
    vertices[is_inside, 2] = dist;
    mesh = pymesh.form_mesh(vertices, mesh.faces);
    return mesh;
def create_graph(mesh,
                 centroids,
                 normals,
                 robot_pos,
                 traversal_tresh=35,
                 bumpiness_tresh=0.37,
                 dbscan_eps=3,
                 dbscan_min_samples=2):
    """

    :param mesh:
    :param centroids:
    :param normals:
    :param closer_centroid_idx:
    :param traversal_tresh:
    :param dbscan_eps:
    :param dbscan_min_samples:
    :return:
    """
    print("Creating Graph... num faces:", mesh.num_faces)

    frontiers = extract_frontiers(mesh)
    print("Found ", frontiers, "frontiers")

    G = nx.Graph()

    for face_idx in xrange(mesh.num_faces):
        face = mesh.faces[face_idx]

        face_inclination = graph_search.MeshGraphSearch.calculate_traversal_angle(
            normals[face_idx])
        # if 0 <= face_inclination <= traversal_tresh or 180 - traversal_tresh <= face_inclination <= 180:
        if traversal_tresh < face_inclination < 180 - traversal_tresh:
            continue

        G.add_node(face_idx)

    for face_idx in list(G.nodes()):
        face_vertexes = mesh.faces[face_idx]
        for v in face_vertexes:
            vertex_adj_faces = mesh.get_vertex_adjacent_faces(v)
            for face_adjacent in vertex_adj_faces:
                if face_adjacent != face_idx and G.has_node(face_adjacent):
                    G.add_edge(face_idx, face_adjacent, weight=1)

    #print "G edge_list:", len(list(G.edges())), sorted(list(G.edges()))

    # remove small connected components
    for component in list(nx.connected_components(G)):
        if len(component) < 3:
            for node in component:
                G.remove_node(node)

    g_centroids = [(centroids[v][0], centroids[v][1], centroids[v][2])
                   for v in sorted(G.nodes())]
    centroid_g_dict = {i: v for i, v in enumerate(sorted(G.nodes()))}

    closer_centroid_idx = mesh_planner.mesh_helper.find_closer_centroid(
        g_centroids, robot_pos, force_return_closer=True)
    conn_nodes = nx.node_connected_component(
        G, centroid_g_dict[closer_centroid_idx])
    Gconn = G.subgraph(conn_nodes).copy()

    kdtree = spatial.KDTree(g_centroids)
    pairs = kdtree.query_pairs(bumpiness_tresh)
    print "pairs:", len(pairs), pairs

    joined_by_bumpiness_nodes = set()
    for pair in pairs:
        p1_conn = centroid_g_dict[
            pair[0]]  # node inside the biggest connected component
        p2_out = centroid_g_dict[
            pair[1]]  # node outside of the biggest connected component

        # if edge is already mapped, then drop it
        if Gconn.has_edge(p1_conn, p2_out) or Gconn.has_edge(p2_out, p1_conn):
            continue

        # if edge is only connecting inside the Gconn drop it
        if Gconn.has_node(p1_conn) and Gconn.has_node(p2_out):
            continue

        # if edge is not connecting Gconn with other connected elements drop it
        if not Gconn.has_node(p1_conn) and not Gconn.has_node(p2_out):
            continue

        if p1_conn not in Gconn.nodes():
            p1_conn, p2_out = p2_out, p1_conn

        # if there is already a connection between the outside element and Gconn
        intersecting_gconn_nodes = list(
            set(G.neighbors(p2_out)).intersection(Gconn.nodes()))
        if len(intersecting_gconn_nodes) > 1:
            continue

        # this node is an another connected subgraph
        # add this node and the other ones of the subgraph
        # if not Gconn.has_node(p2_out):
        #     small_component = nx.node_connected_component(G, p2_out)
        #     for n in small_component:
        #         if not Gconn.has_node(n):
        #             Gconn.add_node(n)

        small_comp_nodes = nx.node_connected_component(G, p2_out)
        Gsmall = G.subgraph(small_comp_nodes).copy()
        GconnTemp = Gconn.copy()
        Gconn = nx.compose(Gconn, Gsmall)

        for pair2 in pairs:
            pair2_1 = centroid_g_dict[pair2[0]]
            pair2_2 = centroid_g_dict[pair2[1]]

            if (Gsmall.has_node(pair2_1) and GconnTemp.has_node(pair2_2)) or \
                (GconnTemp.has_node(pair2_1) and Gsmall.has_node(pair2_2)):

                gconn_node = pair2_1
                outside_node = pair2_2

                if not GconnTemp.has_node(gconn_node):
                    outside_node, gconn_node = gconn_node, outside_node

                # intersecting_gconn_nodes = list(set(Gconn.neighbors(gconn_node)).intersection(Gsmall.nodes()))
                # if len(intersecting_gconn_nodes) > 0:
                #     continue

                Gconn.add_edge(pair2_1, pair2_2, weight=1)
                joined_by_bumpiness_nodes.add(pair2_1)
                joined_by_bumpiness_nodes.add(pair2_2)

                # a = np.asarray(centroids[pair2_1])
                # b = np.asarray(centroids[pair2_2])
                #
                # print("dist:", np.linalg.norm(a - b))

    # add remaining edges of the new component from the original graph
    for e in G.edges():
        p1_conn = e[0]
        p2_out = e[1]

        # if edge is already mapped, then drop it
        if Gconn.has_edge(p1_conn, p2_out) or Gconn.has_edge(p2_out, p1_conn):
            continue

        # if edge is only connecting inside the Gconn drop it
        if not p1_conn in Gconn.nodes() and not p2_out in Gconn.nodes():
            continue

        Gconn.add_edge(p1_conn, p2_out, weight=1)

    print "Gconn node_list:", list(Gconn.nodes())

    # numpy array of x,y,z positions in sorted node order
    gcon_centroids = [(centroids[v][0], centroids[v][1], centroids[v][2])
                      for v in sorted(Gconn.nodes())]
    xyz = np.array(gcon_centroids)
    # scalar colors
    scalars = xyz[:, 2]  #np.array(list(Gconn.nodes())) #xyz[:, 2]  #+ 5

    mlab.figure(1, bgcolor=(0, 0, 0))
    mlab.clf()

    # centroid_gcon_dict = {v: int(i) for i, v in enumerate(gcon_centroids)}
    # print "centroid_gcon_dict:", centroid_gcon_dict.keys()
    # edge_list = []
    # for e in Gconn.edges():
    #     e1 = (centroids[e[0]][0], centroids[e[0]][1], centroids[e[0]][2])
    #     e2 = (centroids[e[1]][0], centroids[e[1]][1], centroids[e[1]][2])
    #     edge_list.append([centroid_gcon_dict[e1], centroid_gcon_dict[e2]])
    #
    # edge_list = np.array(edge_list)
    # #edge_list = np.array(list(Gconn.edges()))
    # print "edge_list:", edge_list
    # pts.mlab_source.dataset.lines = np.array(edge_list)
    # #pts.update()
    # lines = mlab.pipeline.stripper(pts)
    # mlab.pipeline.surface(lines, color=(0.2, 0.4, 0.5), line_width=1.5, opacity=.9)  #colormap='Accent',

    # tube = mlab.pipeline.tube(pts, tube_radius=0.1)
    # mlab.pipeline.surface(tube, color=(0.8, 0.8, 0.8))

    # final_mesh_pts = []
    # for e in Gconn.nodes():
    #     final_mesh_pts.append((centroids[e][0], centroids[e][1], centroids[e][2]))
    #
    # final_mesh_faces = []
    # for e in Gconn.nodes():
    #     final_mesh_faces.append(mesh.faces[e])
    #
    # x, y, z = zip(*final_mesh_pts)
    # x = np.array(x)
    # y = np.array(y)
    # z = np.array(z)
    #
    # print "mesh.faces:", mesh.faces
    #
    # mlab.triangular_mesh(x, y, z, final_mesh_faces)

    filtered_mesh = pymesh.submesh(mesh, Gconn.nodes(), 1)
    pymesh.save_mesh("/tmp/tmp.stl", filtered_mesh)

    pts, _ = pymesh.mesh_to_graph(filtered_mesh)
    x, y, z = zip(*pts)
    x = np.array(x)
    y = np.array(y)
    z = np.array(z)
    mlab.triangular_mesh(x, y, z, filtered_mesh.faces)

    mlab.show()
Example #9
0
def main():
    args = parse_args()
    mesh = pymesh.load_mesh(args.input_mesh)
    mesh = pymesh.submesh(mesh, args.face_indices, args.n_ring)
    pymesh.save_mesh(args.output_mesh, mesh, *mesh.get_attribute_names())
Example #10
0
def main():
    args = parse_args()
    mesh = pymesh.load_mesh(args.input_mesh)
    if not mesh.has_attribute("corner_texture"):
        raise RuntimeError("Mesh contains no uv!")
    mesh.add_attribute("face_area")

    uv = mesh.get_attribute("corner_texture").reshape((-1, 2))
    if len(uv) == 0:
        raise RuntimeError("Invalid uv size.")

    faces = np.arange(mesh.num_faces * mesh.vertex_per_face).reshape(
        (-1, mesh.vertex_per_face))
    uv_mesh = pymesh.form_mesh(uv, faces)
    uv_mesh.add_attribute("face_area")

    ori_area = mesh.get_face_attribute("face_area")
    uv_area = uv_mesh.get_face_attribute("face_area")
    area_ratio = np.divide(uv_area, ori_area)

    uv_mesh.add_attribute("area_ratio")
    uv_mesh.set_attribute("area_ratio", area_ratio)
    mesh.add_attribute("area_ratio")
    mesh.set_attribute("area_ratio", area_ratio)
    mesh.add_attribute("u")
    mesh.set_attribute("u", uv[:, 0])

    if (args.separate):
        uv_mesh, info = pymesh.remove_duplicated_vertices(uv_mesh)
        comps = pymesh.separate_mesh(uv_mesh)
        segments = []
        uv = uv.reshape((-1, 6), order="C")
        vertices = mesh.vertices
        combined_uv = []
        for comp in comps:
            ori_vertex_indices = comp.get_attribute(
                "ori_vertex_index").ravel()
            ori_elem_indices = comp.get_attribute(
                "ori_elem_index").ravel().astype(int)

            segment = pymesh.submesh(mesh, ori_elem_indices, 0)
            ori_face_indices = segment.get_attribute(
                "ori_face_index").ravel().astype(int)
            ori_uv = uv[ori_face_indices]
            combined_uv.append(ori_uv)
            segment.add_attribute("corner_texture")
            segment.set_attribute("corner_texture", ori_uv.ravel())
            segments.append(segment)

        combined_uv = np.vstack(combined_uv)
        mesh = pymesh.merge_meshes(segments)
        mesh.add_attribute("corner_texture")
        mesh.set_attribute("corner_texture", combined_uv.ravel(order="C"))
    elif args.cut:
        uv_mesh, info = pymesh.remove_duplicated_vertices(uv_mesh)
        index_map = info["index_map"]
        vertices = mesh.vertices
        faces = mesh.faces
        vertices = vertices[faces.ravel(order="C")]
        new_vertices = np.zeros((uv_mesh.num_vertices, 3))
        new_vertices[index_map] = vertices

        mesh = pymesh.form_mesh(new_vertices, uv_mesh.faces)
        mesh.add_attribute("corner_texture")
        mesh.set_attribute("corner_texture", uv)

    if args.save_uv:
        pymesh.save_mesh(args.output_mesh, uv_mesh, *uv_mesh.attribute_names)
    else:
        pymesh.save_mesh(args.output_mesh, mesh, *mesh.attribute_names)