1 /*
2 ===============================================================================
3 
4   FILE:  las.hpp
5 
6   CONTENTS:
7     Point formats for LAS
8 
9   PROGRAMMERS:
10 
11     martin.isenburg@rapidlasso.com  -  http://rapidlasso.com
12     uday.karan@gmail.com - Hobu, Inc.
13 
14   COPYRIGHT:
15 
16     (c) 2007-2014, martin isenburg, rapidlasso - tools to catch reality
17     (c) 2014, Uday Verma, Hobu, Inc.
18 
19     This is free software; you can redistribute and/or modify it under the
20     terms of the GNU Lesser General Licence as published by the Free Software
21     Foundation. See the COPYING file for more information.
22 
23     This software is distributed WITHOUT ANY WARRANTY and without even the
24     implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25 
26   CHANGE HISTORY:
27 
28 ===============================================================================
29 */
30 
31 #pragma once
32 
33 #include <stdint.h>
34 
35 #include "decoder.hpp"
36 #include "encoder.hpp"
37 #include "model.hpp"
38 #include "compressor.hpp"
39 #include "streams.hpp"
40 #include "utils.hpp"
41 
42 namespace lazperf
43 {
44 namespace las
45 {
46 
47 #pragma pack(push, 1)
48 struct point10
49 {
50     int x;
51     int y;
52     int z;
53     unsigned short intensity;
54     unsigned char return_number : 3;
55     unsigned char number_of_returns_of_given_pulse : 3;
56     unsigned char scan_direction_flag : 1;
57     unsigned char edge_of_flight_line : 1;
58     unsigned char classification;
59     char scan_angle_rank;
60     unsigned char user_data;
61     unsigned short point_source_ID;
62 
point10lazperf::las::point1063     point10() : x(0), y(0), intensity(0), return_number(0),
64         number_of_returns_of_given_pulse(0), scan_direction_flag(0),
65         edge_of_flight_line(0), classification(0),
66         scan_angle_rank(0), user_data(0), point_source_ID(0)
67     {}
68 
point10lazperf::las::point1069     point10(const char *buf)
70     {
71         unpack(buf);
72     }
73 
unpacklazperf::las::point1074     void unpack(const char *c)
75     {
76         x = utils::unpack<int32_t>(c);                     c += sizeof(int32_t);
77         y = utils::unpack<int32_t>(c);                     c += sizeof(int32_t);
78         z = utils::unpack<int32_t>(c);                     c += sizeof(int32_t);
79         intensity = utils::unpack<uint16_t>(c);            c += sizeof(unsigned short);
80         to_bitfields(*c++);
81         classification = *c++;
82         scan_angle_rank = *c++;
83         user_data = *c++;
84         point_source_ID = utils::unpack<uint16_t>(c);
85     }
86 
packlazperf::las::point1087     void pack(char *c)
88     {
89         utils::pack(x, c);                 c += sizeof(int);
90         utils::pack(y, c);                 c += sizeof(int);
91         utils::pack(z, c);                 c += sizeof(int);
92         utils::pack(intensity, c);         c += sizeof(unsigned short);
93         *c++ = from_bitfields();
94         *c++ = classification;
95         *c++ = scan_angle_rank;
96         *c++ = user_data;
97         utils::pack(point_source_ID, c);
98     }
99 
to_bitfieldslazperf::las::point10100     void to_bitfields(unsigned char d)
101     {
102         return_number = d & 0x7;
103         number_of_returns_of_given_pulse = (d >> 3) & 0x7;
104         scan_direction_flag = (d >> 6) & 0x1;
105         edge_of_flight_line = (d >> 7) & 0x1;
106     }
107 
from_bitfieldslazperf::las::point10108     unsigned char from_bitfields() const
109     {
110         return ((edge_of_flight_line & 0x1) << 7) |
111                ((scan_direction_flag & 0x1) << 6) |
112                ((number_of_returns_of_given_pulse & 0x7) << 3) |
113                (return_number & 0x7);
114     }
115 };
116 
117 struct gpstime
118 {
119 public:
gpstimelazperf::las::gpstime120     gpstime() : value(0)
121     {}
gpstimelazperf::las::gpstime122     gpstime(int64_t v) : value(v)
123     {}
gpstimelazperf::las::gpstime124     gpstime(const char *c)
125     {
126         unpack(c);
127     }
128 
unpacklazperf::las::gpstime129     void unpack(const char *in)
130     {
131         uint64_t lower = utils::unpack<uint32_t>(in);
132         uint64_t upper = utils::unpack<uint32_t>(in + 4);
133 
134         value = ((upper << 32) | lower);
135     }
136 
packlazperf::las::gpstime137     void pack(char *buffer)
138     {
139         utils::pack(uint32_t(value & 0xFFFFFFFF), buffer);
140         utils::pack(uint32_t(value >> 32), buffer + 4);
141     }
142 
143     // Note that in a LAS file, gps time is a double, not int64_t, but since we always
144     // treat it as int here, we just unpack to that form.
145     int64_t value;
146 };
147 
148 struct rgb
149 {
150 public:
rgblazperf::las::rgb151     rgb() : r(0), g(0), b(0)
152     {}
rgblazperf::las::rgb153     rgb(unsigned short r, unsigned short g, unsigned short b) : r(r), g(g), b(b)
154     {}
rgblazperf::las::rgb155     rgb(const char *buf)
156     {
157         unpack(buf);
158     }
159 
unpacklazperf::las::rgb160     void unpack(const char *c)
161     {
162         r = utils::unpack<uint16_t>(c);
163         g = utils::unpack<uint16_t>(c + 2);
164         b = utils::unpack<uint16_t>(c + 4);
165     }
166 
packlazperf::las::rgb167     void pack(char *c)
168     {
169         utils::pack(r, c);
170         utils::pack(g, c + 2);
171         utils::pack(b, c + 4);
172     }
173 
174     uint16_t r;
175     uint16_t g;
176     uint16_t b;
177 };
178 
179 struct rgb14 : public rgb
180 {
rgb14lazperf::las::rgb14181     rgb14()
182     {}
rgb14lazperf::las::rgb14183     rgb14(const rgb& val) : rgb(val)
184     {}
185 };
186 
187 struct nir14
188 {
189     uint16_t val;
190 
nir14lazperf::las::nir14191     nir14() : val(0)
192     {}
193 
nir14lazperf::las::nir14194     nir14(uint16_t v) : val(v)
195     {}
196 
nir14lazperf::las::nir14197     nir14(const char *p)
198     {
199         unpack(p);
200     }
201 
packlazperf::las::nir14202     void pack(char *p)
203     {
204         utils::pack(val, p);
205     }
206 
unpacklazperf::las::nir14207     void unpack(const char *p)
208     {
209         val = utils::unpack<uint16_t>(p);
210     }
211 };
212 
213 using byte14 = std::vector<uint8_t>;
214 
215 
216 struct extrabytes : public std::vector<uint8_t>
217 {};
218 
219 struct point14
220 {
221     int32_t x_;
222     int32_t y_;
223     int32_t z_;
224     uint16_t intensity_;
225     uint8_t returns_;
226     uint8_t flags_;
227     uint8_t classification_;
228     uint8_t user_data_;
229     int16_t scan_angle_;
230     uint16_t point_source_ID_;
231     double gpstime_;
232 
point14lazperf::las::point14233     point14()
234     {}
235 
point14lazperf::las::point14236     point14(const char *c)
237     {
238         unpack(c);
239     }
240 
xlazperf::las::point14241     int32_t x() const
242     { return x_; }
setXlazperf::las::point14243     void setX(int32_t x)
244     { x_ = x; }
245 
ylazperf::las::point14246     int32_t y() const
247     { return y_; }
setYlazperf::las::point14248     void setY(int32_t y)
249     { y_ = y; }
250 
zlazperf::las::point14251     int32_t z() const
252     { return z_; }
setZlazperf::las::point14253     void setZ(int32_t z)
254     { z_ = z; }
255 
intensitylazperf::las::point14256     uint16_t intensity() const
257     { return intensity_; }
setIntensitylazperf::las::point14258     void setIntensity(uint16_t intensity)
259     { intensity_ = intensity; }
260 
returnslazperf::las::point14261     uint8_t returns() const
262     { return returns_; }
setReturnslazperf::las::point14263     void setReturns(uint8_t returns)
264     { returns_ = returns; }
265 
returnNumlazperf::las::point14266     int returnNum() const
267     { return returns_ & 0xF; }
setReturnNumlazperf::las::point14268     void setReturnNum(int rn)
269     { returns_ = rn | (returns_ & 0xF0); }
270 
numReturnslazperf::las::point14271     uint8_t numReturns() const
272     { return returns_ >> 4; }
setNumReturnslazperf::las::point14273     void setNumReturns(int nr)
274     { returns_ = (nr << 4) | (returns_ & 0xF); }
275 
flagslazperf::las::point14276     uint8_t flags() const
277     { return flags_; }
setFlagslazperf::las::point14278     void setFlags(uint8_t flags)
279     { flags_ = flags; }
280 
classFlagslazperf::las::point14281     int classFlags() const
282     { return (flags_ & 0xF); }
setClassFlagslazperf::las::point14283     void setClassFlags(int flags)
284     { flags_ = flags | (flags_ & 0xF0); }
285 
scannerChannellazperf::las::point14286     int scannerChannel() const
287     { return (flags_ >> 4) & 0x03; }
setScannerChannellazperf::las::point14288     void setScannerChannel(int c)
289     { flags_ = (c << 4) | (flags_ & ~0x30); }
290 
scanDirFlaglazperf::las::point14291     int scanDirFlag() const
292     { return ((flags_ >> 6) & 1); }
setScanDirFlaglazperf::las::point14293     void setScanDirFlag(int flag)
294     { flags_ = (flag << 6) | (flags_ & 0xBF); }
295 
eofFlaglazperf::las::point14296     int eofFlag() const
297     { return ((flags_ >> 7) & 1); }
setEofFlaglazperf::las::point14298     void setEofFlag(int flag)
299     { flags_ = (flag << 7) | (flags_ & 0x7F); }
300 
classificationlazperf::las::point14301     uint8_t classification() const
302     { return classification_; }
setClassificationlazperf::las::point14303     void setClassification(uint8_t classification)
304     { classification_ = classification; }
305 
userDatalazperf::las::point14306     uint8_t userData() const
307     { return user_data_; }
setUserDatalazperf::las::point14308     void setUserData(uint8_t user_data)
309     { user_data_ = user_data; }
310 
scanAnglelazperf::las::point14311     int16_t scanAngle() const
312     { return scan_angle_; }
setScanAnglelazperf::las::point14313     void setScanAngle(int16_t scan_angle)
314     { scan_angle_ = scan_angle; }
315 
pointSourceIDlazperf::las::point14316     uint16_t pointSourceID() const
317     { return point_source_ID_; }
setPointSourceIDlazperf::las::point14318     void setPointSourceID(uint16_t point_source_ID)
319     { point_source_ID_ = point_source_ID; }
320 
gpsTimelazperf::las::point14321     double gpsTime() const
322     { return gpstime_; }
setGpsTimelazperf::las::point14323     void setGpsTime(double gpstime)
324     { gpstime_ = gpstime; }
325 
unpacklazperf::las::point14326     void unpack(const char *in)
327     {
328         setX(utils::unpack<int32_t>(in));               in += sizeof(int32_t);
329         setY(utils::unpack<int32_t>(in));               in += sizeof(int32_t);
330         setZ(utils::unpack<int32_t>(in));               in += sizeof(int32_t);
331         setIntensity(utils::unpack<uint16_t>(in));      in += sizeof(uint16_t);
332         setReturns(*in++);
333         setFlags(*in++);
334         setClassification(*in++);
335         setUserData(*in++);
336         setScanAngle(utils::unpack<int16_t>(in));       in += sizeof(int16_t);
337         setPointSourceID(utils::unpack<uint16_t>(in));  in += sizeof(uint16_t);
338         setGpsTime(utils::unpack<double>(in));
339     }
340 };
341 #pragma pack(pop)
342 } // namespace las
343 } // namespace lazperf
344 
345 #include "detail/field_byte10.hpp"
346 #include "detail/field_point10.hpp"
347 #include "detail/field_point14.hpp"
348 #include "detail/field_gpstime10.hpp"
349 #include "detail/field_rgb10.hpp"
350 #include "detail/field_rgb14.hpp"
351 #include "detail/field_nir14.hpp"
352 #include "detail/field_byte14.hpp"
353 
354