Helios++
Helios software for LiDAR simulations
LasSyncFileWriter.h
1 #pragma once
2 
3 #include <SyncFileWriter.h>
4 #include <mutex>
5 #include <string>
6 #include <ctime>
7 #include <laswriter.hpp>
8 #include <helios_version.h>
9 #include <glm/glm.hpp>
10 
17 public:
18  // *** CONSTANTS *** //
19  // ******************* //
23  static const U8 CLASSIFICATION_MASK = 31;
24 protected:
25  // *** ATTRIBUTES *** //
26  // ******************** //
30  LASwriteOpener lwOpener;
34  std::shared_ptr<LASwriter> lw;
38  LASheader lwHeader;
43  LASpoint lp;
51  double scaleFactor;
67  glm::dvec3 offset;
72  double minIntensity;
77  double maxIntensity;
89  bool finished;
125 public:
126  // *** CONSTRUCTION / DESTRUCTION *** //
127  // ************************************ //
139  const std::string &path,
140  bool compress = false,
141  double scaleFactor = 0.0001,
142  glm::dvec3 offset = glm::dvec3(0, 0, 0),
143  double minIntensity = 0.0,
144  double deltaIntensity = 1000000.0
145 
146  ) :
147  SyncFileWriter(path),
148  scaleFactor(scaleFactor),
149  offset(offset),
150  minIntensity(minIntensity),
151  deltaIntensity(deltaIntensity),
152  finished(false)
153  {
154  // Prepare
155  std::stringstream ss;
156  scaleFactorInverse = 1.0 / scaleFactor;
157  maxIntensity = minIntensity + deltaIntensity;
158  intensityCoefficient = 65535.0 / deltaIntensity;
159 
160 
161  // Build header
162  ss << "HELIOS++V" << HELIOS_VERSION;
163  std::string ssStr = ss.str();
164  size_t n = ssStr.length();
165  if(n > 31) n = 31;
166  memcpy(
167  lwHeader.generating_software,
168  ssStr.c_str(),
169  sizeof(char) * n
170  );
171  lwHeader.generating_software[n] = 0;
172  ss.str("");
173  lwHeader.version_major = U8(1);
174  lwHeader.version_minor = U8(0); // las version 1.0
175  time_t now = time(0);
176  tm *gmtm = gmtime(&now);
177  lwHeader.file_creation_day = gmtm->tm_yday;
178  lwHeader.file_creation_year = 1900 + gmtm->tm_year;
179  lwHeader.point_data_format = 1;
180  lwHeader.point_data_record_length = 28;
181  lwHeader.x_scale_factor = scaleFactor;
182  lwHeader.y_scale_factor = scaleFactor;
183  lwHeader.z_scale_factor = scaleFactor;
184  lwHeader.x_offset = F64(offset.x);
185  lwHeader.y_offset = F64(offset.y);
186  lwHeader.z_offset = F64(offset.z);
187  lwHeader.global_encoding = 0;
188 
189  // Extra bytes
190  ewAttrIdx = -1;
191  fwiAttrIdx = -1;
192  hoiAttrIdx = -1;
193  try{
194  I32 ewType = 9; // double
195  I32 fwiType = 5; // int
196  I32 hoiType = 5; // int
197  LASattribute ewAttr(
198  ewType,
199  "echo_width",
200  "Helios++ echo width"
201  );
202  LASattribute fwiAttr(
203  fwiType,
204  "fullwaveIndex",
205  "Helios++ fullwave index"
206  );
207  LASattribute hoiAttr(
208  hoiType,
209  "hitObjectId",
210  "Helios++ hit object ID"
211  );
212  ewAttrIdx = lwHeader.add_attribute(ewAttr);
213  fwiAttrIdx = lwHeader.add_attribute(fwiAttr);
214  hoiAttrIdx = lwHeader.add_attribute(hoiAttr);
215  }
216  catch(std::exception &e){
217  std::stringstream ss;
218  ss << "LasSyncFileWriter failed.\n\tEXCEPTION: "
219  << e.what();
220  logging::WARN(ss.str());
221  }
222  lwHeader.update_extra_bytes_vlr();
223  lwHeader.point_data_record_length += lwHeader.get_attributes_size();
224  ewAttrStart = lwHeader.get_attribute_start(ewAttrIdx);
225  fwiAttrStart = lwHeader.get_attribute_start(fwiAttrIdx);
226  hoiAttrStart = lwHeader.get_attribute_start(hoiAttrIdx);
227 
228  // Initialize LASpoint
229  lp.init(
230  &lwHeader,
231  lwHeader.point_data_format,
232  lwHeader.point_data_record_length,
233  0
234  );
235 
236  // Create LASWriter
237  lwOpener.set_file_name(path.c_str());
238  if(compress) lwOpener.set_format(LAS_TOOLS_FORMAT_LAZ);
239  else lwOpener.set_format(LAS_TOOLS_FORMAT_LAS);
240  lw = std::shared_ptr<LASwriter>(lwOpener.open(&lwHeader));
241 
242  }
244 
245  // *** W R I T E *** //
246  // ******************* //
251  void _write(Measurement const &m, glm::dvec3 const & shift) override{
252  // Compute shifted position
253  glm::dvec3 shifted = m.position + shift - offset;
254 
255  // Populate LAS point (base attributes)
256  lp.set_X(I32(shifted.x * scaleFactorInverse));
257  lp.set_Y(I32(shifted.y * scaleFactorInverse));
258  lp.set_Z(I32(shifted.z * scaleFactorInverse));
259  double intensityf = m.intensity;
260  if(intensityf < minIntensity) intensityf = minIntensity;
261  if(intensityf > maxIntensity) intensityf = maxIntensity;
262  U16 intensity = U16(
263  intensityCoefficient * (intensityf - minIntensity)
264  );
265  lp.set_intensity(intensity);
266  lp.set_return_number(U8(m.returnNumber));
267  lp.set_number_of_returns(U8(m.pulseReturnNumber));
268  lp.set_classification(U8(m.classification) & CLASSIFICATION_MASK);
269  lp.set_gps_time(F64(((double)m.gpsTime)/1000.0));
270 
271  // Populate LAS point (extra bytes attributes)
272  lp.set_attribute(ewAttrStart, F64(m.echo_width));
273  lp.set_attribute(fwiAttrStart, I32(m.fullwaveIndex));
274  lp.set_attribute(hoiAttrStart, I32(std::stoi(m.hitObjectId)));
275 
276  // Write and add to inventory
277  lw->write_point(&lp);
278  lw->update_inventory(&lp);
279  }
280 
285  void _write(
286  std::vector<double> const &fullwave,
287  int fullwaveIndex,
288  double minTime,
289  double maxTime,
290  glm::dvec3 const & beamOrigin,
291  glm::dvec3 const & beamDir,
292  long gpsTime
293  ) override {
294  throw HeliosException(
295  "LasSyncFileWriter does NOT support fullwave writing"
296  );
297  }
298 
307  void _write(Trajectory const &t) override {
308  throw HeliosException(
309  "LasSyncFileWriter does NOT support trajectory writing"
310  );
311  }
312 
313  // *** F I N I S H *** //
314  // ********************* //
323  void finish() override{
324  if(finished) return;
325 
326  lw->update_header(&lwHeader, true);
327 
328  lwHeader.remove_attribute(ewAttrIdx);
329  lwHeader.remove_attribute(fwiAttrIdx);
330  lwHeader.remove_attribute(hoiAttrIdx);
331  free(lwHeader.attributes);
332  free(lwHeader.attribute_starts);
333  free(lwHeader.attribute_sizes);
334 
335  lw->close();
336 
337  finished = true;
338  };
339 };
double minIntensity
Minimum value for intensity. Values less than this will be clipped to minIntensity.
Definition: LasSyncFileWriter.h:72
LASheader lwHeader
Header definition for the LAS file.
Definition: LasSyncFileWriter.h:38
std::string hitObjectId
ID of hit object.
Definition: Measurement.h:20
long gpsTime
Measurement GPS time.
Definition: Measurement.h:64
double scaleFactorInverse
Inverse of the scale factor.
Definition: LasSyncFileWriter.h:59
SyncFileWriter implementation for LAS format.
Definition: LasSyncFileWriter.h:16
int fullwaveIndex
Full wave index.
Definition: Measurement.h:56
Class representing a concrete trajectory definition.
Definition: Trajectory.h:8
Base class for Helios exceptions.
Definition: HeliosException.h:12
I32 hoiAttrStart
Hit object ID attribute start (LAS extra bytes format)
Definition: LasSyncFileWriter.h:124
Class representing a measurement.
Definition: Measurement.h:12
std::string path
Path to file to be written.
Definition: SyncFileWriter.h:19
int pulseReturnNumber
Pulse return number.
Definition: Measurement.h:52
LasSyncFileWriter(const std::string &path, bool compress=false, double scaleFactor=0.0001, glm::dvec3 offset=glm::dvec3(0, 0, 0), double minIntensity=0.0, double deltaIntensity=1000000.0)
Synchronous LAS file writer constructor.
Definition: LasSyncFileWriter.h:138
I32 fwiAttrStart
Full wave index attribute start (LAS extra bytes format)
Definition: LasSyncFileWriter.h:120
glm::dvec3 position
Definition: Measurement.h:24
LASpoint lp
LASpoint used to build different points which shall be written to LAS output file.
Definition: LasSyncFileWriter.h:43
I32 ewAttrStart
Echo width attribute start (LAS extra bytes format)
Definition: LasSyncFileWriter.h:116
I32 ewAttrIdx
Index of echo width attribute in LAS header definition.
Definition: LasSyncFileWriter.h:104
int classification
Point class.
Definition: Measurement.h:60
double intensityCoefficient
Precomputed intensity coefficient.
Definition: LasSyncFileWriter.h:100
double deltaIntensity
The difference between max and min intensity.
Definition: LasSyncFileWriter.h:85
double scaleFactor
Scale factor for coordinates.
Definition: LasSyncFileWriter.h:51
double intensity
Point intensity.
Definition: Measurement.h:40
glm::dvec3 offset
Offset for coordinates.
Definition: LasSyncFileWriter.h:67
double echo_width
Echo width.
Definition: Measurement.h:44
int returnNumber
Measurement return number.
Definition: Measurement.h:48
void _write(Trajectory const &t) override
Write trajectory to compressed file.
Definition: LasSyncFileWriter.h:307
I32 hoiAttrIdx
Index of hit object ID attribute in LAS header definition.
Definition: LasSyncFileWriter.h:112
I32 fwiAttrIdx
Index of full wave index attribute in LAS header definition.
Definition: LasSyncFileWriter.h:108
Abstract class defining common behavior for all synchronous file writers.
Definition: SyncFileWriter.h:14
void _write(Measurement const &m, glm::dvec3 const &shift) override
Write measurement to LAS file.
Definition: LasSyncFileWriter.h:251
LASwriteOpener lwOpener
LASwriter opener. Used to instantiate LASwriter lw.
Definition: LasSyncFileWriter.h:30
double maxIntensity
Maximum value for intensity. Values greater than this will be clipped to maxIntensity.
Definition: LasSyncFileWriter.h:77
std::shared_ptr< LASwriter > lw
LASwriter. Used to write to LAS file.
Definition: LasSyncFileWriter.h:34
bool finished
Flag used to control the sync writer status.
Definition: LasSyncFileWriter.h:89
static const U8 CLASSIFICATION_MASK
Classification mask constant for LAS format.
Definition: LasSyncFileWriter.h:23
void finish() override
LasSyncFileWriter updates header and guarantees writings have been done only after the finish method ...
Definition: LasSyncFileWriter.h:323
void _write(std::vector< double > const &fullwave, int fullwaveIndex, double minTime, double maxTime, glm::dvec3 const &beamOrigin, glm::dvec3 const &beamDir, long gpsTime) override
Write fullwave to LAS file.
Definition: LasSyncFileWriter.h:285