ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
LasScalarField.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 "LasScalarField.h"
9 
10 #include "LasDetails.h"
11 
12 #include <stdexcept>
13 
14 static constexpr bool IsPointFormatExtended(unsigned pointFormat)
15 {
16  return pointFormat >= 6;
17 }
18 
20 {
21  switch (id)
22  {
23  case Intensity:
24  return LasNames::Intensity;
25  case ReturnNumber:
27  case NumberOfReturns:
29  case ScanDirectionFlag:
31  case EdgeOfFlightLine:
33  case Classification:
35  case SyntheticFlag:
37  case KeypointFlag:
39  case WithheldFlag:
41  case ScanAngleRank:
43  case UserData:
44  return LasNames::UserData;
45  case PointSourceId:
47  case GpsTime:
48  return LasNames::GpsTime;
49  case ExtendedScanAngle:
50  return LasNames::ScanAngle;
53  case OverlapFlag:
54  return LasNames::OverlapFlag;
61  case NearInfrared:
63  }
64  // it's a gcc bug, which is fixed in v6.1
65  // throw std::logic_error("unhandled id");
66 }
67 
68 LasScalarField::Id LasScalarField::IdFromName(const char* name, unsigned targetPointFormat)
69 {
70  bool isExtended = IsPointFormatExtended(targetPointFormat);
71  if (strcmp(name, LasNames::Intensity) == 0)
72  {
74  }
75 
76  if (strcmp(name, LasNames::ReturnNumber) == 0)
77  {
78  if (!isExtended)
79  {
81  }
82  else
83  {
84  return LasScalarField::Id::ExtendedReturnNumber;
85  }
86  }
87 
88  if (strcmp(name, LasNames::NumberOfReturns) == 0)
89  {
90  if (!isExtended)
91  {
93  }
94  else
95  {
96  return LasScalarField::Id::ExtendedNumberOfReturns;
97  }
98  }
99 
100  if (strcmp(name, LasNames::ScanDirectionFlag) == 0)
101  {
103  }
104 
105  if (strcmp(name, LasNames::EdgeOfFlightLine) == 0)
106  {
108  }
109 
110  if (strcmp(name, LasNames::Classification) == 0)
111  {
112  if (!isExtended)
113  {
115  }
116  else
117  {
118  return LasScalarField::Id::ExtendedClassification;
119  }
120  }
121 
122  if (strcmp(name, LasNames::SyntheticFlag) == 0)
123  {
125  }
126 
127  if (strcmp(name, LasNames::KeypointFlag) == 0)
128  {
130  }
131 
132  if (strcmp(name, LasNames::WithheldFlag) == 0)
133  {
135  }
136 
137  if (strcmp(name, LasNames::ScanAngleRank) == 0)
138  {
140  }
141 
142  if (strcmp(name, LasNames::UserData) == 0)
143  {
145  }
146 
147  if (strcmp(name, LasNames::PointSourceId) == 0)
148  {
150  }
151 
152  if (strcmp(name, LasNames::GpsTime) == 0)
153  {
155  }
156 
157  if (strcmp(name, LasNames::ScanAngle) == 0)
158  {
159  return LasScalarField::Id::ExtendedScanAngle;
160  }
161 
162  if (strcmp(name, LasNames::ScannerChannel) == 0)
163  {
164  return LasScalarField::Id::ExtendedScannerChannel;
165  }
166 
167  if (strcmp(name, LasNames::OverlapFlag) == 0)
168  {
170  }
171 
172  if (strcmp(name, LasNames::NearInfrared) == 0)
173  {
175  }
176 
177  CVLog::Warning("Unhandled Name %s", name);
178  throw std::logic_error("Unknown name");
179 }
180 
182 {
183  switch (id)
184  {
185  case Intensity:
186  return Range::ForType<uint16_t>();
187  case ReturnNumber:
188  return Range::ForBitCount(3);
189  case NumberOfReturns:
190  return Range::ForBitCount(3);
191  case ScanDirectionFlag:
192  return Range::ForBitCount(1);
193  case EdgeOfFlightLine:
194  return Range::ForBitCount(1);
195  case Classification:
196  return Range::ForBitCount(5);
197  case SyntheticFlag:
198  return Range::ForBitCount(1);
199  case KeypointFlag:
200  return Range::ForBitCount(1);
201  case WithheldFlag:
202  return Range::ForBitCount(1);
203  case ScanAngleRank:
204  // The real range is Range(-90, 90);
205  // but we will allow the full range
206  return Range::ForType<int8_t>();
207  case UserData:
208  return Range::ForType<uint8_t>();
209  case PointSourceId:
210  return Range::ForType<uint16_t>();
211  case GpsTime:
212  return Range(std::numeric_limits<ScalarType>::lowest(), std::numeric_limits<ScalarType>::max());
213  case ExtendedScanAngle:
214  return Range(-30'000.0, 30'000.0);
216  return Range::ForBitCount(2);
217  case OverlapFlag:
218  return Range::ForBitCount(1);
220  return Range::ForType<uint8_t>();
222  return Range::ForBitCount(4);
224  return Range::ForBitCount(4);
225  case NearInfrared:
226  return Range::ForType<uint16_t>();
227  }
228 
229  Q_ASSERT_X(false, __FUNCTION__, "Unhandled las scalar field range");
230  return Range::ForType<ScalarType>();
231 }
232 
234  : id(id)
235  , sf(sf)
236  , range(LasScalarField::ValueRange(id))
237 {
238 }
239 
240 const char* LasScalarField::name() const
241 {
242  return LasScalarField::NameFromId(id);
243 }
244 
245 std::vector<LasScalarField> LasScalarField::ForPointFormat(unsigned pointFormatId)
246 {
247  std::vector<LasScalarField> scalarFields;
248  scalarFields.reserve(16);
249 
250  if (pointFormatId >= 0 && pointFormatId <= 5)
251  {
252  scalarFields.emplace_back(LasScalarField::Id::Intensity);
253  scalarFields.emplace_back(LasScalarField::Id::ReturnNumber);
254  scalarFields.emplace_back(LasScalarField::Id::NumberOfReturns);
255  scalarFields.emplace_back(LasScalarField::Id::ScanDirectionFlag);
256  scalarFields.emplace_back(LasScalarField::Id::EdgeOfFlightLine);
257  scalarFields.emplace_back(LasScalarField::Id::Classification);
258  scalarFields.emplace_back(LasScalarField::Id::SyntheticFlag);
259  scalarFields.emplace_back(LasScalarField::Id::KeypointFlag);
260  scalarFields.emplace_back(LasScalarField::Id::WithheldFlag);
261  scalarFields.emplace_back(LasScalarField::Id::ScanAngleRank);
262  scalarFields.emplace_back(LasScalarField::Id::UserData);
263  scalarFields.emplace_back(LasScalarField::Id::PointSourceId);
264  }
265  else if (pointFormatId >= 6 && pointFormatId <= 10)
266  {
267  scalarFields.emplace_back(LasScalarField::Id::Intensity);
268  scalarFields.emplace_back(LasScalarField::Id::ExtendedReturnNumber);
269  scalarFields.emplace_back(LasScalarField::Id::ExtendedNumberOfReturns);
270  scalarFields.emplace_back(LasScalarField::Id::ExtendedScannerChannel);
271  scalarFields.emplace_back(LasScalarField::Id::ScanDirectionFlag);
272  scalarFields.emplace_back(LasScalarField::Id::EdgeOfFlightLine);
273  scalarFields.emplace_back(LasScalarField::Id::ExtendedClassification);
274  scalarFields.emplace_back(LasScalarField::Id::SyntheticFlag);
275  scalarFields.emplace_back(LasScalarField::Id::KeypointFlag);
276  scalarFields.emplace_back(LasScalarField::Id::WithheldFlag);
277  scalarFields.emplace_back(LasScalarField::Id::OverlapFlag);
278  scalarFields.emplace_back(LasScalarField::Id::ExtendedScanAngle);
279  scalarFields.emplace_back(LasScalarField::Id::UserData);
280  scalarFields.emplace_back(LasScalarField::Id::PointSourceId);
281  }
282 
283  if (LasDetails::HasGpsTime(pointFormatId))
284  {
285  scalarFields.emplace_back(LasScalarField::Id::GpsTime);
286  }
287 
288  if (LasDetails::HasNearInfrared(pointFormatId))
289  {
290  scalarFields.emplace_back(LasScalarField::Id::NearInfrared);
291  }
292 
293  scalarFields.shrink_to_fit();
294 
295  return scalarFields;
296 }
std::string name
static constexpr bool IsPointFormatExtended(unsigned pointFormat)
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
A scalar field associated to display-related parameters.
int max(int a, int b)
Definition: cutil_math.h:48
bool HasNearInfrared(unsigned pointFormatId)
Returns whether the point format support Near Infrared.
Definition: LasDetails.h:151
bool HasGpsTime(unsigned pointFormatId)
Returns whether the point format supports Gps Time.
Definition: LasDetails.h:125
constexpr const char * ScanDirectionFlag
Definition: LasDetails.h:62
constexpr const char * WithheldFlag
Definition: LasDetails.h:67
constexpr const char * EdgeOfFlightLine
Definition: LasDetails.h:63
constexpr const char * ScanAngle
Definition: LasDetails.h:74
constexpr const char * SyntheticFlag
Definition: LasDetails.h:65
constexpr const char * NumberOfReturns
Definition: LasDetails.h:61
constexpr const char * OverlapFlag
Definition: LasDetails.h:76
constexpr const char * UserData
Definition: LasDetails.h:69
constexpr const char * Classification
Definition: LasDetails.h:64
constexpr const char * ScannerChannel
Definition: LasDetails.h:75
constexpr const char * KeypointFlag
Definition: LasDetails.h:66
constexpr const char * ReturnNumber
Definition: LasDetails.h:60
constexpr const char * ScanAngleRank
Definition: LasDetails.h:68
constexpr const char * NearInfrared
Definition: LasDetails.h:77
constexpr const char * GpsTime
Definition: LasDetails.h:71
constexpr const char * Intensity
Definition: LasDetails.h:59
constexpr const char * PointSourceId
Definition: LasDetails.h:70
static Range ForBitCount(uint8_t numBits)
static std::vector< LasScalarField > ForPointFormat(unsigned pointFormatId)
const char * name() const
static LasScalarField::Range ValueRange(LasScalarField::Id id)
Returns the range of value the given field (ID) supports.
static constexpr const char * NameFromId(LasScalarField::Id id)
Returns the name that correspond to the given LasScalarField::Id variant.
LasScalarField()=delete
static LasScalarField::Id IdFromName(const char *name, unsigned targetPointFormat)