Triangle Mesh
triangle_mesh_connected_components.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28import numpy as np
29import copy
30
31if __name__ == "__main__":
32 bunny = o3d.data.BunnyMesh()
33 mesh = o3d.io.read_triangle_mesh(bunny.path)
34 mesh.compute_vertex_normals()
35
36 mesh = mesh.subdivide_midpoint(number_of_iterations=2)
37 vert = np.asarray(mesh.vertices)
38 min_vert, max_vert = vert.min(axis=0), vert.max(axis=0)
39 for _ in range(30):
40 cube = o3d.geometry.TriangleMesh.create_box()
41 cube.scale(0.005, center=cube.get_center())
42 cube.translate(
43 (
44 np.random.uniform(min_vert[0], max_vert[0]),
45 np.random.uniform(min_vert[1], max_vert[1]),
46 np.random.uniform(min_vert[2], max_vert[2]),
47 ),
48 relative=False,
49 )
50 mesh += cube
51 mesh.compute_vertex_normals()
52 print("Displaying input mesh ...")
53 o3d.visualization.draw([mesh])
54
55 print("Clustering connected triangles ...")
56 with o3d.utility.VerbosityContextManager(
57 o3d.utility.VerbosityLevel.Debug) as cm:
58 triangle_clusters, cluster_n_triangles, cluster_area = (
59 mesh.cluster_connected_triangles())
60 triangle_clusters = np.asarray(triangle_clusters)
61 cluster_n_triangles = np.asarray(cluster_n_triangles)
62 cluster_area = np.asarray(cluster_area)
63
64 print("Displaying mesh with small clusters removed ...")
65 mesh_0 = copy.deepcopy(mesh)
66 triangles_to_remove = cluster_n_triangles[triangle_clusters] < 100
67 mesh_0.remove_triangles_by_mask(triangles_to_remove)
68 o3d.visualization.draw([mesh_0])
triangle_mesh_cropping.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28import numpy as np
29import copy
30
31if __name__ == "__main__":
32 knot_mesh = o3d.data.KnotMesh()
33 mesh = o3d.io.read_triangle_mesh(knot_mesh.path)
34 mesh.compute_vertex_normals()
35 print("Displaying original mesh ...")
36 o3d.visualization.draw([mesh])
37
38 print("Displaying mesh of only the first half triangles ...")
39 mesh_cropped = copy.deepcopy(mesh)
40 mesh_cropped.triangles = o3d.utility.Vector3iVector(
41 np.asarray(mesh_cropped.triangles)[:len(mesh_cropped.triangles) //
42 2, :])
43 mesh_cropped.triangle_normals = o3d.utility.Vector3dVector(
44 np.asarray(mesh_cropped.triangle_normals)
45 [:len(mesh_cropped.triangle_normals) // 2, :])
46 print(mesh_cropped.triangles)
47 o3d.visualization.draw([mesh_cropped])
triangle_mesh_deformation.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import numpy as np
28import open3d as o3d
29import time
30import os
31import sys
32
33pyexample_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
34sys.path.append(pyexample_path)
35
36import open3d_example as o3dex
37
38
39def problem0():
40 mesh = o3dex.get_plane_mesh(height=1, width=1)
41 mesh = mesh.subdivide_midpoint(3)
42 vertices = np.asarray(mesh.vertices)
43 static_ids = [
44 1, 46, 47, 48, 16, 51, 49, 50, 6, 31, 33, 32, 11, 26, 27, 25, 0, 64, 65,
45 20, 66, 68, 67, 7, 69, 71, 70, 22, 72, 74, 73, 3, 15, 44, 43, 45, 5, 41,
46 40, 42, 13, 39, 37, 38, 2, 56, 55, 19, 61, 60, 59, 8, 76, 75, 77, 23
47 ]
48 static_positions = []
49 for id in static_ids:
50 static_positions.append(vertices[id])
51 handle_ids = [4]
52 handle_positions = [vertices[4] + np.array((0, 0, 0.4))]
53
54 return mesh, static_ids + handle_ids, static_positions + handle_positions
55
56
57def problem1():
58 mesh = o3dex.get_plane_mesh(height=1, width=1)
59 mesh = mesh.subdivide_midpoint(3)
60 vertices = np.asarray(mesh.vertices)
61 static_ids = [
62 1, 46, 15, 43, 5, 40, 13, 38, 2, 56, 37, 39, 42, 41, 45, 44, 48, 47
63 ]
64 static_positions = []
65 for id in static_ids:
66 static_positions.append(vertices[id])
67 handle_ids = [21]
68 handle_positions = [vertices[21] + np.array((0, 0, 0.4))]
69
70 return mesh, static_ids + handle_ids, static_positions + handle_positions
71
72
73def problem2():
74 armadillo_data = o3d.data.ArmadilloMesh()
75 mesh = o3d.io.read_triangle_mesh(armadillo_data.path)
76 vertices = np.asarray(mesh.vertices)
77 static_ids = [idx for idx in np.where(vertices[:, 1] < -30)[0]]
78 static_positions = []
79 for id in static_ids:
80 static_positions.append(vertices[id])
81 handle_ids = [2490]
82 handle_positions = [vertices[2490] + np.array((-40, -40, -40))]
83
84 return mesh, static_ids + handle_ids, static_positions + handle_positions
85
86
87if __name__ == "__main__":
88 o3d.utility.set_verbosity_level(o3d.utility.Debug)
89
90 for mesh, constraint_ids, constraint_pos in [
91 problem0(), problem1(), problem2()
92 ]:
93 constraint_ids = np.array(constraint_ids, dtype=np.int32)
94 constraint_pos = o3d.utility.Vector3dVector(constraint_pos)
95 tic = time.time()
96 mesh_prime = mesh.deform_as_rigid_as_possible(
97 o3d.utility.IntVector(constraint_ids), constraint_pos, max_iter=50)
98 print("deform took {}[s]".format(time.time() - tic))
99 mesh_prime.compute_vertex_normals()
100
101 mesh.paint_uniform_color((1, 0, 0))
102 handles = o3d.geometry.PointCloud()
103 handles.points = constraint_pos
104 handles.paint_uniform_color((0, 1, 0))
105 o3d.visualization.draw_geometries([mesh, mesh_prime, handles])
106
107 o3d.utility.set_verbosity_level(o3d.utility.Info)
triangle_mesh_filtering_average.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27from numpy.random.mtrand import laplace
28import open3d as o3d
29import numpy as np
30
31
32def average_filtering():
33 # Create noisy mesh.
34 knot_mesh = o3d.data.KnotMesh()
35 mesh_in = o3d.io.read_triangle_mesh(knot_mesh.path)
36 vertices = np.asarray(mesh_in.vertices)
37 noise = 5
38 vertices += np.random.uniform(0, noise, size=vertices.shape)
39 mesh_in.vertices = o3d.utility.Vector3dVector(vertices)
40 mesh_in.compute_vertex_normals()
41 print("Displaying input mesh ...")
42 o3d.visualization.draw_geometries([mesh_in])
43
44 print("Displaying output of average mesh filter after 1 iteration ...")
45 mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=1)
46 mesh_out.compute_vertex_normals()
47 o3d.visualization.draw_geometries([mesh_out])
48
49 print("Displaying output of average mesh filter after 5 iteration ...")
50 mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=5)
51 mesh_out.compute_vertex_normals()
52 o3d.visualization.draw_geometries([mesh_out])
53
54
55def laplace_filtering():
56 # Create noisy mesh.
57 knot_mesh = o3d.data.KnotMesh()
58 mesh_in = o3d.io.read_triangle_mesh(knot_mesh.path)
59 vertices = np.asarray(mesh_in.vertices)
60 noise = 5
61 vertices += np.random.uniform(0, noise, size=vertices.shape)
62 mesh_in.vertices = o3d.utility.Vector3dVector(vertices)
63 mesh_in.compute_vertex_normals()
64 print("Displaying input mesh ...")
65 o3d.visualization.draw_geometries([mesh_in])
66
67 print("Displaying output of Laplace mesh filter after 10 iteration ...")
68 mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=10)
69 mesh_out.compute_vertex_normals()
70 o3d.visualization.draw_geometries([mesh_out])
71
72 print("Displaying output of Laplace mesh filter after 50 iteration ...")
73 mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=50)
74 mesh_out.compute_vertex_normals()
75 o3d.visualization.draw_geometries([mesh_out])
76
77
78def taubin_filtering():
79 # Create noisy mesh.
80 knot_mesh = o3d.data.KnotMesh()
81 mesh_in = o3d.io.read_triangle_mesh(knot_mesh.path)
82 vertices = np.asarray(mesh_in.vertices)
83 noise = 5
84 vertices += np.random.uniform(0, noise, size=vertices.shape)
85 mesh_in.vertices = o3d.utility.Vector3dVector(vertices)
86 mesh_in.compute_vertex_normals()
87 print("Displaying input mesh ...")
88 o3d.visualization.draw_geometries([mesh_in])
89
90 print("Displaying output of Taubin mesh filter after 10 iteration ...")
91 mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=10)
92 mesh_out.compute_vertex_normals()
93 o3d.visualization.draw_geometries([mesh_out])
94
95 print("Displaying output of Taubin mesh filter after 100 iteration ...")
96 mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=100)
97 mesh_out.compute_vertex_normals()
98 o3d.visualization.draw_geometries([mesh_out])
99
100
101if __name__ == "__main__":
102 average_filtering()
103 laplace_filtering()
104 taubin_filtering()
triangle_mesh_from_point_cloud_alpha_shapes.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28
29if __name__ == "__main__":
30 bunny = o3d.data.BunnyMesh()
31 mesh = o3d.io.read_triangle_mesh(bunny.path)
32 mesh.compute_vertex_normals()
33
34 pcd = mesh.sample_points_poisson_disk(750)
35 print("Displaying input pointcloud ...")
36 o3d.visualization.draw_geometries([pcd])
37 alpha = 0.03
38 print(f"alpha={alpha:.3f}")
39 print('Running alpha shapes surface reconstruction ...')
40 mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_alpha_shape(
41 pcd, alpha)
42 mesh.compute_triangle_normals(normalized=True)
43 print("Displaying reconstructed mesh ...")
44 o3d.visualization.draw_geometries([mesh], mesh_show_back_face=True)
triangle_mesh_from_point_cloud_ball_pivoting.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28
29if __name__ == "__main__":
30 bunny = o3d.data.BunnyMesh()
31 gt_mesh = o3d.io.read_triangle_mesh(bunny.path)
32 gt_mesh.compute_vertex_normals()
33
34 pcd = gt_mesh.sample_points_poisson_disk(3000)
35 print("Displaying input pointcloud ...")
36 o3d.visualization.draw([pcd], point_size=5)
37
38 radii = [0.005, 0.01, 0.02, 0.04]
39 print('Running ball pivoting surface reconstruction ...')
40 rec_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(
41 pcd, o3d.utility.DoubleVector(radii))
42 print("Displaying reconstructed mesh ...")
43 o3d.visualization.draw([rec_mesh])
triangle_mesh_from_point_cloud_poisson.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28import numpy as np
29
30if __name__ == "__main__":
31 eagle = o3d.data.EaglePointCloud()
32 pcd = o3d.io.read_point_cloud(eagle.path)
33 R = pcd.get_rotation_matrix_from_xyz((np.pi, -np.pi / 4, 0))
34 pcd.rotate(R, center=(0, 0, 0))
35 print('Displaying input pointcloud ...')
36 o3d.visualization.draw([pcd])
37
38 print('Running Poisson surface reconstruction ...')
39 mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
40 pcd, depth=9)
41 print('Displaying reconstructed mesh ...')
42 o3d.visualization.draw([mesh])
triangle_mesh_normal_estimation.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28import numpy as np
29
30if __name__ == "__main__":
31 knot_mesh = o3d.data.KnotMesh()
32 mesh = o3d.io.read_triangle_mesh(knot_mesh.path)
33 print("Displaying mesh without normals ...")
34 # Invalidate existing normals.
35 mesh.triangle_normals = o3d.utility.Vector3dVector(np.zeros((1, 3)))
36 print("normals: \n", np.asarray(mesh.triangle_normals))
37 o3d.visualization.draw([mesh])
38
39 print("Computing normals and rendering it ...")
40 mesh.compute_vertex_normals()
41 print("normals: \n", np.asarray(mesh.triangle_normals))
42 o3d.visualization.draw([mesh])
triangle_mesh_properties.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28import numpy as np
29import os
30import sys
31
32pyexample_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
33sys.path.append(pyexample_path)
34
35import open3d_example as o3dex
36
37
38def check_properties(name, mesh):
39 mesh.compute_vertex_normals()
40
41 edge_manifold = mesh.is_edge_manifold(allow_boundary_edges=True)
42 edge_manifold_boundary = mesh.is_edge_manifold(allow_boundary_edges=False)
43 vertex_manifold = mesh.is_vertex_manifold()
44 self_intersecting = mesh.is_self_intersecting()
45 watertight = mesh.is_watertight()
46 orientable = mesh.is_orientable()
47
48 print(name)
49 print(f" edge_manifold: {edge_manifold}")
50 print(f" edge_manifold_boundary: {edge_manifold_boundary}")
51 print(f" vertex_manifold: {vertex_manifold}")
52 print(f" self_intersecting: {self_intersecting}")
53 print(f" watertight: {watertight}")
54 print(f" orientable: {orientable}")
55
56 geoms = [mesh]
57 if not edge_manifold:
58 edges = mesh.get_non_manifold_edges(allow_boundary_edges=True)
59 geoms.append(o3dex.edges_to_lineset(mesh, edges, (1, 0, 0)))
60 if not edge_manifold_boundary:
61 edges = mesh.get_non_manifold_edges(allow_boundary_edges=False)
62 geoms.append(o3dex.edges_to_lineset(mesh, edges, (0, 1, 0)))
63 if not vertex_manifold:
64 verts = np.asarray(mesh.get_non_manifold_vertices())
65 pcl = o3d.geometry.PointCloud(
66 points=o3d.utility.Vector3dVector(np.asarray(mesh.vertices)[verts]))
67 pcl.paint_uniform_color((0, 0, 1))
68 geoms.append(pcl)
69 if self_intersecting:
70 intersecting_triangles = np.asarray(
71 mesh.get_self_intersecting_triangles())
72 intersecting_triangles = intersecting_triangles[0:1]
73 intersecting_triangles = np.unique(intersecting_triangles)
74 print(" # visualize self-intersecting triangles")
75 triangles = np.asarray(mesh.triangles)[intersecting_triangles]
76 edges = [
77 np.vstack((triangles[:, i], triangles[:, j]))
78 for i, j in [(0, 1), (1, 2), (2, 0)]
79 ]
80 edges = np.hstack(edges).T
81 edges = o3d.utility.Vector2iVector(edges)
82 geoms.append(o3dex.edges_to_lineset(mesh, edges, (1, 0, 1)))
83 o3d.visualization.draw_geometries(geoms, mesh_show_back_face=True)
84
85
86if __name__ == "__main__":
87 knot_mesh = o3d.data.KnotMesh()
88 mesh = o3d.io.read_triangle_mesh(knot_mesh.path)
89 check_properties('KnotMesh', mesh)
90 check_properties('Mobius',
91 o3d.geometry.TriangleMesh.create_mobius(twists=1))
92 check_properties("non-manifold edge", o3dex.get_non_manifold_edge_mesh())
93 check_properties("non-manifold vertex",
94 o3dex.get_non_manifold_vertex_mesh())
95 check_properties("open box", o3dex.get_open_box_mesh())
96 check_properties("intersecting_boxes", o3dex.get_intersecting_boxes_mesh())
triangle_mesh_sampling.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28
29if __name__ == "__main__":
30 bunny = o3d.data.BunnyMesh()
31 mesh = o3d.io.read_triangle_mesh(bunny.path)
32 mesh.compute_vertex_normals()
33
34 print("Displaying input mesh ...")
35 o3d.visualization.draw([mesh])
36
37 print("Displaying pointcloud using uniform sampling ...")
38 pcd = mesh.sample_points_uniformly(number_of_points=1000)
39 o3d.visualization.draw([pcd], point_size=5)
40
41 print("Displaying pointcloud using Poisson disk sampling ...")
42 pcd = mesh.sample_points_poisson_disk(number_of_points=1000, init_factor=5)
43 o3d.visualization.draw([pcd], point_size=5)
triangle_mesh_simplification_decimation.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28
29if __name__ == "__main__":
30 bunny = o3d.data.BunnyMesh()
31 mesh_in = o3d.io.read_triangle_mesh(bunny.path)
32 mesh_in.compute_vertex_normals()
33
34 print("Before Simplification: ", mesh_in)
35 o3d.visualization.draw_geometries([mesh_in])
36
37 mesh_smp = mesh_in.simplify_quadric_decimation(
38 target_number_of_triangles=6500)
39 print("After Simplification target number of triangles = 6500:\n", mesh_smp)
40 o3d.visualization.draw_geometries([mesh_smp])
41
42 mesh_smp = mesh_in.simplify_quadric_decimation(
43 target_number_of_triangles=1700)
44 print("After Simplification target number of triangles = 1700:\n", mesh_smp)
45 o3d.visualization.draw_geometries([mesh_smp])
triangle_mesh_simplification_vertex_clustering.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28
29if __name__ == "__main__":
30 bunny = o3d.data.BunnyMesh()
31 mesh_in = o3d.io.read_triangle_mesh(bunny.path)
32 mesh_in.compute_vertex_normals()
33
34 print("Before Simplification: ", mesh_in)
35 o3d.visualization.draw_geometries([mesh_in])
36
37 voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 32
38 mesh_smp = mesh_in.simplify_vertex_clustering(
39 voxel_size=voxel_size,
40 contraction=o3d.geometry.SimplificationContraction.Average)
41 print("After Simplification with voxel size =", voxel_size, ":\n", mesh_smp)
42 o3d.visualization.draw_geometries([mesh_smp])
43
44 voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 16
45 mesh_smp = mesh_in.simplify_vertex_clustering(
46 voxel_size=voxel_size,
47 contraction=o3d.geometry.SimplificationContraction.Average)
48 print("After Simplification with voxel size =", voxel_size, ":\n", mesh_smp)
49 o3d.visualization.draw_geometries([mesh_smp])
triangle_mesh_subdivision.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28
29if __name__ == "__main__":
30 knot_mesh = o3d.data.KnotMesh()
31 mesh = o3d.io.read_triangle_mesh(knot_mesh.path)
32 mesh.compute_vertex_normals()
33 print("Before Subdivision: ", mesh)
34 print("Displaying input mesh ...")
35 o3d.visualization.draw_geometries([mesh], mesh_show_wireframe=True)
36 mesh = mesh.subdivide_loop(number_of_iterations=1)
37 print("After Subdivision: ", mesh)
38 print("Displaying subdivided mesh ...")
39 o3d.visualization.draw_geometries([mesh], mesh_show_wireframe=True)
triangle_mesh_transformation.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28import numpy as np
29import copy
30
31
32def translate():
33 mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
34 mesh_tx = copy.deepcopy(mesh).translate((1.3, 0, 0))
35 mesh_ty = copy.deepcopy(mesh).translate((0, 1.3, 0))
36 print('Displaying original and translated geometries ...')
37 o3d.visualization.draw([{
38 "name": "Original Geometry",
39 "geometry": mesh
40 }, {
41 "name": "Translated (in X) Geometry",
42 "geometry": mesh_tx
43 }, {
44 "name": "Translated (in Y) Geometry",
45 "geometry": mesh_ty
46 }],
47 show_ui=True)
48
49
50def rotate():
51 mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
52 mesh_r = copy.deepcopy(mesh)
53 R = mesh.get_rotation_matrix_from_xyz((np.pi / 2, 0, np.pi / 4))
54 mesh_r.rotate(R, center=(0, 0, 0))
55 print('Displaying original and rotated geometries ...')
56 o3d.visualization.draw([{
57 "name": "Original Geometry",
58 "geometry": mesh
59 }, {
60 "name": "Rotated Geometry",
61 "geometry": mesh_r
62 }],
63 show_ui=True)
64
65
66def scale():
67 mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
68 mesh_s = copy.deepcopy(mesh).translate((2, 0, 0))
69 mesh_s.scale(0.5, center=mesh_s.get_center())
70 print('Displaying original and scaled geometries ...')
71 o3d.visualization.draw([{
72 "name": "Original Geometry",
73 "geometry": mesh
74 }, {
75 "name": "Scaled Geometry",
76 "geometry": mesh_s
77 }],
78 show_ui=True)
79
80
81def transform():
82 mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
83 T = np.eye(4)
84 T[:3, :3] = mesh.get_rotation_matrix_from_xyz((0, np.pi / 3, np.pi / 2))
85 T[0, 3] = 1
86 T[1, 3] = 1.3
87 print(T)
88 mesh_t = copy.deepcopy(mesh).transform(T)
89 print('Displaying original and transformed geometries ...')
90 o3d.visualization.draw([{
91 "name": "Original Geometry",
92 "geometry": mesh
93 }, {
94 "name": "Transformed Geometry",
95 "geometry": mesh_t
96 }],
97 show_ui=True)
98
99
100if __name__ == "__main__":
101
102 translate()
103 rotate()
104 scale()
105 transform()
triangle_mesh_with_numpy.py
1# ----------------------------------------------------------------------------
2# - Open3D: www.open3d.org -
3# ----------------------------------------------------------------------------
4# The MIT License (MIT)
5#
6# Copyright (c) 2018-2021 www.open3d.org
7#
8# Permission is hereby granted, free of charge, to any person obtaining a copy
9# of this software and associated documentation files (the "Software"), to deal
10# in the Software without restriction, including without limitation the rights
11# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12# copies of the Software, and to permit persons to whom the Software is
13# furnished to do so, subject to the following conditions:
14#
15# The above copyright notice and this permission notice shall be included in
16# all copies or substantial portions of the Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25# ----------------------------------------------------------------------------
26
27import open3d as o3d
28import numpy as np
29
30if __name__ == "__main__":
31 # Read a mesh and get its data as numpy arrays.
32 knot_mesh = o3d.data.KnotMesh()
33 mesh = o3d.io.read_triangle_mesh(knot_mesh.path)
34 mesh.paint_uniform_color([0.5, 0.1, 0.3])
35 print('Vertices:')
36 print(np.asarray(mesh.vertices))
37 print('Vertex Colors:')
38 print(np.asarray(mesh.vertex_colors))
39 print('Vertex Normals:')
40 print(np.asarray(mesh.vertex_normals))
41 print('Triangles:')
42 print(np.asarray(mesh.triangles))
43 print('Triangle Normals:')
44 print(np.asarray(mesh.triangle_normals))
45 print("Displaying mesh ...")
46 print(mesh)
47 o3d.visualization.draw([mesh])
48
49 # Create a mesh using numpy arrays with random colors.
50 N = 5
51 vertices = o3d.utility.Vector3dVector(
52 np.array([[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1], [0.5, 0.5, 0.5]]))
53 triangles = o3d.utility.Vector3iVector(
54 np.array([[0, 1, 2], [0, 2, 3], [0, 4, 1], [1, 4, 2], [2, 4, 3],
55 [3, 4, 0]]))
56 mesh_np = o3d.geometry.TriangleMesh(vertices, triangles)
57 mesh_np.vertex_colors = o3d.utility.Vector3dVector(
58 np.random.uniform(0, 1, size=(N, 3)))
59 mesh_np.compute_vertex_normals()
60 print(np.asarray(mesh_np.triangle_normals))
61 print("Displaying mesh made using numpy ...")
62 o3d.visualization.draw_geometries([mesh_np])