~ubuntu-branches/ubuntu/trusty/liblas/trusty-proposed

« back to all changes in this revision

Viewing changes to apps/ts2las.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2014-01-05 17:00:29 UTC
  • mfrom: (7.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20140105170029-ddtp0j63x5jvck2u
Tags: 1.7.0+dfsg-2
Fixed missing linking of system boost component.
(closes: #733282)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// $Id$
 
2
//
 
3
// ts2las translates TerraSolid .bin file to ASPRS LAS file.
 
4
//
 
5
// TerraSolid format: http://cdn.terrasolid.fi/tscan.pdf
 
6
//
 
7
// (C) Copyright Howard Butler 2009, hobu.inc@gmail.com
 
8
//
 
9
// Distributed under the BSD License
 
10
// (See accompanying file LICENSE.txt or copy at
 
11
// http://www.opensource.org/licenses/bsd-license.php)
 
12
//
 
13
#include "ts2las.hpp"
 
14
#include "laskernel.hpp"
 
15
 
 
16
// boost
 
17
#ifdef _MSC_VER
 
18
#pragma warning(push)
 
19
#pragma warning(disable : 4512)
 
20
#endif
 
21
 
 
22
#include <boost/program_options.hpp>
 
23
 
 
24
#ifdef _MSC_VER
 
25
#pragma warning(pop)
 
26
#endif
 
27
 
 
28
namespace po = boost::program_options;
 
29
 
 
30
#include <fstream>
 
31
#include <iostream>
 
32
#include <string>
 
33
 
 
34
using namespace liblas;
 
35
 
 
36
// std::istream* OpenInput(std::string filename) 
 
37
// {
 
38
//     std::ios::openmode const mode = std::ios::in | std::ios::binary;
 
39
//     std::istream* istrm;
 
40
//     if (compare_no_case(filename.c_str(),"STDIN",5) == 0)
 
41
//     {
 
42
//         istrm = &std::cin;
 
43
//     }
 
44
//     else 
 
45
//     {
 
46
//         istrm = new std::ifstream(filename.c_str(), mode);
 
47
//     }
 
48
//     
 
49
//     if (!istrm->good())
 
50
//     {
 
51
//         delete istrm;
 
52
//         throw std::runtime_error("Reading stream was not able to be created");
 
53
//         exit(1);
 
54
//     }
 
55
//     return istrm;
 
56
// }
 
57
// 
 
58
// std::ostream* OpenOutput(std::string filename)
 
59
// {
 
60
//     std::ostream* ostrm;
 
61
//     std::ios::openmode m;
 
62
//     m = std::ios::out | std::ios::binary | std::ios::ate;
 
63
//             
 
64
//     if (compare_no_case(filename.c_str(),"STOUT",5) == 0)
 
65
//     {
 
66
//         ostrm = &std::cout;
 
67
//     }
 
68
//     else 
 
69
//     {
 
70
//         ostrm = new std::ofstream(filename.c_str(), m);
 
71
//     }
 
72
// 
 
73
//     
 
74
//     if (!ostrm->good())
 
75
//     {
 
76
//         delete ostrm;
 
77
//         throw std::runtime_error("Writing stream was not able to be created");
 
78
//         exit(1);
 
79
//     }
 
80
//     
 
81
//     return ostrm;
 
82
// }
 
83
 
 
84
liblas::Header CreateHeader(ScanHdr* hdr, bool verbose)
 
85
{
 
86
    liblas::Header header;
 
87
    
 
88
    // Checks for time and color values
 
89
    liblas::PointFormatName format = liblas::ePointFormat0;
 
90
    
 
91
    if (hdr->Time) {
 
92
        if (hdr->Color) {
 
93
            format = liblas::ePointFormat3;
 
94
        } else {
 
95
            format = liblas::ePointFormat1;
 
96
        }
 
97
    } else if (hdr->Color) {
 
98
        format = liblas::ePointFormat2;
 
99
    } 
 
100
    header.SetVersionMinor(2);
 
101
    header.SetDataFormatId(format);
 
102
 
 
103
    double scale = 1.0/(double)hdr->Units;
 
104
    header.SetScale(scale, scale, scale);
 
105
    header.SetOffset(hdr->OrgX*scale, hdr->OrgY*scale, hdr->OrgZ*scale);
 
106
    header.SetPointRecordsCount(hdr->PntCnt);
 
107
    
 
108
    if (verbose)
 
109
    {
 
110
        std::cout << "The file says there should be " << hdr->PntCnt << " points" << std::endl;
 
111
        std::cout << "units: " << hdr->Units << std::endl;
 
112
        std::cout << "format: " << format << std::endl;
 
113
        std::cout << "scale: " << scale << std::endl;
 
114
        std::cout << "x origin: " << hdr->OrgX << std::endl;
 
115
        std::cout << "y origin: " << hdr->OrgY << std::endl;
 
116
        std::cout << "z origin: " << hdr->OrgZ << std::endl;
 
117
 
 
118
        boost::uint32_t precision = GetStreamPrecision(scale);
 
119
 
 
120
        std::cout.setf(std::ios_base::fixed, std::ios_base::floatfield);
 
121
        std::cout.precision(precision);
 
122
        std::cout << "offset x: " << header.GetOffsetX() << std::endl;
 
123
        std::cout << "offset y: " << header.GetOffsetY() << std::endl;
 
124
        std::cout << "offset z: " << header.GetOffsetZ() << std::endl;
 
125
        
 
126
    }
 
127
 
 
128
 
 
129
 
 
130
    return header;
 
131
}
 
132
 
 
133
bool ReadHeader(ScanHdr* hdr, std::istream& istrm)
 
134
{
 
135
    try
 
136
    {
 
137
        liblas::detail::read_n(*hdr, istrm, sizeof(ScanHdr));
 
138
        
 
139
        if (hdr->Tunniste != 970401) return false;
 
140
        if (memcmp(hdr->Magic,"CXYZ",4)) return false;
 
141
        
 
142
        int version = hdr->HdrVersion;
 
143
        if (version == 970404) return true;
 
144
        if (version == 20010129) return true;
 
145
        if (version == 20010712) return true;
 
146
        if (version == 20020715) return true;
 
147
        if (( version > 20020715) && (version < 20051231)) return true;
 
148
        return false;
 
149
    }
 
150
    catch (std::exception const&)
 
151
    {
 
152
        return false;
 
153
    }    
 
154
 
 
155
}
 
156
 
 
157
bool WritePoints(liblas::Writer& writer, std::istream& strm, ScanHdr* hdr, bool verbose) 
 
158
{
 
159
    ScanPnt* point = new ScanPnt;
 
160
    ScanRow* row = new ScanRow;
 
161
    boost::uint32_t i = 0;
 
162
    
 
163
    for (std::size_t t = 0; t < static_cast<std::size_t>(hdr->PntCnt); t++)
 
164
    {
 
165
 
 
166
        if (hdr->HdrVersion == 20020715) {
 
167
            try 
 
168
            {
 
169
                liblas::detail::read_n(*point, strm, sizeof(ScanPnt));
 
170
            }
 
171
            catch (std::out_of_range&) // we reached the end of the file
 
172
            {
 
173
                return true;
 
174
                // break;
 
175
            }            
 
176
        } else{
 
177
            try 
 
178
            {
 
179
                liblas::detail::read_n(*row, strm, sizeof(ScanRow));
 
180
            }
 
181
            catch (std::out_of_range&) // we reached the end of the file
 
182
            {
 
183
                return true;
 
184
                // break;
 
185
            }   
 
186
            
 
187
            point->Pnt.x = row->x;
 
188
            point->Pnt.y = row->y;
 
189
            point->Pnt.z = row->z;
 
190
            point->Code = row->Code;
 
191
            point->Line = row->Line;
 
192
            point->Intensity = row->EchoInt & 0x3FFF;
 
193
            point->Echo = (row->EchoInt >> 14);
 
194
        }
 
195
        Point p;
 
196
        
 
197
        p.SetRawX(point->Pnt.x);
 
198
        p.SetRawY(point->Pnt.y);
 
199
        p.SetRawZ(point->Pnt.z);
 
200
 
 
201
        // std::cout << "read x: " << point->Pnt.x << " y: "<< point->Pnt.y << " z: " <<point->Pnt.z<< std::endl;
 
202
        // std::cout << "wrote x: " << p.GetX() << " y: "<< p.GetY() << " z: " <<p.GetZ()<< std::endl;
 
203
        // std::cout << "Code: " << point->Code << " Intensity: "<< point->Intensity << std::endl;
 
204
        p.SetClassification(point->Code);
 
205
        p.SetIntensity(point->Intensity);
 
206
        if (hdr->Time) {
 
207
            boost::uint32_t t = 0xFFFFFFFF;
 
208
            liblas::detail::read_n(t, strm, sizeof(t));
 
209
 
 
210
            // Time stamps are assumed to be GPS week seconds. The 
 
211
            // storage format is a 32 bit unsigned integer where 
 
212
            // each integer step is 0.0002 seconds.
 
213
 
 
214
            p.SetTime(t*0.0002);
 
215
        }
 
216
        if (hdr->Color) {
 
217
            boost::uint8_t r, g, b, a = 0;
 
218
            liblas::Color color;
 
219
            liblas::detail::read_n(r, strm, sizeof(r));
 
220
            liblas::detail::read_n(b, strm, sizeof(b));
 
221
            liblas::detail::read_n(g, strm, sizeof(g));
 
222
            
 
223
            // TS .bin says to read 4 bytes here for some reason.  Maybe 
 
224
            // this is an alpha value or something
 
225
            liblas::detail::read_n(a, strm, sizeof(a));
 
226
            
 
227
            color.SetGreen(g);
 
228
            color.SetBlue(b);
 
229
            color.SetRed(r);
 
230
            p.SetColor(color);
 
231
        }
 
232
        
 
233
        // Set return number
 
234
        /* 
 
235
            TerraScan uses two bits for storing echo information. The possible values are: 
 
236
            0 Only echo 
 
237
            1 First of many echo 
 
238
            2 Intermediate echo 
 
239
            3 Last of many echo
 
240
        */
 
241
        if (point->Echo == 0) { 
 
242
            p.SetNumberOfReturns(1);
 
243
            p.SetReturnNumber(1);
 
244
        } else if (point->Echo == 1) {
 
245
            p.SetReturnNumber(1);
 
246
        } else if (point->Echo == 3) {
 
247
            p.SetReturnNumber(2);
 
248
            p.SetNumberOfReturns(2);
 
249
        } else {
 
250
            // I don't know what the hell to do here without cumulating
 
251
            // through all of the points.  Why wouldn't you store the return 
 
252
            // number?!
 
253
            p.SetReturnNumber(2);
 
254
            p.SetNumberOfReturns(3);
 
255
        }
 
256
 
 
257
        try {
 
258
            writer.WritePoint(p);
 
259
        } catch (std::exception) 
 
260
        {
 
261
            std::cerr << "Point writing failed!" << std::endl; 
 
262
        }
 
263
        i++;
 
264
        if (verbose)
 
265
            term_progress(std::cout, (i + 1) / static_cast<double>(hdr->PntCnt));
 
266
     
 
267
    }
 
268
 
 
269
    delete point;
 
270
    delete row;
 
271
    return true;    
 
272
 
 
273
}
 
274
 
 
275
void OutputHelp( std::ostream & oss, po::options_description const& options)
 
276
{
 
277
    oss << "--------------------------------------------------------------------\n";
 
278
    oss << "    ts2las (" << GetFullVersion() << ")\n";
 
279
    oss << "--------------------------------------------------------------------\n";
 
280
 
 
281
    oss << options;
 
282
 
 
283
    oss <<"\nFor more information, see the full documentation for ts2las at:\n";
 
284
 
 
285
    oss << " http://liblas.org/utilities/ts2las.html\n";
 
286
    oss << "----------------------------------------------------------\n";
 
287
 
 
288
}
 
289
 
 
290
int main(int argc, char* argv[])
 
291
{
 
292
    std::string input;
 
293
    std::string output;
 
294
    bool verbose = false;
 
295
    std::vector<liblas::FilterPtr> filters;
 
296
    
 
297
    po::options_description ts2las_options("ts2las options");
 
298
    po::options_description filtering_options = GetFilteringOptions();
 
299
    po::positional_options_description p;
 
300
    p.add("input", 1);
 
301
    p.add("output", 1);
 
302
 
 
303
    ts2las_options.add_options()
 
304
        ("help,h", "Produce this help message")
 
305
        ("input,i", po::value< std::string >(&input), "input TerraSolid .bin file")
 
306
        ("output,o", po::value< std::string >(&output)->default_value(""), "The output .las file (defaults to input filename + .las)")
 
307
        ("verbose,v", po::value<bool>(&verbose)->zero_tokens(), "Verbose message output")
 
308
 
 
309
    ;
 
310
    
 
311
    po::variables_map vm;        
 
312
    po::options_description options;
 
313
    options.add(ts2las_options).add(filtering_options);
 
314
    po::store(po::command_line_parser(argc, argv).
 
315
      options(options).positional(p).run(), vm);
 
316
;
 
317
 
 
318
    po::notify(vm);
 
319
 
 
320
    if (vm.count("help")) 
 
321
    {
 
322
        OutputHelp(std::cout, options);
 
323
        return 1;
 
324
    }
 
325
    
 
326
    if (input.empty())
 
327
    {
 
328
        std::cerr << "No input TerraSolid .bin file was specfied!" << std::endl;
 
329
        OutputHelp(std::cout, options);
 
330
        return 1;
 
331
    }
 
332
    
 
333
    
 
334
    filters = GetFilters(vm, verbose);
 
335
 
 
336
    if (verbose)
 
337
        std::cout << "input: " << input<<  " output: " <<output<<std::endl;
 
338
    
 
339
    ScanHdr* hdr = new ScanHdr;
 
340
 
 
341
    std::ifstream istrm;
 
342
    bool opened = liblas::Open(istrm, input);
 
343
    if (!opened)
 
344
    {
 
345
        std::cerr << "Could not open file '" << input << "' to read TerraSolid .bin data! " << std::endl;
 
346
        return 1;
 
347
    }
 
348
    
 
349
    std::ofstream ostrm;
 
350
    bool created = liblas::Create(ostrm, output);
 
351
    if (!created)
 
352
    {
 
353
        std::cerr << "Could not create file " << output << " to write LAS data!" << std::endl;;
 
354
        return 1;
 
355
    }
 
356
    
 
357
    bool success;
 
358
    success = ReadHeader(hdr, istrm);
 
359
    if (!success) 
 
360
    {
 
361
        std::cerr<<"Unable to read " << input << "to read file!" << std::endl; 
 
362
        return 1;
 
363
    }
 
364
    
 
365
    // std::cout << "stream position is: " << istrm->tellg() << std::endl;
 
366
    liblas::Header header = CreateHeader(hdr, verbose);
 
367
    liblas::Writer writer(ostrm, header);
 
368
    
 
369
    writer.SetFilters(filters);
 
370
    
 
371
    success = WritePoints(writer, istrm, hdr, verbose);
 
372
 
 
373
    if (verbose)
 
374
    {
 
375
        std::cout << "Successfully wrote " << header.GetPointRecordsCount() 
 
376
                  <<" points to " << output << std::endl;
 
377
    }
 
378
    return 0;
 
379
}
 
380