File size: 2,252 Bytes
a5407e7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
from typing import Optional, Tuple
import matplotlib.pyplot as plt
import numpy as np
from .point_cloud import PointCloud
def plot_point_cloud(
pc: PointCloud,
color: bool = True,
grid_size: int = 1,
fixed_bounds: Optional[Tuple[Tuple[float, float, float], Tuple[float, float, float]]] = (
(-0.75, -0.75, -0.75),
(0.75, 0.75, 0.75),
),
):
"""
Render a point cloud as a plot to the given image path.
:param pc: the PointCloud to plot.
:param image_path: the path to save the image, with a file extension.
:param color: if True, show the RGB colors from the point cloud.
:param grid_size: the number of random rotations to render.
"""
fig = plt.figure(figsize=(8, 8))
for i in range(grid_size):
for j in range(grid_size):
ax = fig.add_subplot(grid_size, grid_size, 1 + j + i * grid_size, projection="3d")
color_args = {}
if color:
color_args["c"] = np.stack(
[pc.channels["R"], pc.channels["G"], pc.channels["B"]], axis=-1
)
c = pc.coords
if grid_size > 1:
theta = np.pi * 2 * (i * grid_size + j) / (grid_size**2)
rotation = np.array(
[
[np.cos(theta), -np.sin(theta), 0.0],
[np.sin(theta), np.cos(theta), 0.0],
[0.0, 0.0, 1.0],
]
)
c = c @ rotation
ax.scatter(c[:, 0], c[:, 1], c[:, 2], **color_args)
if fixed_bounds is None:
min_point = c.min(0)
max_point = c.max(0)
size = (max_point - min_point).max() / 2
center = (min_point + max_point) / 2
ax.set_xlim3d(center[0] - size, center[0] + size)
ax.set_ylim3d(center[1] - size, center[1] + size)
ax.set_zlim3d(center[2] - size, center[2] + size)
else:
ax.set_xlim3d(fixed_bounds[0][0], fixed_bounds[1][0])
ax.set_ylim3d(fixed_bounds[0][1], fixed_bounds[1][1])
ax.set_zlim3d(fixed_bounds[0][2], fixed_bounds[1][2])
return fig
|