File size: 1,553 Bytes
4db294e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""PLY export for colored point clouds."""
from __future__ import annotations

import numpy as np


def save_ply(path: str, points: np.ndarray, colors: np.ndarray | None = None):
    """Write a colored point cloud to a binary PLY file.

    Args:
        path: output ``.ply`` path.
        points: (N, 3) float coordinates.
        colors: optional (N, 3) uint8 RGB (or float in [0,1]).
    """
    points = np.asarray(points, dtype=np.float32)
    finite = np.isfinite(points).all(axis=1)
    points = points[finite]
    n = points.shape[0]

    if colors is not None:
        colors = np.asarray(colors)[finite]
        if colors.dtype != np.uint8:
            colors = np.clip(colors * (255 if colors.max() <= 1.0 else 1), 0, 255).astype(np.uint8)
    else:
        colors = np.full((n, 3), 200, np.uint8)

    header = (
        "ply\n"
        "format binary_little_endian 1.0\n"
        f"element vertex {n}\n"
        "property float x\nproperty float y\nproperty float z\n"
        "property uchar red\nproperty uchar green\nproperty uchar blue\n"
        "end_header\n"
    )
    dtype = np.dtype([("x", "<f4"), ("y", "<f4"), ("z", "<f4"),
                      ("red", "u1"), ("green", "u1"), ("blue", "u1")])
    verts = np.empty(n, dtype=dtype)
    verts["x"], verts["y"], verts["z"] = points[:, 0], points[:, 1], points[:, 2]
    verts["red"], verts["green"], verts["blue"] = colors[:, 0], colors[:, 1], colors[:, 2]

    with open(path, "wb") as f:
        f.write(header.encode("ascii"))
        f.write(verts.tobytes())
    return path