Coverage for trimesh/exchange/xyz.py: 89%
36 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-24 04:40 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-24 04:40 +0000
1import numpy as np
3from .. import util
4from ..points import PointCloud
7def load_xyz(file_obj, delimiter=None, **kwargs):
8 """
9 Load an XYZ file into a PointCloud.
11 Parameters
12 ------------
13 file_obj : an open file-like object
14 Source data, ASCII XYZ
15 delimiter : None or string
16 Characters used to separate the columns of the file
17 If not passed will use whitespace or commas
19 Returns
20 ----------
21 kwargs : dict
22 Data which can be passed to PointCloud constructor
23 """
24 # read the whole file into memory as a string
25 raw = util.decode_text(file_obj.read()).strip()
26 # get the first line to look at
27 first = raw[: raw.find("\n")].strip()
28 # guess the column count by looking at the first line
29 columns = len(first.split())
30 if columns < 3:
31 raise ValueError("not enough columns in xyz file!")
33 if delimiter is None and "," in first:
34 # if no delimiter passed and file has commas
35 delimiter = ","
36 if delimiter is not None:
37 # replace delimiter with whitespace so split works
38 raw = raw.replace(delimiter, " ")
40 # use string splitting to get array
41 array = np.array(raw.split(), dtype=np.float64)
42 # reshape to column count
43 # if file has different numbers of values
44 # per row this will fail as it should
45 data = array.reshape((-1, columns))
47 # start with no colors
48 colors = None
49 # vertices are the first three columns
50 vertices = data[:, :3]
51 if columns == 6:
52 # RGB colors
53 colors = np.array(data[:, 3:], dtype=np.uint8)
54 colors = np.concatenate(
55 (colors, np.ones((len(data), 1), dtype=np.uint8) * 255), axis=1
56 )
57 elif columns >= 7:
58 # extract RGBA colors
59 colors = np.array(data[:, 3:8], dtype=np.uint8)
60 # add extracted colors and vertices to kwargs
61 kwargs.update({"vertices": vertices, "colors": colors})
63 return kwargs
66def export_xyz(cloud, write_colors=True, delimiter=None):
67 """
68 Export a PointCloud object to an XYZ format string.
70 Parameters
71 -------------
72 cloud : trimesh.PointCloud
73 Geometry in space
74 write_colors : bool
75 Write colors or not
76 delimiter : None or str
77 What to separate columns with
79 Returns
80 --------------
81 export : str
82 Pointcloud in XYZ format
83 """
84 if not isinstance(cloud, PointCloud):
85 raise ValueError("object must be PointCloud")
87 # compile data into a blob
88 data = cloud.vertices
89 if write_colors and hasattr(cloud, "colors") and cloud.colors is not None:
90 # stack colors and vertices
91 data = np.hstack((data, cloud.colors))
93 # if delimiter not passed use whitespace
94 if delimiter is None:
95 delimiter = " "
96 # stack blob into XYZ format
97 export = util.array_to_string(data, col_delim=delimiter)
99 return export
102_xyz_loaders = {"xyz": load_xyz}
103_xyz_exporters = {"xyz": export_xyz}