Branch data Line data Source code
1 : : /*
2 : : ===============================================================================
3 : :
4 : : FILE: factory.hpp
5 : :
6 : : CONTENTS:
7 : : Factory to create dynamic compressors and decompressors
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 : :
32 : : #ifndef __factory_hpp__
33 : : #define __factory_hpp__
34 : :
35 : : #include "formats.hpp"
36 : : #include "excepts.hpp"
37 : : #include "las.hpp"
38 : :
39 : : #include <sstream>
40 : :
41 : : namespace laszip {
42 : : namespace factory {
43 : : struct record_item {
44 : : enum {
45 : : BYTE = 0,
46 : : POINT10 = 6,
47 : : GPSTIME = 7,
48 : : RGB12 = 8
49 : : };
50 : :
51 : : int type, size, version;
52 : 0 : record_item(int t, int s, int v) :
53 : 0 : type(t), size(s), version(v) {}
54 : :
55 : 0 : bool operator == (const record_item& other) const
56 : : {
57 : 0 : return (type == other.type &&
58 : 0 : version == other.version &&
59 : 0 : size == other.size);
60 : : }
61 : :
62 : 0 : bool operator != (const record_item& other) const
63 : : {
64 : 0 : return !(*this == other);
65 : : }
66 : :
67 : 0 : static const record_item& point()
68 : : {
69 : 0 : static record_item item(POINT10, 20, 2);
70 : 0 : return item;
71 : 0 : }
72 : :
73 : 0 : static const record_item& gpstime()
74 : : {
75 : 0 : static record_item item(GPSTIME, 8, 2);
76 : 0 : return item;
77 : 0 : }
78 : :
79 : 0 : static const record_item& rgb()
80 : : {
81 : 0 : static record_item item(RGB12, 6, 2);
82 : 0 : return item;
83 : 0 : }
84 : :
85 : : static const record_item eb(size_t count)
86 : : {
87 : : return record_item(BYTE, count, 2);
88 : : }
89 : : };
90 : :
91 : 0 : struct record_schema {
92 : 0 : record_schema() : records() { }
93 : :
94 : 0 : void push(const record_item& item) {
95 : 0 : records.push_back(item);
96 : 0 : }
97 : :
98 : : // This is backward compatible support. Remove.
99 : : #ifdef _WIN32
100 : : __declspec(deprecated) void push(int t)
101 : : #else
102 : : void push(int t) __attribute__ ((deprecated))
103 : : #endif
104 : : {
105 : : if (t == record_item::POINT10)
106 : : push(record_item::point());
107 : : else if (t == record_item::GPSTIME)
108 : : push(record_item::gpstime());
109 : : else if (t == record_item::RGB12)
110 : : push(record_item::rgb());
111 : : else
112 : : throw unknown_schema_type();
113 : : }
114 : :
115 : : record_schema& operator () (const record_item& i) {
116 : : push(i);
117 : : return *this;
118 : : }
119 : :
120 : : int size_in_bytes() const {
121 : : int sum = 0;
122 : : for (auto i : records)
123 : : sum += i.size;
124 : :
125 : : return sum;
126 : : }
127 : :
128 : 0 : int format() const
129 : : {
130 : 0 : size_t count = records.size();
131 : 0 : if (count == 0)
132 : 0 : return -1;
133 : :
134 : : // Ignore extrabytes record that should be at the end.
135 : 0 : if (extrabytes())
136 : 0 : count--;
137 : :
138 : 0 : if (count == 0 || records[0] != record_item::point())
139 : 0 : return -1;
140 : :
141 : 0 : if (count == 1)
142 : 0 : return 0;
143 : 0 : if (count == 2)
144 : : {
145 : 0 : if (records[1] == record_item::gpstime())
146 : 0 : return 1;
147 : 0 : else if (records[1] == record_item::rgb())
148 : 0 : return 2;
149 : 0 : }
150 : 0 : if (count == 3 && records[1] == record_item::gpstime() &&
151 : 0 : records[2] == record_item::rgb())
152 : 0 : return 3;
153 : 0 : return -1;
154 : 0 : }
155 : :
156 : 0 : size_t extrabytes() const
157 : : {
158 : 0 : if (records.size())
159 : : {
160 : 0 : auto ri = records.rbegin();
161 : 0 : if (ri->type == record_item::BYTE && ri->version == 2)
162 : 0 : return ri->size;
163 : 0 : }
164 : 0 : return 0;
165 : 0 : }
166 : :
167 : : std::vector<record_item> records;
168 : : };
169 : :
170 : :
171 : : template<typename TDecoder>
172 : 0 : formats::dynamic_decompressor::ptr build_decompressor(TDecoder& decoder,
173 : : const record_schema& schema)
174 : : {
175 : : using namespace formats;
176 : :
177 : 0 : int format = schema.format();
178 : 0 : if (format == -1)
179 : 0 : throw unknown_schema_type();
180 : 0 : size_t ebCount = schema.extrabytes();
181 : 0 : if (ebCount)
182 : : {
183 : 0 : auto decompressor = make_dynamic_decompressor(decoder);
184 : 0 : decompressor->template add_field<las::point10>();
185 : 0 : if (format == 1 || format == 3)
186 : 0 : decompressor->template add_field<las::gpstime>();
187 : 0 : if (format == 2 || format == 3)
188 : 0 : decompressor->template add_field<las::rgb>();
189 : 0 : decompressor->add_field(field<las::extrabytes>(ebCount));
190 : 0 : return decompressor;
191 : 0 : }
192 : : else
193 : : {
194 : 0 : switch (format)
195 : : {
196 : : case 0:
197 : 0 : return make_dynamic_decompressor(decoder,
198 : 0 : new formats::record_decompressor<
199 : : field<las::point10>>());
200 : : case 1:
201 : 0 : return make_dynamic_decompressor(decoder,
202 : 0 : new formats::record_decompressor<
203 : : field<las::point10>,
204 : : field<las::gpstime>>());
205 : : case 2:
206 : 0 : return make_dynamic_decompressor(decoder,
207 : 0 : new formats::record_decompressor<
208 : : field<las::point10>,
209 : : field<las::rgb>>());
210 : : case 3:
211 : 0 : return make_dynamic_decompressor(decoder,
212 : 0 : new formats::record_decompressor<
213 : : field<las::point10>,
214 : : field<las::gpstime>,
215 : : field<las::rgb>>());
216 : : }
217 : : }
218 : 0 : return dynamic_decompressor::ptr();
219 : 0 : }
220 : :
221 : : template<typename TEncoder>
222 : : formats::dynamic_compressor::ptr build_compressor(TEncoder& encoder,
223 : : const record_schema& schema)
224 : : {
225 : : using namespace formats;
226 : :
227 : : int format = schema.format();
228 : : if (format == -1)
229 : : throw unknown_schema_type();
230 : : size_t ebCount = schema.extrabytes();
231 : : if (ebCount)
232 : : {
233 : : auto compressor = make_dynamic_compressor(encoder);
234 : : compressor->template add_field<las::point10>();
235 : : if (format == 1 || format == 3)
236 : : compressor->template add_field<las::gpstime>();
237 : : if (format == 2 || format == 3)
238 : : compressor->template add_field<las::rgb>();
239 : : compressor->add_field(field<las::extrabytes>(ebCount));
240 : : return compressor;
241 : : }
242 : : else
243 : : {
244 : : switch (format)
245 : : {
246 : : case 0:
247 : : return make_dynamic_compressor(encoder,
248 : : new formats::record_compressor<
249 : : field<las::point10>>());
250 : : case 1:
251 : : return make_dynamic_compressor(encoder,
252 : : new formats::record_compressor<
253 : : field<las::point10>,
254 : : field<las::gpstime>>());
255 : : case 2:
256 : : return make_dynamic_compressor(encoder,
257 : : new formats::record_compressor<
258 : : field<las::point10>,
259 : : field<las::rgb>>());
260 : : case 3:
261 : : return make_dynamic_compressor(encoder,
262 : : new formats::record_compressor<
263 : : field<las::point10>,
264 : : field<las::gpstime>,
265 : : field<las::rgb>>());
266 : : }
267 : : }
268 : : return dynamic_compressor::ptr();
269 : : }
270 : :
271 : : } // namespace factory
272 : : } // namespace laszip
273 : :
274 : : #endif // __factory_hpp__
|