ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
LasTiler.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 "LasTiler.h"
9 
10 #include <QElapsedTimer>
11 #include <QFileInfo>
12 #include <ecvProgressDialog.h>
13 
14 CC_FILE_ERROR TileLasReader(laszip_POINTER laszipReader, const QString& originName, const LasTilingOptions& options)
15 {
16  laszip_header* laszipHeader{nullptr};
17  laszip_CHAR* errorMsg{nullptr};
18 
19  if (laszip_get_header_pointer(laszipReader, &laszipHeader))
20  {
21  laszip_get_error(laszipHeader, &errorMsg);
22  CVLog::Warning("[LAS] laszip error: '%s'", errorMsg);
23  laszip_close_reader(laszipReader);
24  laszip_clean(laszipReader);
25  laszip_destroy(laszipReader);
27  }
28 
29  laszip_U64 pointCount;
30  if (laszipHeader->version_minor == 4)
31  {
32  pointCount = laszipHeader->extended_number_of_point_records;
33  }
34  else
35  {
36  pointCount = laszipHeader->number_of_point_records;
37  }
38 
39  laszip_point* laszipPoint{nullptr};
40  if (laszip_get_point_pointer(laszipReader, &laszipPoint))
41  {
42  laszip_get_error(laszipHeader, &errorMsg);
43  CVLog::Warning("[LAS] laszip error: '%s'", errorMsg);
44  laszip_close_reader(laszipReader);
45  laszip_clean(laszipReader);
46  laszip_destroy(laszipReader);
48  }
49 
50  std::vector<laszip_POINTER> writers;
51  writers.resize(options.numTiles0 * options.numTiles1, nullptr);
52 
54 
55  const size_t index0 = options.index0();
56  const size_t index1 = options.index1();
57 
58  double cloudMins[3] = {
59  laszipHeader->min_x,
60  laszipHeader->min_y,
61  laszipHeader->min_z,
62  };
63 
64  double cloudBBox[3] = {
65  laszipHeader->max_x - laszipHeader->min_x,
66  laszipHeader->max_y - laszipHeader->min_y,
67  laszipHeader->max_z - laszipHeader->min_z,
68  };
69 
70  double tileSize[2] = {
71  cloudBBox[index0] / options.numTiles0,
72  cloudBBox[index1] / options.numTiles1,
73  };
74 
75  laszip_F64 laszipCoordinates[3] = {0};
76 
77  QElapsedTimer timer;
78  timer.start();
79 
80  QFileInfo originInfo(originName);
81 
82  ecvProgressDialog progressDialog(true);
83  progressDialog.setMethodTitle("Tiling LAS file");
84  progressDialog.setInfo("Tiling...");
85  cloudViewer::NormalizedProgress normProgress(&progressDialog, pointCount);
86  progressDialog.start();
87 
88  for (unsigned i = 0; i < pointCount; ++i)
89  {
90  if (laszip_read_point(laszipReader))
91  {
92  laszip_get_error(laszipReader, &errorMsg);
93  CVLog::Warning("[LAS] laszip error :'%s'", errorMsg);
95  break;
96  }
97 
98  if (laszip_get_coordinates(laszipReader, laszipCoordinates))
99  {
100  laszip_get_error(laszipReader, &errorMsg);
101  CVLog::Warning("[LAS] laszip error :'%s'", errorMsg);
103  break;
104  }
105 
106  auto tileI = static_cast<size_t>((laszipCoordinates[index0] - cloudMins[index0]) / tileSize[0]);
107  tileI = std::min(tileI, static_cast<size_t>(options.numTiles0 - 1));
108  auto tileJ = static_cast<size_t>((laszipCoordinates[index1] - cloudMins[index1]) / tileSize[1]);
109  tileJ = std::min(tileJ, static_cast<size_t>(options.numTiles1 - 1));
110 
111  const size_t tileIndex = (tileI * options.numTiles1) + tileJ;
112 
113  laszip_POINTER& writer = writers[tileIndex];
114 
115  if (writer == nullptr)
116  {
117  QString outputName;
118 
119  if (!options.outputDir.isEmpty())
120  {
121  outputName += options.outputDir;
122  outputName += '/';
123  }
124 
125  const QString fileName = QString("%1_%2_%3.%4").arg(originInfo.baseName(), QString::number(tileI), QString::number(tileJ), originInfo.suffix());
126  outputName += fileName;
127  const std::string outputNameStd = outputName.toStdString();
128 
129  if (laszip_create(&writer))
130  {
131  CVLog::Warning("[LAS] Failed to create tile writer");
133  break;
134  }
135 
136  if (laszip_set_header(writer, laszipHeader))
137  {
138  laszip_get_error(writer, &errorMsg);
139  CVLog::Warning("[LAS] laszip error :'%s'", errorMsg);
141  break;
142  }
143 
144  if (laszip_open_writer(writer, outputNameStd.c_str(), false))
145  {
146  laszip_get_error(writer, &errorMsg);
147  CVLog::Warning("[LAS] laszip error :'%s'", errorMsg);
149  break;
150  }
151  }
152 
153  if (laszip_set_point(writer, laszipPoint))
154  {
155  laszip_get_error(writer, &errorMsg);
156  CVLog::Warning("[LAS] laszip error :'%s'", errorMsg);
158  break;
159  }
160 
161  if (laszip_write_point(writer))
162  {
163  laszip_get_error(writer, &errorMsg);
164  CVLog::Warning("[LAS] laszip error :'%s'", errorMsg);
166  break;
167  }
168 
169  if (laszip_update_inventory(writer))
170  {
171  laszip_get_error(writer, &errorMsg);
172  CVLog::Warning("[LAS] laszip error :'%s'", errorMsg);
174  break;
175  }
176 
177  normProgress.oneStep();
178  }
179 
180  for (laszip_POINTER writer : writers)
181  {
182  if (writer == nullptr)
183  {
184  continue;
185  }
186 
187  laszip_close_writer(writer);
188  laszip_clean(writer);
189  laszip_destroy(writer);
190  }
191 
192  laszip_close_reader(laszipReader);
193  laszip_clean(laszipReader);
194  laszip_destroy(laszipReader);
195 
196  if (error == CC_FERR_NO_ERROR)
197  {
198  timer.elapsed();
199  qint64 elapsed_ms = timer.elapsed();
200  qint64 minutes = elapsed_ms / (1000 * 60);
201  elapsed_ms -= minutes * (1000 * 60);
202  qint64 seconds = elapsed_ms / 1000;
203  elapsed_ms -= seconds * 1000;
204  CVLog::Print(QString("[LAS] File tiled in %1m%2s%3ms").arg(minutes).arg(seconds).arg(elapsed_ms));
205  }
206 
207  return error;
208 }
CC_FILE_ERROR
Typical I/O filter errors.
Definition: FileIOFilter.h:20
@ CC_FERR_THIRD_PARTY_LIB_FAILURE
Definition: FileIOFilter.h:36
@ CC_FERR_NO_ERROR
Definition: FileIOFilter.h:21
CC_FILE_ERROR TileLasReader(laszip_POINTER laszipReader, const QString &originName, const LasTilingOptions &options)
Definition: LasTiler.cpp:14
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
bool oneStep()
Increments total progress value of a single unit.
Graphical progress indicator (thread-safe)
virtual void start() override
virtual void setInfo(const char *infoStr) override
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle) override
Notifies the algorithm title.
int min(int a, int b)
Definition: cutil_math.h:53
static void error(char *msg)
Definition: lsd.c:159
#define seconds
Definition: rename.h:375
size_t index0() const
Definition: LasTiler.h:45
size_t index1() const
Definition: LasTiler.h:59
unsigned numTiles0
Definition: LasTiler.h:42
unsigned numTiles1
Definition: LasTiler.h:43
QString outputDir
Definition: LasTiler.h:40
double timer
Definition: struct.h:215