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