1 /* 2 =============================================================================== 3 4 FILE: field_xyz.hpp 5 6 CONTENTS: 7 XYZ fields encoder 8 9 10 PROGRAMMERS: 11 12 martin.isenburg@rapidlasso.com - http://rapidlasso.com 13 uday.karan@gmail.com - Hobu, Inc. 14 15 COPYRIGHT: 16 17 (c) 2007-2014, martin isenburg, rapidlasso - tools to catch reality 18 (c) 2014, Uday Verma, Hobu, Inc. 19 20 This is free software; you can redistribute and/or modify it under the 21 terms of the GNU Lesser General Licence as published by the Free Software 22 Foundation. See the COPYING file for more information. 23 24 This software is distributed WITHOUT ANY WARRANTY and without even the 25 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 26 27 CHANGE HISTORY: 28 29 =============================================================================== 30 */ 31 32 #ifndef __las_hpp__ 33 #error Cannot directly include this file, this is a part of las.hpp 34 #endif 35 36 namespace laszip { 37 namespace formats { 38 // Teach packers how to pack unpack the xyz struct 39 // 40 template<> 41 struct packers<las::xyz> { unpacklaszip::formats::packers42 inline static las::xyz unpack(const char *in) { 43 // blind casting will cause problems for ARM and Emscripten targets 44 // 45 las::xyz p; 46 47 p.x = packers<int>::unpack(in); in += sizeof(int); 48 p.y = packers<int>::unpack(in); in += sizeof(int); 49 p.z = packers<int>::unpack(in); 50 51 return p; 52 } 53 packlaszip::formats::packers54 inline static void pack(const las::xyz& p, char *buffer) { 55 packers<int>::pack(p.x, buffer); buffer += sizeof(int); 56 packers<int>::pack(p.y, buffer); buffer += sizeof(int); 57 packers<int>::pack(p.z, buffer); 58 } 59 }; 60 61 // specialize field to compress point 10 62 // 63 template<> 64 struct field<las::xyz> { 65 typedef las::xyz type; 66 fieldlaszip::formats::field67 field() : compressor_inited_(false), decompressors_inited_(false) { } 68 69 template< 70 typename TEncoder 71 > compressWithlaszip::formats::field72 inline const char *compressWith(TEncoder& enc, const char *buf) 73 { 74 if (!compressor_inited_) { 75 compressors_.init(); 76 compressor_inited_ = true; 77 } 78 79 las::xyz this_val = packers<las::xyz>::unpack(buf); 80 if (!common_.have_last_) { 81 // don't have the first data yet, just push it to our have last stuff and move on 82 common_.have_last_ = true; 83 common_.last_ = this_val; 84 85 enc.getOutStream().putBytes((const unsigned char*)buf, 86 sizeof(las::xyz)); 87 88 // we are done here 89 return buf + sizeof(las::xyz); 90 } 91 92 unsigned int k_bits; 93 int median, diff; 94 95 // compress x coordinate 96 median = common_.last_x_diff_median5.get(); 97 diff = this_val.x - common_.last_.x; 98 compressors_.ic_dx.compress(enc, median, diff, 0); 99 common_.last_x_diff_median5.add(diff); 100 101 // compress y coordinate 102 k_bits = compressors_.ic_dx.getK(); 103 median = common_.last_y_diff_median5.get(); 104 diff = this_val.y - common_.last_.y; 105 compressors_.ic_dy.compress(enc, median, diff, ( k_bits < 20 ? U32_ZERO_BIT_0(k_bits) : 20 )); 106 common_.last_y_diff_median5.add(diff); 107 108 // compress z coordinate 109 k_bits = (compressors_.ic_dx.getK() + compressors_.ic_dy.getK()) / 2; 110 compressors_.ic_z.compress(enc, common_.last_height, this_val.z, (k_bits < 18 ? U32_ZERO_BIT_0(k_bits) : 18)); 111 common_.last_height = this_val.z; 112 113 common_.last_ = this_val; 114 return buf + sizeof(las::xyz); 115 } 116 117 template< 118 typename TDecoder 119 > decompressWithlaszip::formats::field120 inline char *decompressWith(TDecoder& dec, char *buf) 121 { 122 if (!decompressors_inited_) { 123 decompressors_.init(); 124 decompressors_inited_ = true; 125 } 126 127 if (!common_.have_last_) { 128 // don't have the first data yet, read the whole point out of the stream 129 common_.have_last_ = true; 130 131 dec.getInStream().getBytes((unsigned char*)buf, 132 sizeof(las::xyz)); 133 134 // decode this value 135 common_.last_ = packers<las::xyz>::unpack(buf); 136 137 // we are done here 138 return buf + sizeof(las::xyz); 139 } 140 141 unsigned int k_bits; 142 int median, diff; 143 144 // decompress x coordinate 145 median = common_.last_x_diff_median5.get(); 146 147 diff = decompressors_.ic_dx.decompress(dec, median, 0); 148 common_.last_.x += diff; 149 common_.last_x_diff_median5.add(diff); 150 151 // decompress y coordinate 152 median = common_.last_y_diff_median5.get(); 153 k_bits = decompressors_.ic_dx.getK(); 154 diff = decompressors_.ic_dy.decompress(dec, median, ( k_bits < 20 ? U32_ZERO_BIT_0(k_bits) : 20 )); 155 common_.last_.y += diff; 156 common_.last_y_diff_median5.add(diff); 157 158 // decompress z coordinate 159 k_bits = (decompressors_.ic_dx.getK() + decompressors_.ic_dy.getK()) / 2; 160 common_.last_.z = decompressors_.ic_z.decompress(dec, common_.last_height, (k_bits < 18 ? U32_ZERO_BIT_0(k_bits) : 18)); 161 common_.last_height = common_.last_.z; 162 163 packers<las::xyz>::pack(common_.last_, buf); 164 return buf + sizeof(las::xyz); 165 } 166 167 // All the things we need to compress a point, group them into structs 168 // so we don't have too many names flying around 169 170 // Common parts for both a compressor and decompressor go here 171 struct __common { 172 type last_; 173 174 utils::streaming_median<int> last_x_diff_median5; 175 utils::streaming_median<int> last_y_diff_median5; 176 177 int last_height; 178 bool have_last_; 179 __commonlaszip::formats::field::__common180 __common() : 181 last_height(0), 182 have_last_(false) { 183 } 184 ~__commonlaszip::formats::field::__common185 ~__common() { 186 } 187 } common_; 188 189 // These compressors are specific to a compressor usage, so we keep them separate here 190 struct __compressors { 191 compressors::integer ic_dx; 192 compressors::integer ic_dy; 193 compressors::integer ic_z; 194 __compressorslaszip::formats::field::__compressors195 __compressors() : 196 ic_dx(32, 2), 197 ic_dy(32, 22), 198 ic_z(32, 20) { } 199 initlaszip::formats::field::__compressors200 void init() { 201 ic_dx.init(); 202 ic_dy.init(); 203 ic_z.init(); 204 } 205 } compressors_; 206 207 struct __decompressors { 208 decompressors::integer ic_dx; 209 decompressors::integer ic_dy; 210 decompressors::integer ic_z; 211 __decompressorslaszip::formats::field::__decompressors212 __decompressors() : 213 ic_dx(32, 2), 214 ic_dy(32, 22), 215 ic_z(32, 20) { } 216 initlaszip::formats::field::__decompressors217 void init() { 218 ic_dx.init(); 219 ic_dy.init(); 220 ic_z.init(); 221 } 222 } decompressors_; 223 224 bool compressor_inited_; 225 bool decompressors_inited_; 226 }; 227 } 228 } 229