ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
LasScalarFieldSaver.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 "LasScalarFieldSaver.h"
9 
10 #include <ecvScalarField.h>
11 #include <laszip/laszip_api.h>
12 
13 LasScalarFieldSaver::LasScalarFieldSaver(std::vector<LasScalarField>&& standardFields,
14  std::vector<LasExtraScalarField>&& extraFields)
15  : m_standardFields(standardFields)
16  , m_extraFields(extraFields)
17 {
18 }
19 
20 void LasScalarFieldSaver::handleScalarFields(size_t pointIndex, laszip_point& point)
21 {
22  for (const LasScalarField& field : m_standardFields)
23  {
24  Q_ASSERT_X(field.sf != nullptr, __func__, "LasScalarField has a null ptr to ccScalarField");
25  ScalarType value = field.sf->getValue(pointIndex);
26  value = std::max(field.range.min, value);
27  value = std::min(field.range.max, value);
28  switch (field.id)
29  {
31  if (field.sf)
32  {
33  point.intensity = static_cast<laszip_U16>(value);
34  }
35  break;
37  if (field.sf)
38  {
39  point.return_number = static_cast<laszip_U8>(value);
40  }
41  break;
43  if (field.sf)
44  {
45  point.number_of_returns = static_cast<laszip_U8>(value);
46  }
47  break;
49  if (field.sf)
50  {
51  point.scan_direction_flag = (static_cast<laszip_U8>(value) > 0);
52  }
53  break;
55  if (field.sf)
56  {
57  point.edge_of_flight_line = (static_cast<laszip_U8>(value) > 0);
58  }
59  break;
61  if (field.sf)
62  {
63  point.classification = static_cast<laszip_U8>(value);
64  }
66  if (field.sf)
67  {
68  point.synthetic_flag = (static_cast<laszip_U8>(value) > 0);
69  }
70  break;
72  if (field.sf)
73  {
74  point.keypoint_flag = (static_cast<laszip_U8>(value) > 0);
75  }
76  break;
78  if (field.sf)
79  {
80  point.withheld_flag = (static_cast<laszip_U8>(value) > 0);
81  }
82  break;
84  if (field.sf)
85  {
86  point.scan_angle_rank = static_cast<laszip_I8>(value);
87  }
89  if (field.sf)
90  {
91  point.user_data = static_cast<laszip_U8>(value);
92  }
93  break;
95  if (field.sf)
96  {
97  point.point_source_ID = static_cast<laszip_U16>(value);
98  }
99  break;
101  if (field.sf)
102  {
103  point.gps_time = static_cast<laszip_F64>(value) + field.sf->getGlobalShift();
104  }
105  break;
107  if (field.sf)
108  {
109  point.extended_scan_angle = static_cast<laszip_I16>(value / SCAN_ANGLE_SCALE);
110  }
111  break;
113  if (field.sf)
114  {
115  point.extended_scanner_channel = static_cast<laszip_U8>(value);
116  }
117  break;
119  if (field.sf)
120  {
121  point.extended_classification_flags |= (static_cast<laszip_U8>(value) > 0) ? LasDetails::OVERLAP_FLAG_BIT_MASK : 0;
122  }
123  break;
125  if (field.sf)
126  {
127  point.extended_classification = static_cast<laszip_U8>(value);
128  }
129  break;
131  if (field.sf)
132  {
133  point.extended_return_number = static_cast<laszip_U16>(value);
134  }
135  break;
137  if (field.sf)
138  {
139  point.extended_number_of_returns = static_cast<laszip_U16>(value);
140  }
141  break;
143  if (field.sf)
144  {
145  point.rgb[3] = static_cast<laszip_U16>(value);
146  }
147  break;
148  }
149  }
150 }
151 
152 void LasScalarFieldSaver::handleExtraFields(size_t pointIndex, laszip_point& point)
153 {
154  if (point.num_extra_bytes == 0 || point.extra_bytes == nullptr)
155  {
156  return;
157  }
158 
159  ScalarType values[LasExtraScalarField::MAX_DIM_SIZE] = {0.0};
160 
161  for (const LasExtraScalarField& extraField : m_extraFields)
162  {
163  laszip_U8* dataStart = point.extra_bytes + extraField.byteOffset;
164 
165  assert(extraField.byteOffset < static_cast<unsigned>(point.num_extra_bytes));
166  assert(extraField.byteOffset + extraField.byteSize() <= static_cast<unsigned>(point.num_extra_bytes));
167 
168  for (size_t elemIndex{0}; elemIndex < extraField.numElements(); ++elemIndex)
169  {
170  values[elemIndex] = (*extraField.scalarFields[elemIndex])[pointIndex];
171  }
172 
173  if (extraField.scaleIsRelevant() || extraField.offsetIsRelevant())
174  {
175  assert(extraField.numElements() <= 3);
176  for (size_t elemIndex{0}; elemIndex < extraField.numElements(); ++elemIndex)
177  {
178  values[elemIndex] = (values[elemIndex] - extraField.offsets[elemIndex]) / extraField.scales[elemIndex];
179  }
180  }
181 
182  for (unsigned i = 0; i < extraField.numElements(); i++)
183  {
184  switch (extraField.type)
185  {
187  WriteScalarValueAs<uint8_t>(values[i], dataStart);
188  break;
190  WriteScalarValueAs<uint16_t>(values[i], dataStart);
191  break;
193  WriteScalarValueAs<uint32_t>(values[i], dataStart);
194  break;
196  WriteScalarValueAs<uint64_t>(values[i], dataStart);
197  break;
199  WriteScalarValueAs<int8_t>(values[i], dataStart);
200  break;
202  WriteScalarValueAs<int16_t>(values[i], dataStart);
203  break;
205  WriteScalarValueAs<int32_t>(values[i], dataStart);
206  break;
208  WriteScalarValueAs<int64_t>(values[i], dataStart);
209  break;
211  WriteScalarValueAs<float>(values[i], dataStart);
212  break;
214  WriteScalarValueAs<double>(values[i], dataStart);
215  break;
218  break;
219  }
220  dataStart += extraField.elementSize();
221  }
222  }
223 }
constexpr double SCAN_ANGLE_SCALE
Definition: LasDetails.h:50
This serves the same purpose as LasScalarField but for extra bytes.
static constexpr unsigned MAX_DIM_SIZE
void handleExtraFields(size_t pointIndex, laszip_point &point)
Saves the extra scalar fields values for pointIndex into the given laszip_point.
LasScalarFieldSaver()=default
void handleScalarFields(size_t pointIndex, laszip_point &point)
Saves the scalar fields values for pointIndex into the given laszip_point.
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
constexpr unsigned OVERLAP_FLAG_BIT_MASK
Definition: LasDetails.h:85
Definition: lsd.c:149