ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
FileTXT.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include <FileSystem.h>
9 #include <Logging.h>
10 #include <ProgressReporters.h>
11 
12 #include <cstdio>
13 
14 #include "cloudViewer/core/Dtype.h"
18 
19 namespace cloudViewer {
20 namespace t {
21 namespace io {
22 
25 }
26 
28  const std::string &filename,
29  geometry::PointCloud &pointcloud,
31  try {
32  pointcloud.Clear();
33 
35  if (!file.Open(filename, "r")) {
36  utility::LogWarning("Read TXT failed: unable to open file: {}",
37  filename);
38  return false;
39  }
40  utility::CountingProgressReporter reporter(params.update_progress);
41  reporter.SetTotal(file.GetFileSize());
42 
43  std::string format_txt =
45 
46  int64_t num_points = file.GetNumLines();
47  int64_t num_attrs;
48 
49  if (format_txt == "xyz") {
50  num_attrs = 3;
51  } else if (format_txt == "xyzd") {
52  num_attrs = 4;
53  } else if (format_txt == "xyzi") {
54  num_attrs = 4;
55  } else if (format_txt == "xyzn") {
56  num_attrs = 6;
57  } else if (format_txt == "xyzrgb") {
58  num_attrs = 6;
59  } else {
60  utility::LogWarning("The format of {} is not supported",
61  format_txt);
62  return false;
63  }
64 
65  core::Tensor pcd_buffer({num_points, num_attrs}, core::Float32);
66  float *pcd_buffer_ptr = pcd_buffer.GetDataPtr<float>();
67 
68  int i = 0;
69  std::vector<float> line_attrs(num_attrs);
70  float *line_attr_ptr = line_attrs.data();
71  const char *line_buffer;
72 
73  // Read TXT to buffer.
74  while ((line_buffer = file.ReadLine())) {
75  if (num_attrs == 3 &&
76  (sscanf(line_buffer, "%f %f %f", &line_attr_ptr[0],
77  &line_attr_ptr[1], &line_attr_ptr[2]) == 3)) {
78  std::memcpy(&pcd_buffer_ptr[num_attrs * i], line_attr_ptr,
79  num_attrs * sizeof(float));
80  } else if (num_attrs == 4 &&
81  (sscanf(line_buffer, "%f %f %f %f", &line_attr_ptr[0],
82  &line_attr_ptr[1], &line_attr_ptr[2],
83  &line_attr_ptr[3]) == 4)) {
84  std::memcpy(&pcd_buffer_ptr[num_attrs * i], line_attr_ptr,
85  num_attrs * sizeof(float));
86  } else if (num_attrs == 6 &&
87  (sscanf(line_buffer, "%f %f %f %f %f %f",
88  &line_attr_ptr[0], &line_attr_ptr[1],
89  &line_attr_ptr[2], &line_attr_ptr[3],
90  &line_attr_ptr[4], &line_attr_ptr[5]) == 6)) {
91  std::memcpy(&pcd_buffer_ptr[num_attrs * i], line_attr_ptr,
92  num_attrs * sizeof(float));
93  } else {
94  utility::LogWarning("Read TXT failed at line: {}", line_buffer);
95  return false;
96  }
97  if (++i % 1000 == 0) {
98  reporter.Update(file.CurPos());
99  }
100  }
101 
102  // Buffer to point cloud.
103  pointcloud.SetPointPositions(pcd_buffer.Slice(1, 0, 3, 1).Contiguous());
104  if (format_txt == "xyz") {
105  // No additional attributes.
106  } else if (format_txt == "xyzd") {
107  pointcloud.SetPointAttr("dopplers",
108  pcd_buffer.Slice(1, 3, 4, 1).Contiguous());
109  } else if (format_txt == "xyzi") {
110  pointcloud.SetPointAttr("intensities",
111  pcd_buffer.Slice(1, 3, 4, 1).Contiguous());
112  } else if (format_txt == "xyzn") {
113  pointcloud.SetPointAttr("normals",
114  pcd_buffer.Slice(1, 3, 6, 1).Contiguous());
115  } else if (format_txt == "xyzrgb") {
116  pointcloud.SetPointAttr("colors",
117  pcd_buffer.Slice(1, 3, 6, 1).Contiguous());
118  } else {
119  utility::LogWarning("The format of {} is not supported",
120  format_txt);
121  return false;
122  }
123  reporter.Finish();
124  return true;
125 
126  } catch (const std::exception &e) {
127  utility::LogWarning("Read TXT failed with exception: {}", e.what());
128  return false;
129  }
130 }
131 
133  const std::string &filename,
134  const geometry::PointCloud &pointcloud,
136  try {
138  if (!file.Open(filename, "w")) {
139  utility::LogWarning("Write TXT failed: unable to open file: {}",
140  filename);
141  return false;
142  }
143  utility::CountingProgressReporter reporter(params.update_progress);
144 
145  std::string format_txt =
147  const core::Tensor &points = pointcloud.GetPointPositions();
148 
149  if (!points.GetShape().IsCompatible({utility::nullopt, 3})) {
151  "Write TXT failed: Shape of points is {}, but it should "
152  "be Nx3.",
153  points.GetShape());
154  return false;
155  }
156  reporter.SetTotal(points.GetShape(0));
157  int64_t num_points = points.GetShape(0);
158  int64_t len_attr;
159 
160  // Check attribute length.
161  if (format_txt == "xyz") {
162  // No additional attributes.
163  len_attr = num_points;
164  } else if (format_txt == "xyzd") {
165  len_attr = pointcloud.GetPointAttr("dopplers").GetLength();
166  } else if (format_txt == "xyzi") {
167  len_attr = pointcloud.GetPointAttr("intensities").GetLength();
168  } else if (format_txt == "xyzn") {
169  len_attr = pointcloud.GetPointAttr("normals").GetLength();
170  } else if (format_txt == "xyzrgb") {
171  len_attr = pointcloud.GetPointAttr("colors").GetLength();
172  } else {
173  utility::LogWarning("The format of {} is not supported",
174  format_txt);
175  return false;
176  }
177 
178  if (len_attr != num_points) {
180  "Write TXT failed: Points ({}) and attributes ({}) have "
181  "different lengths.",
182  num_points, len_attr);
183  return false;
184  }
185 
186  const float *points_ptr = points.GetDataPtr<float>();
187  const float *attr_ptr = nullptr;
188 
189  if (format_txt == "xyz") {
190  for (int i = 0; i < num_points; i++) {
191  if (fprintf(file.GetFILE(), "%.10f %.10f %.10f\n",
192  points_ptr[3 * i + 0], points_ptr[3 * i + 1],
193  points_ptr[3 * i + 2]) < 0) {
195  "Write TXT failed: unable to write file: {}",
196  filename);
197  return false; // error happened during writing.
198  }
199  if (i % 1000 == 0) {
200  reporter.Update(i);
201  }
202  }
203  } else if (format_txt == "xyzd") {
204  attr_ptr = pointcloud.GetPointAttr("dopplers").GetDataPtr<float>();
205  for (int i = 0; i < num_points; i++) {
206  if (fprintf(file.GetFILE(), "%.10f %.10f %.10f %.10f\n",
207  points_ptr[3 * i + 0], points_ptr[3 * i + 1],
208  points_ptr[3 * i + 2], attr_ptr[i]) < 0) {
210  "Write TXT failed: unable to write file: {}",
211  filename);
212  return false; // error happened during writing.
213  }
214  if (i % 1000 == 0) {
215  reporter.Update(i);
216  }
217  }
218  } else if (format_txt == "xyzi") {
219  attr_ptr =
220  pointcloud.GetPointAttr("intensities").GetDataPtr<float>();
221  for (int i = 0; i < num_points; i++) {
222  if (fprintf(file.GetFILE(), "%.10f %.10f %.10f %.10f\n",
223  points_ptr[3 * i + 0], points_ptr[3 * i + 1],
224  points_ptr[3 * i + 2], attr_ptr[i]) < 0) {
226  "Write TXT failed: unable to write file: {}",
227  filename);
228  return false; // error happened during writing.
229  }
230  if (i % 1000 == 0) {
231  reporter.Update(i);
232  }
233  }
234  } else if (format_txt == "xyzn") {
235  attr_ptr = pointcloud.GetPointAttr("normals").GetDataPtr<float>();
236  for (int i = 0; i < num_points; i++) {
237  if (fprintf(file.GetFILE(),
238  "%.10f %.10f %.10f %.10f %.10f %.10f\n",
239  points_ptr[3 * i + 0], points_ptr[3 * i + 1],
240  points_ptr[3 * i + 2], attr_ptr[3 * i + 0],
241  attr_ptr[3 * i + 1], attr_ptr[3 * i + 2]) < 0) {
243  "Write TXT failed: unable to write file: {}",
244  filename);
245  return false; // error happened during writing.
246  }
247  if (i % 1000 == 0) {
248  reporter.Update(i);
249  }
250  }
251  } else if (format_txt == "xyzrgb") {
252  attr_ptr = pointcloud.GetPointAttr("colors").GetDataPtr<float>();
253  for (int i = 0; i < num_points; i++) {
254  if (fprintf(file.GetFILE(),
255  "%.10f %.10f %.10f %.10f %.10f %.10f\n",
256  points_ptr[3 * i + 0], points_ptr[3 * i + 1],
257  points_ptr[3 * i + 2], attr_ptr[3 * i + 0],
258  attr_ptr[3 * i + 1], attr_ptr[3 * i + 2]) < 0) {
260  "Write TXT failed: unable to write file: {}",
261  filename);
262  return false; // error happened during writing.
263  }
264  if (i % 1000 == 0) {
265  reporter.Update(i);
266  }
267  }
268  } else {
269  utility::LogWarning("The format of {} is not supported",
270  format_txt);
271  return false;
272  }
273 
274  reporter.Finish();
275  return true;
276 
277  } catch (const std::exception &e) {
278  utility::LogWarning("Write TXT failed with exception: {}", e.what());
279  return false;
280  }
281 }
282 
283 } // namespace io
284 } // namespace t
285 } // namespace cloudViewer
std::string filename
int points
cmdLineReadable * params[]
A point cloud contains a list of 3D points.
Definition: PointCloud.h:82
void SetPointPositions(const core::Tensor &value)
Set the value of the "positions" attribute. Convenience function.
Definition: PointCloud.h:186
core::Tensor & GetPointPositions()
Get the value of the "positions" attribute. Convenience function.
Definition: PointCloud.h:124
const TensorMap & GetPointAttr() const
Getter for point_attr_ TensorMap. Used in Pybind.
Definition: PointCloud.h:111
PointCloud & Clear() override
Clear all data in the point cloud.
Definition: PointCloud.h:251
void SetPointAttr(const std::string &key, const core::Tensor &value)
Definition: PointCloud.h:177
bool Open(const std::string &filename, const std::string &mode)
Open a file.
Definition: FileSystem.cpp:739
int64_t CurPos()
Returns current position in the file (ftell).
Definition: FileSystem.cpp:760
FILE * GetFILE()
Returns the underlying C FILE pointer.
Definition: FileSystem.h:264
int64_t GetFileSize()
Returns the file size in bytes.
Definition: FileSystem.cpp:772
int64_t GetNumLines()
Returns the number of lines in the file.
Definition: FileSystem.cpp:793
#define LogWarning(...)
Definition: Logging.h:72
const Dtype Float32
Definition: Dtype.cpp:42
static const std::string path
Definition: PointCloud.cpp:59
bool ReadPointCloudFromTXT(const std::string &filename, geometry::PointCloud &pointcloud, const cloudViewer::io::ReadPointCloudOption &params)
Definition: FileTXT.cpp:27
bool WritePointCloudToTXT(const std::string &filename, const geometry::PointCloud &pointcloud, const cloudViewer::io::WritePointCloudOption &params)
Definition: FileTXT.cpp:132
cloudViewer::io::FileGeometry ReadFileGeometryTypeTXT(const std::string &path)
Definition: FileTXT.cpp:23
std::string GetFileExtensionInLowerCase(const std::string &filename)
Definition: FileSystem.cpp:281
Generic file read and write utility for python interface.
Optional parameters to ReadPointCloud.
Definition: FileIO.h:39
Optional parameters to WritePointCloud.
Definition: FileIO.h:77