diff --git a/python/tutorials/tutorial_301_normal_estimtion.py b/python/tutorials/tutorial_301_normal_estimtion.py index b5c28b5d..9ab04954 100644 --- a/python/tutorials/tutorial_301_normal_estimtion.py +++ b/python/tutorials/tutorial_301_normal_estimtion.py @@ -36,40 +36,51 @@ print(f"Input file name: {file_name}") # Load the point cloud from the specified file. -pc = easy3d.PointCloudIO.load(file_name) +point_cloud = easy3d.PointCloudIO.load(file_name) # ------------------------------------------------------------------------------- # Estimating Point Cloud Normals # ------------------------------------------------------------------------------- -# Estimate normals for the point cloud. The `16` parameter specifies the -# number of neighbors to use for normal estimation. -easy3d.PointCloudNormals.estimate(pc, 16) +# Since we want to visualize both input and resulted point clouds, let's make a +# copy of the input point cloud. The algorithm will be applied to the copy one. +copied_point_cloud = easy3d.PointCloud(point_cloud) # Create a copy +easy3d.PointCloudNormals.estimate(copied_point_cloud, 16) # Reorient the normals to ensure consistency. -easy3d.PointCloudNormals.reorient(pc, 16) +easy3d.PointCloudNormals.reorient(copied_point_cloud, 16) # ------------------------------------------------------------------------------- # Saving the Processed Point Cloud # ------------------------------------------------------------------------------- # Save the point cloud with estimated normals to a new file in .ply format. output_file = file_name + "-result.ply" -easy3d.PointCloudIO.save(output_file, pc) +easy3d.PointCloudIO.save(output_file, copied_point_cloud) print(f"Processed point cloud saved to: {output_file}") # ------------------------------------------------------------------------------- -# Visualizing the Point Cloud +# Visualizing the input and the resulted point clouds side-by-side # ------------------------------------------------------------------------------- -# Create a viewer instance to visualize the point cloud. -viewer = easy3d.Viewer("Easy3D Viewer - Normal estimation") -# Set to an empty to get rid of the lengthy usage instructions -viewer.set_usage("") -# Add the point cloud model to the viewer and run the viewer to interact with the model. -viewer.add_model(pc) +# Create a MultiViewer instance with 1 row and 2 columns. +viewer = easy3d.MultiViewer(1, 2, "Easy3D Viewer - Normal estimation") -# Set the camera view direction and up vector for a better view position. +# Add the input point cloud to the viewer and assign it to the left view (row=0, column=0). +viewer.add_model(point_cloud) +viewer.assign(0, 0, point_cloud) + +# Add the resulted point cloud to the viewer and assign it to the right view (row=0, column=1). +viewer.add_model(copied_point_cloud) +viewer.assign(0, 1, copied_point_cloud) + +# Add instructions for the viewer (optional). +viewer.set_usage( + "- Left: Original point cloud.\n" + "- Right: Resulted point cloud with normal information." +) + +# # Set the camera view direction and up vector for a better view position. viewer.camera().setViewDirection(easy3d.vec3(0, 0, -1)) # Set the view direction. viewer.camera().setUpVector(easy3d.vec3(0, 1, 0)) # Set the up vector. -# Running the Viewer -viewer.run() +# Launch the viewer. +viewer.run() \ No newline at end of file diff --git a/python/tutorials/tutorial_303_plane_extraction.py b/python/tutorials/tutorial_303_plane_extraction.py index 7b2efe5f..481b2bb7 100644 --- a/python/tutorials/tutorial_303_plane_extraction.py +++ b/python/tutorials/tutorial_303_plane_extraction.py @@ -110,7 +110,10 @@ print(f" Index: {plane.primitive_index}") print(f" Position: {plane.position}") print(f" Normal: {plane.normal}") - print(f" Vertices: {plane.vertices}") # e.g., [5788, 5801, 5777, 5796, ... ] + + # Print up to 20 vertex indices (for demonstration purposes) + vertex_count = len(plane.vertices) + print(f" Vertices ({min(vertex_count, 20)} out of {vertex_count} shown): {plane.vertices[:20]}") # e.g., [5788, 5801, 5777, 5796, ... ] # ----------------------------------------------------------------------------- # Optional: Detecting Cylinders @@ -128,3 +131,6 @@ # print(f" Position: {cylinder.position}") # print(f" Direction: {cylinder.direction}") # print(f" Radius: {cylinder.radius}") +# # Print up to 20 vertex indices (for demonstration purposes) +# vertex_count = len(cylinder.vertices) +# print(f" Vertices ({min(vertex_count, 20)} out of {vertex_count} shown): {cylinder.vertices[:20]}") # e.g., [5788, 5801, 5777, 5796, ... ] \ No newline at end of file diff --git a/python/tutorials/tutorial_304_point_cloud_downsampling.py b/python/tutorials/tutorial_304_point_cloud_downsampling.py index 9c100e17..23eb2fe3 100644 --- a/python/tutorials/tutorial_304_point_cloud_downsampling.py +++ b/python/tutorials/tutorial_304_point_cloud_downsampling.py @@ -9,6 +9,8 @@ # 1. Load a point cloud from a file. # 2. Apply different downsampling techniques, including grid and uniform # simplifications, and measure their effects on the point cloud size. +# 3. Visualize the original point cloud and the sampled point cloud side-by-side +# using Easy3D's `MultiViewer`. # ----------------------------------------------------------------------------- # If you built Easy3D locally, you'll need to add its Python bindings to the @@ -30,8 +32,8 @@ # Easy3D supports various file formats for point clouds (e.g., .bin, .xyz). # Here, we load a sample file provided by Easy3D. Replace the path with your # own file if needed. -pointcloud_file = easy3d.directory() + "/data/polyhedron.bin" # Update as needed -point_cloud = easy3d.PointCloudIO.load(pointcloud_file) # Load the point cloud +file = easy3d.directory() + "/data/polyhedron.bin" # Update as needed +point_cloud = easy3d.PointCloudIO.load(file) # Load the point cloud print(f"Loaded point cloud with {point_cloud.n_vertices()} points.") # Print the initial point count # ----------------------------------------------------------------------------- @@ -57,7 +59,7 @@ print(f"Uniform simplification (distance threshold): {len(uniform_indices_by_epsilon)} points will be removed.") # Option 2: Specify the desired number of points in the final point cloud (`num`). -target_point_count = 50000 +target_point_count = 10000 uniform_indices_by_number = easy3d.PointCloudSimplification.uniform_simplification(point_cloud, num=target_point_count) print(f"Uniform simplification (target point count): {len(uniform_indices_by_number)} points will be removed.") @@ -66,10 +68,36 @@ # ----------------------------------------------------------------------------- # The indices returned by simplification methods indicate the points to be removed. # We use `delete_points()` to apply the simplifications to the point cloud. -point_cloud.delete_points(uniform_indices_by_number) -print(f"Final point cloud size after simplification: {point_cloud.n_vertices()} points.") +# Since we want to visualize both the input and the downsampled point clouds, let's +# make a copy of the original point cloud. +copied_point_cloud = easy3d.PointCloud(point_cloud) # Create a copy for simplification. +copied_point_cloud.delete_points(uniform_indices_by_number) +print(f"Final point cloud size after simplification: {copied_point_cloud.n_vertices()} points.") -# Optional: Save the result to a file if needed (or visualize using the Easy3D viewer). +# Optional: Save the result to a file if needed # output_file = "downsampled_point_cloud.ply" # Specify the output file name -# easy3d.PointCloudIO.save(output_file, point_cloud) -# print(f"Downsampled point cloud saved to {output_file}") \ No newline at end of file +# easy3d.PointCloudIO.save(output_file, copied_point_cloud) +# print(f"Downsampled point cloud saved to {output_file}") + +# ----------------------------------------------------------------------------- +# Visualize the input and downsampled point cloud side-by-side +# ----------------------------------------------------------------------------- +# Create a MultiViewer instance with 1 row and 2 columns. +viewer = easy3d.MultiViewer(1, 2, "Easy3D Viewer - Point Cloud Downsampling") + +# Add the input to the viewer and assign it to the left view (row=0, column=0). +mesh = viewer.add_model(point_cloud) +viewer.assign(0, 0, mesh) + +# Add the downsampled one to the viewer and assign it to the right view (row=0, column=1). +viewer.add_model(copied_point_cloud) +viewer.assign(0, 1, copied_point_cloud) + +# Add instructions for the viewer (optional). +viewer.set_usage( + "- Left: Original point cloud.\n" + "- Right: Downsampled point cloud." +) + +# Launch the viewer. +viewer.run() \ No newline at end of file