Triangle Mesh#
triangle_mesh.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8# examples/Python/Basic/mesh.py
9
10import copy
11import numpy as np
12import cloudViewer as cv3d
13
14if __name__ == "__main__":
15
16 print("Testing mesh in cloudViewer ...")
17 knot_data = cv3d.data.KnotMesh()
18 mesh = cv3d.io.read_triangle_mesh(knot_data.path)
19 mesh.compute_vertex_normals()
20 print(mesh)
21 print(np.asarray(mesh.get_vertices()))
22 print(np.asarray(mesh.get_triangles()))
23 print("")
24
25 # triangulation
26 # DELAUNAY_2D_AXIS_ALIGNED or DELAUNAY_2D_BEST_LS_PLANE.
27 triangulation_type = cv3d.geometry.DELAUNAY_2D_BEST_LS_PLANE
28 new_mesh = cv3d.geometry.ccMesh.triangulate(
29 cloud=mesh.get_associated_cloud(), type=triangulation_type)
30 new_mesh.compute_vertex_normals()
31 cv3d.visualization.draw_geometries([new_mesh])
32
33 # triangulation between with two polylines
34 cv3d.data.set_custom_downloads_prefix(
35 "https://github.com/Asher-1/cloudViewer_downloads/releases/download/")
36 polylines_data = cv3d.data.PolylinesModel()
37 entity = cv3d.io.read_entity(polylines_data.path)
38 polylines = entity.filter_children(recursive=False,
39 filter=cv3d.geometry.ccHObject.POLY_LINE)
40 print(polylines)
41 assert len(polylines) > 1
42 mesh_polys = cv3d.geometry.ccMesh.triangulate_two_polylines(
43 poly1=polylines[0], poly2=polylines[1])
44 mesh_polys.compute_vertex_normals()
45 cv3d.visualization.draw_geometries(polylines + [mesh_polys])
46
47 print("Try to render a mesh with normals (exist: " +
48 str(mesh.has_vertex_normals()) + ") and colors (exist: " +
49 str(mesh.has_vertex_colors()) + ")")
50 mesh.set_temp_color([0, 0, 1])
51 mesh.set_opacity(0.5)
52 mesh.show_colors(True)
53 cv3d.visualization.draw_geometries([mesh])
54 print("A mesh with no normals and no colors does not seem good.")
55
56 print("Computing normal and rendering it.")
57 mesh.compute_vertex_normals()
58 print(np.asarray(mesh.get_triangle_normals()))
59 cv3d.visualization.draw_geometries([mesh])
60
61 print("We make a partial mesh of only the first half triangles.")
62 mesh1 = copy.deepcopy(mesh)
63 triangles = np.asarray(mesh1.get_triangles())
64 triangle_normals = np.asarray(mesh1.get_triangle_normals())
65 mesh1.set_triangles(
66 cv3d.utility.Vector3iVector(triangles[:len(triangles) // 2, :]))
67 mesh1.set_triangle_normals(
68 cv3d.utility.Vector3dVector(triangle_normals[:len(triangle_normals) //
69 2, :]))
70 print(mesh1.get_triangles())
71 cv3d.visualization.draw_geometries([mesh1])
72
73 print("Painting the mesh")
74 mesh1.paint_uniform_color([1, 0.706, 0])
75 cv3d.visualization.draw_geometries([mesh1])
triangle_mesh_collision.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import numpy as np
9import cloudViewer as cv3d
10import time
11
12import os
13import sys
14
15if __name__ == "__main__":
16 # intersection tests
17 print("#" * 80)
18 print("Intersection tests")
19 print("#" * 80)
20 np.random.seed(30)
21 bbox = cv3d.geometry.ccMesh.create_box(20, 20, 20).translate(
22 (-10, -10, -10))
23 meshes = [cv3d.geometry.ccMesh.create_box() for _ in range(20)]
24 meshes.append(cv3d.geometry.ccMesh.create_sphere())
25 meshes.append(cv3d.geometry.ccMesh.create_cone())
26 meshes.append(cv3d.geometry.ccMesh.create_torus())
27 dirs = [np.random.uniform(-0.1, 0.1, size=(3,)) for _ in meshes]
28 for mesh in meshes:
29 mesh.compute_vertex_normals()
30 mesh.paint_uniform_color((0.5, 0.5, 0.5))
31 mesh.translate(np.random.uniform(-7.5, 7.5, size=(3,)))
32 vis = cv3d.visualization.Visualizer()
33 vis.create_window()
34 for mesh in meshes:
35 vis.add_geometry(mesh)
36 for iter in range(1000):
37 for mesh, dir in zip(meshes, dirs):
38 mesh.paint_uniform_color((0.5, 0.5, 0.5))
39 mesh.translate(dir)
40 for idx0, mesh0 in enumerate(meshes):
41 collision = False
42 collision = collision or mesh0.is_intersecting(bbox)
43 for idx1, mesh1 in enumerate(meshes):
44 if collision:
45 break
46 if idx0 == idx1:
47 continue
48 collision = collision or mesh0.is_intersecting(mesh1)
49 if collision:
50 mesh0.paint_uniform_color((1, 0, 0))
51 dirs[idx0] *= -1
52 vis.update_geometry(mesh0)
53 vis.poll_events()
54 vis.update_renderer()
55 time.sleep(0.05)
56 vis.destroy_window()
triangle_mesh_connected_components.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8# examples/Python/Basic/mesh_connected_components.py
9
10import cloudViewer as cv3d
11import numpy as np
12import copy
13import time
14
15if __name__ == "__main__":
16 cv3d.utility.set_verbosity_level(cv3d.utility.Debug)
17
18 print("Generate data")
19 bunny = cv3d.data.BunnyMesh()
20 mesh = cv3d.io.read_triangle_mesh(bunny.path)
21 mesh.compute_vertex_normals()
22
23 print("Subdivide mesh to make it a bit harder")
24 mesh = mesh.subdivide_midpoint(number_of_iterations=2)
25 print(mesh)
26
27 vert = np.asarray(mesh.get_vertices())
28 min_vert, max_vert = vert.min(axis=0), vert.max(axis=0)
29 for _ in range(30):
30 cube = cv3d.geometry.ccMesh.create_box()
31 cube.scale(0.005)
32 cube.translate(
33 (
34 np.random.uniform(min_vert[0], max_vert[0]),
35 np.random.uniform(min_vert[1], max_vert[1]),
36 np.random.uniform(min_vert[2], max_vert[2]),
37 ),
38 relative=False,
39 )
40 mesh += cube
41 mesh.compute_vertex_normals()
42 print("Displaying input mesh ...")
43 cv3d.visualization.draw([mesh])
44
45 print("Cluster connected triangles")
46 with cv3d.utility.VerbosityContextManager(
47 cv3d.utility.VerbosityLevel.Debug) as cm:
48 triangle_clusters, cluster_n_triangles, cluster_area = (
49 mesh.cluster_connected_triangles())
50 triangle_clusters = np.asarray(triangle_clusters)
51 cluster_n_triangles = np.asarray(cluster_n_triangles)
52 cluster_area = np.asarray(cluster_area)
53
54 print("Displaying mesh with small clusters removed ...")
55 mesh_0 = copy.deepcopy(mesh)
56 triangles_to_remove = cluster_n_triangles[triangle_clusters] < 100
57 mesh_0.remove_triangles_by_mask(triangles_to_remove)
58 cv3d.visualization.draw([mesh_0])
triangle_mesh_cropping.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8# examples/Python/Basic/mesh_filter.py
9
10import numpy as np
11import cloudViewer as cv3d
12import copy
13
14if __name__ == "__main__":
15 knot_mesh = cv3d.data.KnotMesh()
16 mesh = cv3d.io.read_triangle_mesh(knot_mesh.path)
17 mesh.compute_vertex_normals()
18 print("Displaying original mesh ...")
19 cv3d.visualization.draw([mesh])
20
21 print("Displaying mesh of only the first half triangles ...")
22 mesh_cropped = copy.deepcopy(mesh)
23 mesh_cropped.set_triangles(
24 cv3d.utility.Vector3iVector(
25 np.asarray(
26 mesh_cropped.triangles())[:len(mesh_cropped.triangles()) //
27 2, :]))
28 mesh_cropped.set_triangle_normals(
29 cv3d.utility.Vector3dVector(
30 np.asarray(mesh_cropped.triangle_normals())
31 [:len(mesh_cropped.triangle_normals()) // 2, :]))
32 print(mesh_cropped.triangles())
33 cv3d.visualization.draw([mesh_cropped])
triangle_mesh_deformation.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import numpy as np
9import cloudViewer as cv3d
10import time
11import os
12import sys
13
14pyexample_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15sys.path.append(pyexample_path)
16
17import cloudViewer_example as cv3dex
18
19
20def problem0():
21 mesh = cv3dex.get_plane_mesh(height=1, width=1)
22 mesh = mesh.subdivide_midpoint(3)
23 vertices = np.asarray(mesh.vertices())
24 static_ids = [
25 1, 46, 47, 48, 16, 51, 49, 50, 6, 31, 33, 32, 11, 26, 27, 25, 0, 64, 65,
26 20, 66, 68, 67, 7, 69, 71, 70, 22, 72, 74, 73, 3, 15, 44, 43, 45, 5, 41,
27 40, 42, 13, 39, 37, 38, 2, 56, 55, 19, 61, 60, 59, 8, 76, 75, 77, 23
28 ]
29 static_positions = []
30 for id in static_ids:
31 static_positions.append(vertices[id])
32 handle_ids = [4]
33 handle_positions = [vertices[4] + np.array((0, 0, 0.4))]
34
35 return mesh, static_ids + handle_ids, static_positions + handle_positions
36
37
38def problem1():
39 mesh = cv3dex.get_plane_mesh(height=1, width=1)
40 mesh = mesh.subdivide_midpoint(3)
41 vertices = np.asarray(mesh.vertices())
42 static_ids = [
43 1, 46, 15, 43, 5, 40, 13, 38, 2, 56, 37, 39, 42, 41, 45, 44, 48, 47
44 ]
45 static_positions = []
46 for id in static_ids:
47 static_positions.append(vertices[id])
48 handle_ids = [21]
49 handle_positions = [vertices[21] + np.array((0, 0, 0.4))]
50
51 return mesh, static_ids + handle_ids, static_positions + handle_positions
52
53
54def problem2():
55 armadillo_data = cv3d.data.ArmadilloMesh()
56 mesh = cv3d.io.read_triangle_mesh(armadillo_data.path)
57 vertices = np.asarray(mesh.vertices())
58 static_ids = [idx for idx in np.where(vertices[:, 1] < -30)[0]]
59 static_positions = []
60 for id in static_ids:
61 static_positions.append(vertices[id])
62 handle_ids = [2490]
63 handle_positions = [vertices[2490] + np.array((-40, -40, -40))]
64
65 return mesh, static_ids + handle_ids, static_positions + handle_positions
66
67
68if __name__ == "__main__":
69 cv3d.utility.set_verbosity_level(cv3d.utility.Debug)
70
71 for mesh, constraint_ids, constraint_pos in [
72 problem0(), problem1(), problem2()
73 ]:
74 constraint_ids = np.array(constraint_ids, dtype=np.int32)
75 constraint_pos = cv3d.utility.Vector3dVector(constraint_pos)
76 tic = time.time()
77 mesh_prime = mesh.deform_as_rigid_as_possible(
78 cv3d.utility.IntVector(constraint_ids), constraint_pos, max_iter=50)
79 print("deform took {}[s]".format(time.time() - tic))
80 mesh_prime.compute_vertex_normals()
81
82 mesh.paint_uniform_color((1, 0, 0))
83 handles = cv3d.geometry.ccPointCloud()
84 handles.set_points(constraint_pos)
85 handles.paint_uniform_color((0, 1, 0))
86 cv3d.visualization.draw_geometries([mesh, mesh_prime, handles],
87 mesh_show_back_face=True)
88
89 cv3d.utility.set_verbosity_level(cv3d.utility.Info)
triangle_mesh_filtering_average.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import numpy as np
9import cloudViewer as cv3d
10
11
12def average_filtering():
13 # Create noisy mesh.
14 knot_mesh = cv3d.data.KnotMesh()
15 mesh_in = cv3d.io.read_triangle_mesh(knot_mesh.path)
16 vertices = np.asarray(mesh_in.vertices())
17 noise = 5
18 vertices += np.random.uniform(0, noise, size=vertices.shape)
19 mesh_in.set_vertices(cv3d.utility.Vector3dVector(vertices))
20 mesh_in.compute_vertex_normals()
21 print("Displaying input mesh ...")
22 cv3d.visualization.draw_geometries([mesh_in])
23
24 print("Displaying output of average mesh filter after 1 iteration ...")
25 mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=1)
26 mesh_out.compute_vertex_normals()
27 cv3d.visualization.draw_geometries([mesh_out])
28
29 print("Displaying output of average mesh filter after 5 iteration ...")
30 mesh_out = mesh_in.filter_smooth_simple(number_of_iterations=5)
31 mesh_out.compute_vertex_normals()
32 cv3d.visualization.draw_geometries([mesh_out])
33
34
35def laplace_filtering():
36 # Create noisy mesh.
37 knot_mesh = cv3d.data.KnotMesh()
38 mesh_in = cv3d.io.read_triangle_mesh(knot_mesh.path)
39 vertices = np.asarray(mesh_in.vertices())
40 noise = 5
41 vertices += np.random.uniform(0, noise, size=vertices.shape)
42 mesh_in.set_vertices(cv3d.utility.Vector3dVector(vertices))
43 mesh_in.compute_vertex_normals()
44 print("Displaying input mesh ...")
45 cv3d.visualization.draw_geometries([mesh_in])
46
47 print("Displaying output of Laplace mesh filter after 10 iteration ...")
48 mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=10)
49 mesh_out.compute_vertex_normals()
50 cv3d.visualization.draw_geometries([mesh_out])
51
52 print("Displaying output of Laplace mesh filter after 50 iteration ...")
53 mesh_out = mesh_in.filter_smooth_laplacian(number_of_iterations=50)
54 mesh_out.compute_vertex_normals()
55 cv3d.visualization.draw_geometries([mesh_out])
56
57
58def taubin_filtering():
59 # Create noisy mesh.
60 knot_mesh = cv3d.data.KnotMesh()
61 mesh_in = cv3d.io.read_triangle_mesh(knot_mesh.path)
62 vertices = np.asarray(mesh_in.vertices())
63 noise = 5
64 vertices += np.random.uniform(0, noise, size=vertices.shape)
65 mesh_in.set_vertices(cv3d.utility.Vector3dVector(vertices))
66 mesh_in.compute_vertex_normals()
67 print("Displaying input mesh ...")
68 cv3d.visualization.draw_geometries([mesh_in])
69
70 print("Displaying output of Taubin mesh filter after 10 iteration ...")
71 mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=10)
72 mesh_out.compute_vertex_normals()
73 cv3d.visualization.draw_geometries([mesh_out])
74
75 print("Displaying output of Taubin mesh filter after 100 iteration ...")
76 mesh_out = mesh_in.filter_smooth_taubin(number_of_iterations=100)
77 mesh_out.compute_vertex_normals()
78 cv3d.visualization.draw_geometries([mesh_out])
79
80
81if __name__ == "__main__":
82 average_filtering()
83 laplace_filtering()
84 taubin_filtering()
triangle_mesh_from_point_cloud_alpha_shapes.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9import numpy as np
10
11if __name__ == "__main__":
12 bunny = cv3d.data.BunnyMesh()
13 mesh = cv3d.io.read_triangle_mesh(bunny.path)
14 mesh.compute_vertex_normals()
15
16 pcd = mesh.sample_points_poisson_disk(750)
17 print("Displaying input pointcloud ...")
18 cv3d.visualization.draw_geometries([pcd])
19 alpha = 0.03
20 print(f"alpha={alpha:.3f}")
21 print('Running alpha shapes surface reconstruction ...')
22 mesh = cv3d.geometry.ccMesh.create_from_point_cloud_alpha_shape(pcd, alpha)
23 mesh.compute_triangle_normals(normalized=True)
24 print("Displaying reconstructed mesh ...")
25 cv3d.visualization.draw_geometries([mesh], mesh_show_back_face=True)
26
27 tetra_mesh, pt_map = cv3d.geometry.TetraMesh.create_from_point_cloud(pcd)
28 print("done with tetra mesh")
29 cv3d.visualization.draw_geometries([tetra_mesh])
30 for alpha in np.logspace(np.log10(0.5), np.log10(0.01), num=4):
31 print("alpha={}".format(alpha))
32 mesh = cv3d.geometry.ccMesh.create_from_point_cloud_alpha_shape(
33 pcd, alpha, tetra_mesh, pt_map)
34 mesh.compute_vertex_normals()
35 cv3d.visualization.draw_geometries([mesh], mesh_show_back_face=True)
triangle_mesh_from_point_cloud_ball_pivoting.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9
10if __name__ == "__main__":
11 bunny = cv3d.data.BunnyMesh()
12 gt_mesh = cv3d.io.read_triangle_mesh(bunny.path)
13 gt_mesh.compute_vertex_normals()
14
15 pcd = gt_mesh.sample_points_poisson_disk(3000)
16 print("Displaying input pointcloud ...")
17 cv3d.visualization.draw([pcd], point_size=5)
18
19 radii = [0.005, 0.01, 0.02, 0.04]
20 print('Running ball pivoting surface reconstruction ...')
21 rec_mesh = cv3d.geometry.ccMesh.create_from_point_cloud_ball_pivoting(
22 pcd, cv3d.utility.DoubleVector(radii))
23 print("Displaying reconstructed mesh ...")
24 cv3d.visualization.draw([rec_mesh])
triangle_mesh_from_point_cloud_poisson.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9import numpy as np
10import matplotlib.pyplot as plt
11
12if __name__ == "__main__":
13 eagle = cv3d.data.EaglePointCloud()
14 pcd = cv3d.io.read_point_cloud(eagle.path)
15 R = pcd.get_rotation_matrix_from_xyz((np.pi, -np.pi / 4, 0))
16 pcd.rotate(R, center=(0, 0, 0))
17 print('Displaying input pointcloud ...')
18 cv3d.visualization.draw([pcd])
19
20 print('Running Poisson surface reconstruction ...')
21 mesh, densities = cv3d.geometry.ccMesh.create_from_point_cloud_poisson(
22 pcd, depth=9)
23 print('Displaying reconstructed mesh ...')
24 cv3d.visualization.draw([mesh])
25
26 print('visualize densities')
27 densities = np.asarray(densities)
28 density_colors = plt.get_cmap('plasma')(
29 (densities - densities.min()) / (densities.max() - densities.min()))
30 density_colors = density_colors[:, :3]
31 density_mesh = cv3d.geometry.ccMesh()
32 density_mesh.create_internal_cloud()
33 density_mesh.set_vertices(mesh.get_vertices())
34 density_mesh.set_triangles(mesh.get_triangles())
35 density_mesh.set_vertex_colors(cv3d.utility.Vector3dVector(density_colors))
36 cv3d.visualization.draw_geometries([density_mesh])
37
38 print('remove low density vertices')
39 vertices_to_remove = densities < np.quantile(densities, 0.1)
40 mesh.remove_vertices_by_mask(vertices_to_remove)
41 print(mesh)
42 cv3d.visualization.draw_geometries([mesh])
triangle_mesh_half_edge.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import numpy as np
9import cloudViewer as cv3d
10
11if __name__ == "__main__":
12 # Initialize a HalfEdgeTriangleMesh from TriangleMesh
13 mesh = cv3d.geometry.ccMesh.create_sphere()
14 bbox = cv3d.geometry.ccBBox()
15 bbox.set_min_bound([-1, -1, -1])
16 bbox.set_max_bound([1, 0.6, 1])
17 bbox.set_validity(True)
18 mesh = mesh.crop(bbox)
19 het_mesh = cv3d.geometry.HalfEdgeTriangleMesh.create_from_triangle_mesh(
20 mesh)
21 cv3d.visualization.draw_geometries([het_mesh], mesh_show_back_face=True)
22
23 # Colorize boundary vertices to red
24 vertex_colors = 0.75 * np.ones((len(het_mesh.vertices), 3))
25 for boundary in het_mesh.get_boundaries():
26 for vertex_id in boundary:
27 vertex_colors[vertex_id] = [1, 0, 0]
28 het_mesh.vertex_colors = cv3d.utility.Vector3dVector(vertex_colors)
29 cv3d.visualization.draw_geometries([het_mesh], mesh_show_back_face=True)
triangle_mesh_project_to_albedo.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7"""This example demonstrates project_image_to_albedo. Use create_dataset mode to
8render images of a 3D mesh or model from different viewpoints.
9albedo_from_dataset mode then uses the calibrated images to re-create the albedo
10texture for the mesh.
11"""
12import os
13import argparse
14from pathlib import Path
15import subprocess as sp
16import time
17import numpy as np
18import cloudViewer as cv3d
19from cloudViewer.visualization import gui, rendering, O3DVisualizer
20from cloudViewer.core import Tensor
21
22
23def create_dataset(meshfile, n_images=10, movie=False, vary_exposure=False):
24 """Render images of a 3D mesh from different viewpoints, covering the
25 northern hemisphere. These form a synthetic dataset to test the
26 project_images_to_albedo function.
27 """
28 # Adjust these parameters to properly frame your model.
29 # Window system pixel scaling (e.g. 1 for normal, 2 for HiDPI / retina display)
30 SCALING = 2
31 width, height = 1024, 1024 # image width, height
32 focal_length = 512
33 d_camera_obj = 0.3 # distance from camera to object
34 K = np.array([[focal_length, 0, width / 2], [0, focal_length, height / 2],
35 [0, 0, 1]])
36 t = np.array([0, 0, d_camera_obj]) # origin / object in camera ref frame
37
38 model = cv3d.io.read_triangle_model(meshfile)
39 # DefaultLit shader will produce non-uniform images with specular
40 # highlights, etc. These should be avoided to accurately capture the diffuse
41 # albedo
42 unlit = rendering.MaterialRecord()
43 unlit.shader = "unlit"
44
45 def triangle_wave(n, period=1):
46 """Triangle wave function between [0,1] with given period."""
47 return abs(n % period - period / 2) / (period / 2)
48
49 def rotate_camera_and_shoot(cv3dvis):
50 Rts = []
51 images = []
52 cv3dvis.scene.scene.enable_sun_light(False)
53 print("Rendering images: ", end='', flush=True)
54 n_0 = 2 * n_images // 3
55 n_1 = n_images - n_0 - 1
56 for n in range(n_images):
57 Rt = np.eye(4)
58 Rt[:3, 3] = t
59 if n < n_0:
60 theta = n * (2 * np.pi) / n_0
61 Rt[:3, :
62 3] = cv3d.geometry.ccHObject.get_rotation_matrix_from_zyx(
63 [np.pi, theta, 0])
64 elif n < n_images - 1:
65 theta = (n - n_0) * (2 * np.pi) / n_1
66 Rt[:3, :
67 3] = cv3d.geometry.ccHObject.get_rotation_matrix_from_xyz(
68 [np.pi / 4, theta, np.pi])
69 else: # one image from the top
70 Rt[:3, :
71 3] = cv3d.geometry.ccHObject.get_rotation_matrix_from_zyx(
72 [np.pi, 0, -np.pi / 2])
73 Rts.append(Rt)
74 cv3dvis.setup_camera(K, Rt, width, height)
75 # Vary IBL intensity as a poxy for exposure value. IBL ranges from
76 # [0,150000]. We vary it between 20000 and 100000.
77 if vary_exposure:
78 cv3dvis.set_ibl_intensity(20000 + 80000 *
79 triangle_wave(n, n_images / 4))
80 cv3dvis.post_redraw()
81 cv3dvis.export_current_image(f"render-{n:02}.jpg")
82 images.append(f"render-{n:02}.jpg")
83 print('.', end='', flush=True)
84 np.savez("cameras.npz",
85 width=width,
86 height=height,
87 K=K,
88 Rts=Rts,
89 images=images)
90 # Now create a movie from the saved images by calling ffmpeg with
91 # subprocess
92 if movie:
93 print("\nCreating movie...", end='', flush=True)
94 sp.run([
95 "ffmpeg", "-framerate", f"{n_images / 6}", "-pattern_type",
96 "glob", "-i", "render-*.jpg", "-y", meshfile.stem + ".mp4"
97 ],
98 check=True)
99 cv3dvis.close()
100 print("\nDone.")
101
102 print("If the object is properly framed in the GUI window, click on the "
103 "'Save Images' action in the menu.")
104 cv3d.visualization.draw([{
105 'geometry': model,
106 'name': meshfile.name,
107 'material': unlit
108 }],
109 show_ui=False,
110 width=int(width / SCALING),
111 height=int(height / SCALING),
112 actions=[("Save Images", rotate_camera_and_shoot)])
113
114
115def albedo_from_images(meshfile, calib_data_file, albedo_contrast=1.25):
116 model = cv3d.io.read_triangle_model(meshfile)
117 tmeshes = cv3d.t.geometry.TriangleMesh.from_triangle_mesh_model(model)
118 tmeshes = list(tmeshes.values())
119 calib = np.load(calib_data_file)
120 Ks = list(Tensor(calib["K"]) for _ in range(len(calib["Rts"])))
121 Rts = list(Tensor(Rt) for Rt in calib["Rts"])
122 images = list(cv3d.t.io.read_image(imfile) for imfile in calib["images"])
123 calib.close()
124 start = time.time()
125 with cv3d.utility.VerbosityContextManager(
126 cv3d.utility.VerbosityLevel.Debug):
127 albedo = tmeshes[0].project_images_to_albedo(images, Ks, Rts, 1024,
128 True)
129 albedo = albedo.linear_transform(scale=albedo_contrast) # brighten albedo
130 tmeshes[0].material.texture_maps["albedo"] = albedo
131 print(f"project_images_to_albedo ran in {time.time() - start:.2f}s")
132 cv3d.t.io.write_image("albedo.png", albedo)
133 cv3d.t.io.write_triangle_mesh(meshfile.stem + "_albedo.glb", tmeshes[0])
134 cam_vis = list({
135 "name":
136 f"camera-{i:02}",
137 "geometry":
138 cv3d.geometry.LineSet.create_camera_visualization(
139 images[0].columns, images[0].rows, K.numpy(), Rt.numpy(), 0.1)
140 } for i, (K, Rt) in enumerate(zip(Ks, Rts)))
141 cv3d.visualization.draw(cam_vis + [{
142 "name": meshfile.name,
143 "geometry": tmeshes[0]
144 }],
145 show_ui=True)
146
147
148if __name__ == "__main__":
149
150 parser = argparse.ArgumentParser(description=__doc__)
151 parser.add_argument("action",
152 choices=('create_dataset', 'albedo_from_images'))
153 parser.add_argument("--meshfile",
154 type=Path,
155 default=Path("."),
156 help="Path to mesh file.")
157 parser.add_argument("--n-images",
158 type=int,
159 default=10,
160 help="Number of images to render.")
161 parser.add_argument("--download_sample_model",
162 help="Download a sample 3D model for this example.",
163 action="store_true")
164 parser.add_argument(
165 "--movie",
166 action="store_true",
167 help=
168 "Create movie from rendered images with ffmpeg. ffmpeg must be installed and in path."
169 )
170 args = parser.parse_args()
171
172 if args.action == "create_dataset":
173 if args.download_sample_model:
174 cv3d.data.set_custom_downloads_prefix(
175 "https://github.com/Asher-1/cloudViewer_downloads/releases/download/"
176 )
177 args.meshfile = Path(cv3d.data.BalusterVase().path)
178 if args.meshfile == Path("."):
179 parser.error("Please provide a path to a mesh file, or use "
180 "--download_sample_model.")
181 if args.n_images < 10:
182 parser.error("Atleast 10 images should be used!")
183 create_dataset(args.meshfile,
184 n_images=args.n_images,
185 movie=args.movie,
186 vary_exposure=True)
187 else:
188 cv3d.data.set_custom_downloads_prefix(
189 "https://github.com/Asher-1/cloudViewer_downloads/releases/download/"
190 )
191 args.meshfile = Path(cv3d.data.BalusterVase().path)
192 albedo_from_images(args.meshfile, "cameras.npz")
triangle_mesh_properties.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9import numpy as np
10import os
11import sys
12
13pyexample_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
14sys.path.append(pyexample_path)
15
16import cloudViewer_example as cv3dex
17
18
19def check_properties(name, mesh):
20 mesh.compute_vertex_normals()
21
22 edge_manifold = mesh.is_edge_manifold(allow_boundary_edges=True)
23 edge_manifold_boundary = mesh.is_edge_manifold(allow_boundary_edges=False)
24 vertex_manifold = mesh.is_vertex_manifold()
25 self_intersecting = mesh.is_self_intersecting()
26 watertight = mesh.is_watertight()
27 orientable = mesh.is_orientable()
28
29 print(name)
30 print(f" edge_manifold: {edge_manifold}")
31 print(f" edge_manifold_boundary: {edge_manifold_boundary}")
32 print(f" vertex_manifold: {vertex_manifold}")
33 print(f" self_intersecting: {self_intersecting}")
34 print(f" watertight: {watertight}")
35 print(f" orientable: {orientable}")
36
37 geoms = [mesh]
38 if not edge_manifold:
39 edges = mesh.get_non_manifold_edges(allow_boundary_edges=True)
40 geoms.append(cv3dex.edges_to_lineset(mesh, edges, (1, 0, 0)))
41 if not edge_manifold_boundary:
42 edges = mesh.get_non_manifold_edges(allow_boundary_edges=False)
43 geoms.append(cv3dex.edges_to_lineset(mesh, edges, (0, 1, 0)))
44 if not vertex_manifold:
45 verts = np.asarray(mesh.get_non_manifold_vertices())
46 pcl = cv3d.geometry.ccPointCloud(points=cv3d.utility.Vector3dVector(
47 np.asarray(mesh.get_vertices())[verts]))
48 pcl.paint_uniform_color((0, 0, 1))
49 geoms.append(pcl)
50 if self_intersecting:
51 intersecting_triangles = np.asarray(
52 mesh.get_self_intersecting_triangles())
53 intersecting_triangles = intersecting_triangles[0:1]
54 intersecting_triangles = np.unique(intersecting_triangles)
55 print(" # visualize self-intersecting triangles")
56 triangles = np.asarray(mesh.get_triangles())[intersecting_triangles]
57 edges = [
58 np.vstack((triangles[:, i], triangles[:, j]))
59 for i, j in [(0, 1), (1, 2), (2, 0)]
60 ]
61 edges = np.hstack(edges).T
62 edges = cv3d.utility.Vector2iVector(edges)
63 geoms.append(cv3dex.edges_to_lineset(mesh, edges, (1, 0, 1)))
64 cv3d.visualization.draw_geometries(geoms, mesh_show_back_face=True)
65
66
67if __name__ == "__main__":
68 knot_mesh = cv3d.data.KnotMesh()
69 mesh = cv3d.io.read_triangle_mesh(knot_mesh.path)
70 check_properties('KnotMesh', mesh)
71 check_properties('Mobius', cv3d.geometry.ccMesh.create_mobius(twists=1))
72 check_properties("non-manifold edge", cv3dex.get_non_manifold_edge_mesh())
73 check_properties("non-manifold vertex",
74 cv3dex.get_non_manifold_vertex_mesh())
75 check_properties("open box", cv3dex.get_open_box_mesh())
76 check_properties("intersecting_boxes", cv3dex.get_intersecting_boxes_mesh())
triangle_mesh_sampling.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import numpy as np
9import time
10import cloudViewer as cv3d
11
12
13def time_fcn(fcn, *fcn_args, runs=5):
14 times = []
15 for _ in range(runs):
16 tic = time.time()
17 res = fcn(*fcn_args)
18 times.append(time.time() - tic)
19 return res, times
20
21
22def mesh_generator():
23 yield cv3d.geometry.ccMesh.create_plane()
24 yield cv3d.geometry.ccMesh.create_sphere()
25
26 bunny = cv3d.data.BunnyMesh()
27 mesh = cv3d.io.read_triangle_mesh(bunny.path)
28 mesh.compute_vertex_normals()
29 yield mesh
30
31
32if __name__ == "__main__":
33 plane = cv3d.geometry.ccMesh.create_plane()
34 cv3d.visualization.draw_geometries([plane], mesh_show_back_face=True)
35
36 print('Uniform sampling can yield clusters of points on the surface')
37 pcd = plane.sample_points_uniformly(number_of_points=500)
38 cv3d.visualization.draw_geometries([pcd])
39
40 print(
41 'Poisson disk sampling can evenly distributes the points on the surface.'
42 )
43 print('The method implements sample elimination.')
44 print('Therefore, the method starts with a sampled point cloud and removes '
45 'point to satisfy the sampling criterion.')
46 print('The method supports two options to provide the initial point cloud')
47 print('1) Default via the parameter init_factor: The method first samples '
48 'uniformly a point cloud from the mesh with '
49 'init_factor x number_of_points and uses this for the elimination')
50 pcd = plane.sample_points_poisson_disk(number_of_points=500, init_factor=5)
51 cv3d.visualization.draw_geometries([pcd])
52
53 print(
54 '2) one can provide an own point cloud and pass it to the '
55 'cv3d.geometry.sample_points_poisson_disk method. Then this point cloud is used '
56 'for elimination.')
57 print('Initial point cloud')
58 pcd = plane.sample_points_uniformly(number_of_points=2500)
59 cv3d.visualization.draw_geometries([pcd])
60 pcd = plane.sample_points_poisson_disk(number_of_points=500, pcl=pcd)
61 cv3d.visualization.draw_geometries([pcd])
62
63 print('Timings')
64 for mesh in mesh_generator():
65 mesh.compute_vertex_normals()
66 cv3d.visualization.draw_geometries([mesh])
67
68 pcd, times = time_fcn(mesh.sample_points_uniformly, 500)
69 print('sample uniform took on average: %f[s]' % np.mean(times))
70 cv3d.visualization.draw_geometries([pcd])
71
72 pcd, times = time_fcn(mesh.sample_points_poisson_disk, 500, 5)
73 print('sample poisson disk took on average: %f[s]' % np.mean(times))
74 cv3d.visualization.draw_geometries([pcd])
triangle_mesh_simplification_decimation.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9
10if __name__ == "__main__":
11 bunny = cv3d.data.BunnyMesh()
12 mesh_in = cv3d.io.read_triangle_mesh(bunny.path)
13 mesh_in.compute_vertex_normals()
14
15 print("Before Simplification: ", mesh_in)
16 cv3d.visualization.draw_geometries([mesh_in])
17
18 mesh_smp = mesh_in.simplify_quadric_decimation(
19 target_number_of_triangles=6500)
20 print("After Simplification target number of triangles = 6500:\n", mesh_smp)
21 cv3d.visualization.draw_geometries([mesh_smp])
22
23 mesh_smp = mesh_in.simplify_quadric_decimation(
24 target_number_of_triangles=1700)
25 print("After Simplification target number of triangles = 1700:\n", mesh_smp)
26 cv3d.visualization.draw_geometries([mesh_smp])
triangle_mesh_simplification_vertex_clustering.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9
10if __name__ == "__main__":
11 bunny = cv3d.data.BunnyMesh()
12 mesh_in = cv3d.io.read_triangle_mesh(bunny.path)
13 mesh_in.compute_vertex_normals()
14
15 print("Before Simplification: ", mesh_in)
16 cv3d.visualization.draw_geometries([mesh_in])
17
18 voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 32
19 mesh_smp = mesh_in.simplify_vertex_clustering(
20 voxel_size=voxel_size,
21 contraction=cv3d.geometry.SimplificationContraction.Average)
22 print("After Simplification with voxel size =", voxel_size, ":\n", mesh_smp)
23 cv3d.visualization.draw_geometries([mesh_smp])
24
25 voxel_size = max(mesh_in.get_max_bound() - mesh_in.get_min_bound()) / 16
26 mesh_smp = mesh_in.simplify_vertex_clustering(
27 voxel_size=voxel_size,
28 contraction=cv3d.geometry.SimplificationContraction.Average)
29 print("After Simplification with voxel size =", voxel_size, ":\n", mesh_smp)
30 cv3d.visualization.draw_geometries([mesh_smp])
triangle_mesh_subdivision.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8# examples/Python/Basic/mesh_subdivision.py
9
10import numpy as np
11import cloudViewer as cv3d
12
13
14def mesh_generator():
15 knot_mesh = cv3d.data.KnotMesh()
16 yield cv3d.io.read_triangle_mesh(knot_mesh.path)
17 yield cv3d.geometry.ccMesh.create_plane()
18 yield cv3d.geometry.ccMesh.create_tetrahedron()
19 yield cv3d.geometry.ccMesh.create_box()
20 yield cv3d.geometry.ccMesh.create_octahedron()
21 yield cv3d.geometry.ccMesh.create_icosahedron()
22 yield cv3d.geometry.ccMesh.create_sphere()
23 yield cv3d.geometry.ccMesh.create_cone()
24 yield cv3d.geometry.ccMesh.create_cylinder()
25
26
27if __name__ == "__main__":
28 np.random.seed(42)
29
30 number_of_iterations = 3
31
32 for mesh in mesh_generator():
33 mesh.compute_vertex_normals()
34 print("original mesh has %d triangles and %d vertices" %
35 (np.asarray(mesh.get_triangles()).shape[0],
36 np.asarray(mesh.get_vertices()).shape[0]))
37 cv3d.visualization.draw_geometries([mesh], mesh_show_wireframe=True)
38
39 mesh_up = mesh.subdivide_midpoint(
40 number_of_iterations=number_of_iterations)
41 print("midpoint upsampled mesh has %d triangles and %d vertices" %
42 (np.asarray(mesh_up.get_triangles()).shape[0],
43 np.asarray(mesh_up.get_vertices()).shape[0]))
44 cv3d.visualization.draw_geometries([mesh_up], mesh_show_wireframe=True)
45
46 mesh_up = mesh.subdivide_loop(number_of_iterations=number_of_iterations)
47 print("loop upsampled mesh has %d triangles and %d vertices" %
48 (np.asarray(mesh_up.get_triangles()).shape[0],
49 np.asarray(mesh_up.get_vertices()).shape[0]))
50 cv3d.visualization.draw_geometries([mesh_up], mesh_show_wireframe=True)
triangle_mesh_transformation.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9import numpy as np
10import copy
11
12
13def translate():
14 mesh = cv3d.geometry.ccMesh.create_coordinate_frame()
15 mesh_tx = copy.deepcopy(mesh).translate((1.3, 0, 0))
16 mesh_ty = copy.deepcopy(mesh).translate((0, 1.3, 0))
17 print('Displaying original and translated geometries ...')
18 cv3d.visualization.draw([{
19 "name": "Original Geometry",
20 "geometry": mesh
21 }, {
22 "name": "Translated (in X) Geometry",
23 "geometry": mesh_tx
24 }, {
25 "name": "Translated (in Y) Geometry",
26 "geometry": mesh_ty
27 }],
28 show_ui=True)
29
30
31def rotate():
32 mesh = cv3d.geometry.ccMesh.create_coordinate_frame()
33 mesh_r = copy.deepcopy(mesh)
34 R = mesh.get_rotation_matrix_from_xyz((np.pi / 2, 0, np.pi / 4))
35 mesh_r.rotate(R, center=(0, 0, 0))
36 print('Displaying original and rotated geometries ...')
37 cv3d.visualization.draw([{
38 "name": "Original Geometry",
39 "geometry": mesh
40 }, {
41 "name": "Rotated Geometry",
42 "geometry": mesh_r
43 }],
44 show_ui=True)
45
46
47def scale():
48 mesh = cv3d.geometry.ccMesh.create_coordinate_frame()
49 mesh_s = copy.deepcopy(mesh).translate((2, 0, 0))
50 mesh_s.scale(0.5, center=mesh_s.get_center())
51 print('Displaying original and scaled geometries ...')
52 cv3d.visualization.draw([{
53 "name": "Original Geometry",
54 "geometry": mesh
55 }, {
56 "name": "Scaled Geometry",
57 "geometry": mesh_s
58 }],
59 show_ui=True)
60
61
62def transform():
63 mesh = cv3d.geometry.ccMesh.create_coordinate_frame()
64 T = np.eye(4)
65 T[:3, :3] = mesh.get_rotation_matrix_from_xyz((0, np.pi / 3, np.pi / 2))
66 T[0, 3] = 1
67 T[1, 3] = 1.3
68 print(T)
69 mesh_t = copy.deepcopy(mesh).transform(T)
70 print('Displaying original and transformed geometries ...')
71 cv3d.visualization.draw([{
72 "name": "Original Geometry",
73 "geometry": mesh
74 }, {
75 "name": "Transformed Geometry",
76 "geometry": mesh_t
77 }],
78 show_ui=True)
79
80
81if __name__ == "__main__":
82 translate()
83 rotate()
84 scale()
85 transform()
triangle_mesh_voxelization.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import time
9import cloudViewer as cv3d
10import numpy as np
11
12
13def preprocess(model):
14 """Normalize model to fit in unit sphere (sphere with unit radius).
15
16 Calculate center & scale of vertices, and transform vertices to have 0 mean and unit variance.
17
18 Returns:
19 cloudViewer.geometry.ccMesh: normalized mesh
20 """
21 min_bound = model.get_min_bound()
22 max_bound = model.get_max_bound()
23 center = min_bound + (max_bound - min_bound) / 2.0
24 scale = np.linalg.norm(max_bound - min_bound) / 2.0
25 vertices = np.asarray(model.get_vertices())
26 vertices -= center
27 model.set_vertices(cv3d.utility.Vector3dVector(vertices / scale))
28
29 ## Paint uniform color for pleasing visualization
30 model.paint_uniform_color(np.array([1, 0.7, 0]))
31 return model
32
33
34def mesh_generator():
35 bunny = cv3d.data.BunnyMesh()
36 mesh_bunny = cv3d.io.read_triangle_mesh(bunny.path)
37 mesh_bunny.compute_vertex_normals()
38 yield mesh_bunny
39
40 armadillo = cv3d.data.ArmadilloMesh()
41 mesh_armadillo = cv3d.io.read_triangle_mesh(armadillo.path)
42 mesh_armadillo.compute_vertex_normals()
43 yield mesh_armadillo
44
45
46if __name__ == "__main__":
47 print("Start mesh_sampling_and_voxelization example")
48 for mesh in mesh_generator():
49 print("Normalize mesh")
50 mesh = preprocess(mesh)
51 cv3d.visualization.draw_geometries([mesh])
52 print("")
53
54 print("Sample uniform points")
55 start = time.time()
56 pcd = mesh.sample_points_uniformly(number_of_points=100000)
57 print("took %.2f milliseconds" % ((time.time() - start) * 1000.0))
58 print("")
59
60 print("visualize sampled point cloud")
61 cv3d.visualization.draw_geometries([pcd])
62 print("")
63
64 print("Voxelize point cloud")
65 start = time.time()
66 voxel = cv3d.geometry.VoxelGrid.create_from_point_cloud(pcd,
67 voxel_size=0.05)
68 print("took %.2f milliseconds" % ((time.time() - start) * 1000.0))
69 print("")
70
71 print("visualize voxel grid")
72 cv3d.visualization.draw_geometries([voxel])
73 print("")
74
75 print("Element-wise check if points belong to voxel grid")
76 queries = np.asarray(pcd.get_points())
77 start = time.time()
78 output = voxel.check_if_included(cv3d.utility.Vector3dVector(queries))
79 print("took %.2f milliseconds" % ((time.time() - start) * 1000.0))
80 print(output[:10])
81 print("")
82
83 print(
84 "Element-wise check if points with additive Gaussian noise belong to voxel grid"
85 )
86 queries_noise = queries + np.random.normal(0, 0.1,
87 (len(pcd.get_points()), 3))
88 start = time.time()
89 output_noise = voxel.check_if_included(
90 cv3d.utility.Vector3dVector(queries_noise))
91 print(output_noise[:10])
92 print("took %.2f milliseconds" % ((time.time() - start) * 1000.0))
93 print("")
94
95 print("Transform voxelgrid to octree")
96 start = time.time()
97 octree = voxel.to_octree(max_depth=8)
98 print(octree)
99 print("took %.2f milliseconds" % ((time.time() - start) * 1000.0))
100 cv3d.visualization.draw_geometries([octree])
101 print("")
triangle_mesh_with_numpy.py#
1# ----------------------------------------------------------------------------
2# - CloudViewer: www.cloudViewer.org -
3# ----------------------------------------------------------------------------
4# Copyright (c) 2018-2024 www.cloudViewer.org
5# SPDX-License-Identifier: MIT
6# ----------------------------------------------------------------------------
7
8import cloudViewer as cv3d
9import numpy as np
10
11if __name__ == "__main__":
12 # Read a mesh and get its data as numpy arrays.
13 knot_mesh = cv3d.data.KnotMesh()
14 mesh = cv3d.io.read_triangle_mesh(knot_mesh.path)
15 mesh.compute_vertex_normals()
16 mesh.paint_uniform_color([0.5, 0.1, 0.3])
17 print('Vertices:')
18 print(np.asarray(mesh.vertices()))
19 print('Vertex Colors:')
20 print(np.asarray(mesh.vertex_colors()))
21 print('Vertex Normals:')
22 print(np.asarray(mesh.vertex_normals()))
23 print('Triangles:')
24 print(np.asarray(mesh.triangles()))
25 print('Triangle Normals:')
26 print(np.asarray(mesh.triangle_normals()))
27 print("Displaying mesh ...")
28 print(mesh)
29 cv3d.visualization.draw([mesh])
30
31 # Create a mesh using numpy arrays with random colors.
32 N = 5
33 vertices = cv3d.utility.Vector3dVector(
34 np.array([[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1], [0.5, 0.5, 0.5]]))
35 triangles = cv3d.utility.Vector3iVector(
36 np.array([[0, 1, 2], [0, 2, 3], [0, 4, 1], [1, 4, 2], [2, 4, 3],
37 [3, 4, 0]]))
38 mesh_np = cv3d.geometry.ccMesh(vertices, triangles)
39 mesh_np.set_vertex_colors(
40 cv3d.utility.Vector3dVector(np.random.uniform(0, 1, size=(N, 3))))
41 mesh_np.compute_vertex_normals()
42 print(np.asarray(mesh_np.triangle_normals))
43 print("Displaying mesh made using numpy ...")
44 cv3d.visualization.draw_geometries([mesh_np], mesh_show_wireframe=True)