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

« back to all changes in this revision

Viewing changes to apps/las2txt.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
/***************************************************************************
 
2
 *
 
3
 * Project: libLAS -- C/C++ read/write library for LAS LIDAR data
 
4
 * Purpose: LAS translation to ASCII text with optional configuration
 
5
 * Author:  Martin Isenburg isenburg@cs.unc.edu 
 
6
 * Author:  Howard Butler, hobu.inc at gmail.com
 
7
 ***************************************************************************
 
8
 * Copyright (c) 2010, Howard Butler, hobu.inc at gmail.com 
 
9
 *
 
10
 * See LICENSE.txt in this source distribution for more information.
 
11
 **************************************************************************/
 
12
 
 
13
#include <liblas/liblas.hpp>
 
14
#include "laskernel.hpp"
 
15
#include <liblas/utility.hpp>
 
16
 
 
17
#include <boost/cstdint.hpp>
 
18
#include <boost/foreach.hpp>
 
19
#include <boost/array.hpp>
 
20
#include <boost/lexical_cast.hpp>
 
21
 
 
22
#include <string>
 
23
 
 
24
using namespace liblas;
 
25
using namespace std;
 
26
 
 
27
#ifdef _WIN32
 
28
#define compare_no_case(a,b,n)  _strnicmp( (a), (b), (n) )
 
29
#else
 
30
#define compare_no_case(a,b,n)  strncasecmp( (a), (b), (n) )
 
31
#endif
 
32
 
 
33
 
 
34
std::string GetLabels(std::string const& parse_string,
 
35
                    std::string const& delimiter)
 
36
{
 
37
    std::ostringstream output;
 
38
    
 
39
    boost::uint32_t i = 0;
 
40
    for (;;)
 
41
    {
 
42
        
 
43
        switch (parse_string[i])
 
44
        {
 
45
        /* // the x coordinate */      
 
46
        case 'x':
 
47
            output << "\"X\"";
 
48
            break;
 
49
        /* // the y coordinate */
 
50
        case 'y':
 
51
            output << "\"Y\"";
 
52
            break;
 
53
        /* // the z coordinate */ 
 
54
        case 'z':
 
55
            output << "\"Z\"";
 
56
            break;
 
57
        /* // the raw x coordinate */      
 
58
        case 'X':
 
59
            output << "\"Raw X\"";
 
60
            break;
 
61
        /* // the raw y coordinate */
 
62
        case 'Y':
 
63
            output << "\"Raw Y\"";
 
64
            break;
 
65
        /* // the raw z coordinate */ 
 
66
        case 'Z':
 
67
            output << "\"Raw Z\"";
 
68
            break;
 
69
        /* // the gps-time */
 
70
        case 't': 
 
71
            output << "\"Time\"";
 
72
            break;
 
73
        /* // the intensity */
 
74
        case 'i':
 
75
            output << "\"Intensity\"";
 
76
            break;
 
77
        /* the scan angle */
 
78
        case 'a':
 
79
            output << "\"Scan Angle\"";
 
80
            break;
 
81
        /* the number of the return */
 
82
        case 'r': 
 
83
            output << "\"Return Number\"";
 
84
            break;
 
85
        /* the classification */
 
86
        case 'c':
 
87
            output << "\"Classification\"";
 
88
            break;
 
89
        /* the classification name */
 
90
        case 'C':
 
91
            output << "\"Classification Name\"";
 
92
            break;
 
93
        /* the user data */
 
94
        case 'u': 
 
95
            output << "\"User Data\"";
 
96
            break;
 
97
        /* the number of returns of given pulse */
 
98
        case 'n':
 
99
            output << "\"Number of Returns\"";
 
100
            break;
 
101
        /* the red channel color */
 
102
        case 'R':
 
103
            output << "\"Red\"";
 
104
            break;            
 
105
        /* the green channel color */
 
106
        case 'G': 
 
107
            output << "\"Green\"";
 
108
            break;            
 
109
        /* the blue channel color */
 
110
        case 'B': 
 
111
            output << "\"Blue\"";
 
112
            break;            
 
113
        case 'M':
 
114
            output << "\"ID\"";
 
115
            break;
 
116
        case 'p':
 
117
            output << "\"Point Source ID\"";
 
118
            break;
 
119
        /* the edge of flight line flag */
 
120
        case 'e': 
 
121
            output << "\"Flight Line Edge\"";
 
122
            break;
 
123
        /* the direction of scan flag */
 
124
        case 'd': 
 
125
            output << "\"Scan Direction\"";
 
126
            break;
 
127
        }
 
128
 
 
129
        i++;
 
130
 
 
131
        if (parse_string[i])
 
132
        {
 
133
            output << delimiter;
 
134
        }
 
135
        else
 
136
        {
 
137
            output << std::endl;
 
138
            break;
 
139
        }
 
140
 
 
141
    }
 
142
    return output.str();
 
143
}
 
144
 
 
145
std::string GetPointString( std::string const& parse_string,
 
146
                            std::string const& delimiter,
 
147
                            liblas::Point const& p, 
 
148
                            boost::array<boost::uint32_t, 4> precisions, 
 
149
                            boost::uint32_t index)
 
150
{
 
151
    
 
152
    std::ostringstream output;
 
153
 
 
154
    boost::uint32_t i = 0;
 
155
    liblas::Color const& c = p.GetColor();
 
156
    for (;;)
 
157
    {
 
158
        
 
159
        switch (parse_string[i])
 
160
        {
 
161
        /* // the x coordinate */      
 
162
        case 'x':
 
163
            output.setf(std::ios_base::fixed, std::ios_base::floatfield);
 
164
            output.precision(precisions[0]); //x precision
 
165
            output << p.GetX();
 
166
            output.unsetf(std::ios_base::fixed);
 
167
            output.unsetf(std::ios_base::floatfield);
 
168
            break;
 
169
        /* // the y coordinate */
 
170
        case 'y':
 
171
            output.setf(std::ios_base::fixed, std::ios_base::floatfield);
 
172
            output.precision(precisions[1]); //y precision
 
173
            output << p.GetY();
 
174
            output.unsetf(std::ios_base::fixed);
 
175
            output.unsetf(std::ios_base::floatfield);
 
176
            break;
 
177
        /* // the z coordinate */ 
 
178
        case 'z':
 
179
            output.setf(std::ios_base::fixed, std::ios_base::floatfield);
 
180
            output.precision(precisions[2]); //z precision
 
181
            output << p.GetZ();
 
182
            output.unsetf(std::ios_base::fixed);
 
183
            output.unsetf(std::ios_base::floatfield);
 
184
            break;
 
185
        /* // the raw x coordinate */      
 
186
        case 'X':
 
187
            output << p.GetRawX();
 
188
            break;
 
189
        /* // the raw y coordinate */
 
190
        case 'Y':
 
191
            output << p.GetRawY();
 
192
            break;
 
193
        /* // the raw z coordinate */ 
 
194
        case 'Z':
 
195
            output << p.GetRawZ();
 
196
            break;
 
197
        /* // the gps-time */
 
198
        case 't': 
 
199
            output.setf(std::ios_base::fixed, std::ios_base::floatfield);
 
200
            output.precision(precisions[3]); //t precision
 
201
            output << p.GetTime();
 
202
            output.unsetf(std::ios_base::fixed);
 
203
            output.unsetf(std::ios_base::floatfield);
 
204
            break;
 
205
        /* // the intensity */
 
206
        case 'i':
 
207
            output << p.GetIntensity();
 
208
            break;
 
209
        /* the scan angle */
 
210
        case 'a':
 
211
            output << (int)p.GetScanAngleRank();
 
212
            break;
 
213
        /* the number of the return */
 
214
        case 'r': 
 
215
            output << p.GetReturnNumber();
 
216
            break;
 
217
        /* the classification */
 
218
        case 'c':
 
219
            output << static_cast<boost::uint32_t>(p.GetClassification().GetClass());
 
220
            break;
 
221
        /* the classification name */
 
222
        case 'C':
 
223
            output << p.GetClassification().GetClassName();
 
224
            break;
 
225
        /* the user data */
 
226
        case 'u': 
 
227
            // output.setf( std::ios_base::hex, std::ios_base::basefield );
 
228
            // output.setf( std::ios::showbase);
 
229
            output << (int)p.GetUserData();
 
230
            // output.unsetf(std::ios_base::hex);
 
231
            // output.unsetf(std::ios_base::basefield);
 
232
            // output.unsetf( std::ios::showbase);
 
233
            break;
 
234
        /* the number of returns of given pulse */
 
235
        case 'n':
 
236
            output << p.GetNumberOfReturns();
 
237
            break;
 
238
        /* the red channel color */
 
239
        case 'R':
 
240
            output << c.GetRed();
 
241
            break;            
 
242
        /* the green channel color */
 
243
        case 'G': 
 
244
            output << c.GetGreen();
 
245
            break;            
 
246
        /* the blue channel color */
 
247
        case 'B': 
 
248
            output << c.GetBlue();
 
249
            break;            
 
250
        case 'M':
 
251
            output << index;
 
252
            break;
 
253
        case 'p':
 
254
            output << p.GetPointSourceID();
 
255
            break;
 
256
        /* the edge of flight line flag */
 
257
        case 'e': 
 
258
            output << p.GetFlightLineEdge();
 
259
            break;
 
260
        /* the direction of scan flag */
 
261
        case 'd': 
 
262
            output << p.GetScanDirection();
 
263
            break;
 
264
        }
 
265
 
 
266
        i++;
 
267
 
 
268
        if (parse_string[i])
 
269
        {
 
270
            output << delimiter;
 
271
        }
 
272
        else
 
273
        {
 
274
            output << std::endl;
 
275
            break;
 
276
        }
 
277
 
 
278
    }
 
279
 
 
280
    
 
281
    return output.str();
 
282
}
 
283
 
 
284
std::string GetHeader(liblas::Reader& reader)
 
285
{
 
286
    boost::ignore_unused_variable_warning(reader);
 
287
 
 
288
    std::ostringstream oss;
 
289
    
 
290
    return oss.str();
 
291
}
 
292
void write_points(  liblas::Reader& reader,
 
293
                    std::ostream& oss,
 
294
                    std::string const& parse_string,
 
295
                    std::string const& delimiter,
 
296
                    std::vector<liblas::FilterPtr>& filters,
 
297
                    std::vector<liblas::TransformPtr>& transforms,
 
298
                    boost::array<boost::uint32_t, 4> precisions,
 
299
                    bool bPrintLabels,
 
300
                    bool bPrintHeader,
 
301
                    bool verbose)
 
302
{
 
303
 
 
304
    liblas::Summary summary;
 
305
    
 
306
    reader.SetFilters(filters);
 
307
    reader.SetTransforms(transforms);
 
308
 
 
309
 
 
310
    if (verbose)
 
311
    std::cout << "Writing points:" 
 
312
        << "\n - : "
 
313
        << std::endl;
 
314
 
 
315
    //
 
316
    // Translation of points cloud to features set
 
317
    //
 
318
    boost::uint32_t i = 0;
 
319
    boost::uint32_t const size = reader.GetHeader().GetPointRecordsCount();
 
320
    
 
321
    if (bPrintHeader)
 
322
    {
 
323
        oss << GetHeader(reader);
 
324
    }
 
325
    
 
326
    if (bPrintLabels) 
 
327
    {
 
328
        oss << GetLabels(parse_string, delimiter);
 
329
    }
 
330
 
 
331
 
 
332
    while (reader.ReadNextPoint())
 
333
    {
 
334
        liblas::Point const& p = reader.GetPoint();
 
335
        // summary.AddPoint(p); 
 
336
        std::string output = GetPointString(parse_string, delimiter, p, precisions, i);
 
337
        
 
338
        oss << output;
 
339
        if (verbose)
 
340
            term_progress(std::cout, (i + 1) / static_cast<double>(size));
 
341
        i++;
 
342
 
 
343
    }
 
344
    if (verbose)
 
345
        std::cout << std::endl;
 
346
    
 
347
    
 
348
}
 
349
 
 
350
void OutputHelp( std::ostream & oss, po::options_description const& options)
 
351
{
 
352
    oss << "--------------------------------------------------------------------\n";
 
353
    oss << "    las2txt (" << GetFullVersion() << ")\n";
 
354
    oss << "--------------------------------------------------------------------\n";
 
355
 
 
356
    oss << options;
 
357
 
 
358
    oss <<"\nFor more information, see the full documentation for lasinfo at:\n";
 
359
    
 
360
    oss << " http://liblas.org/utilities/las2txt.html\n";
 
361
    oss << "----------------------------------------------------------\n";
 
362
 
 
363
}
 
364
 
 
365
 
 
366
int main(int argc, char* argv[])
 
367
{
 
368
 
 
369
    std::string input;
 
370
    std::string output;
 
371
    std::string parse_string("xyz");
 
372
    std::string delimiter(",");
 
373
    std::ostream* os = NULL;
 
374
    
 
375
    bool verbose = false;
 
376
    bool output_xml = false;
 
377
    bool bPrintLabels = false;
 
378
    bool bPrintHeader = false;
 
379
    bool bUseStdout = false;
 
380
    
 
381
    std::vector<liblas::FilterPtr> filters;
 
382
    std::vector<liblas::TransformPtr> transforms;
 
383
    
 
384
    liblas::Header header;
 
385
    boost::array<boost::uint32_t, 4> precisions;
 
386
    precisions.assign(0);
 
387
    
 
388
const char* parse_description = "The '--parse txyz' flag specifies how to format each"
 
389
                                " each line of the ASCII file. For example, 'txyzia'" 
 
390
    " means that the first number of each line should be the" 
 
391
    " gpstime, the next three numbers should be the x, y, and"
 
392
    " z coordinate, the next number should be the intensity"
 
393
    " and the next number should be the scan angle.\n\n" 
 
394
    " The supported entries are:\n" 
 
395
    "   x - x coordinate as a double\n"
 
396
    "   y - y coordinate as a double\n"
 
397
    "   z - z coordinate as a double\n"
 
398
    "   X - x coordinate as unscaled integer\n"
 
399
    "   Y - y coordinate as unscaled integer\n"
 
400
    "   Z - z coordinate as unscaled integer\n"
 
401
    "   a - scan angle\n"
 
402
    "   i - intensity\n"
 
403
    "   n - number of returns for given pulse\n"
 
404
    "   r - number of this return\n"
 
405
    "   c - classification number\n"
 
406
    "   C - classification name\n"
 
407
    "   u - user data\n"
 
408
    "   p - point source ID\n"
 
409
    "   e - edge of flight line\n"
 
410
    "   d - direction of scan flag\n"
 
411
    "   R - red channel of RGB color\n"
 
412
    "   G - green channel of RGB color\n"
 
413
    "   B - blue channel of RGB color\n"
 
414
    "   M - vertex index number\n"
 
415
    ;
 
416
 
 
417
 
 
418
    try {
 
419
 
 
420
        po::options_description file_options("las2txt options");
 
421
        po::options_description filtering_options = GetFilteringOptions();
 
422
        po::options_description header_options = GetHeaderOptions();
 
423
 
 
424
        po::positional_options_description p;
 
425
        p.add("input", 1);
 
426
        p.add("output", 1);
 
427
        
 
428
        
 
429
        file_options.add_options()
 
430
            ("help,h", "produce help message")
 
431
            ("input,i", po::value< string >(), "input LAS file.")
 
432
            ("output,o", po::value< string >(), "output text file.  Use 'stdout' if you want it written to the standard output stream")
 
433
            ("parse", po::value< string >(&parse_string), parse_description)
 
434
            ("precision", po::value< std::vector<string> >()->multitoken(), "The number of decimal places to use for x,y,z,[t] output.  \n --precision 7 7 3\n --precision 3 3 4 6\nIf you don't specify any precision, las2txt uses the implicit values defined by the header's scale value (and a precision of 8 is used for any time values.)")
 
435
            ("delimiter", po::value< string >(&delimiter), "The character to use for delimiting fields in the output.\n --delimiter \",\"\n --delimiter \"\t\"\n --delimiter \" \"")
 
436
            ("labels", po::value<bool>(&bPrintLabels)->zero_tokens()->implicit_value(true), "Print row of header labels")
 
437
            ("header", po::value<bool>(&bPrintHeader)->zero_tokens()->implicit_value(true), "Print header information")
 
438
 
 
439
            ("verbose,v", po::value<bool>(&verbose)->zero_tokens(), "Verbose message output")
 
440
            ("xml", po::value<bool>(&output_xml)->zero_tokens()->implicit_value(true), "Output as XML -- no formatting given by --parse is respected in this case.")
 
441
            ("stdout", po::value<bool>(&bUseStdout)->zero_tokens()->implicit_value(true), "Output data to stdout")
 
442
 
 
443
        ;
 
444
 
 
445
        po::variables_map vm;
 
446
        po::options_description options;
 
447
        options.add(file_options).add(filtering_options);
 
448
        po::store(po::command_line_parser(argc, argv).
 
449
          options(options).positional(p).run(), vm);
 
450
 
 
451
        po::notify(vm);
 
452
 
 
453
        if (vm.count("help")) 
 
454
        {
 
455
            OutputHelp(std::cout, options);
 
456
            return 1;
 
457
        }
 
458
 
 
459
 
 
460
        if (vm.count("input")) 
 
461
        {
 
462
            input = vm["input"].as< string >();
 
463
            std::ifstream ifs;
 
464
            if (verbose)
 
465
                std::cout << "Opening " << input << " to fetch Header" << std::endl;
 
466
            if (!liblas::Open(ifs, input.c_str()))
 
467
            {
 
468
                std::cerr << "Cannot open " << input << " for read.  Exiting..." << std::endl;
 
469
                return 1;
 
470
            }
 
471
            liblas::ReaderFactory f;
 
472
            liblas::Reader reader = f.CreateWithStream(ifs);
 
473
            header = reader.GetHeader();
 
474
        } else {
 
475
            std::cerr << "Input LAS file not specified!\n";
 
476
            OutputHelp(std::cout, options);
 
477
            return 1;
 
478
        }
 
479
 
 
480
 
 
481
        if (vm.count("output")) 
 
482
        {
 
483
            output = vm["output"].as< string >();
 
484
            
 
485
            std::ios::openmode const mode = std::ios::out | std::ios::binary;
 
486
            if (compare_no_case(output.c_str(),"STDOUT",5) == 0)
 
487
            {
 
488
                os = &std::cout;
 
489
                bUseStdout = true;
 
490
            }
 
491
            else 
 
492
            {
 
493
                os = new std::ofstream(output.c_str(), mode);
 
494
            }
 
495
    
 
496
            if (!os->good())
 
497
            {
 
498
                delete os;
 
499
                std::cerr << "Cannot open " << output << " to write.  Exiting..." << std::endl;
 
500
                return 1;
 
501
            }
 
502
 
 
503
            
 
504
 
 
505
        } else {
 
506
            
 
507
            if (bUseStdout) 
 
508
            {
 
509
                os = &std::cout;
 
510
            } else 
 
511
            {
 
512
                std::cerr << "Output text file not specified!\n";
 
513
                OutputHelp(std::cout, options);
 
514
                return 1;
 
515
            }
 
516
 
 
517
        }
 
518
        filters = GetFilters(vm, verbose);
 
519
 
 
520
        std::ifstream ifs;
 
521
        if (!liblas::Open(ifs, input.c_str()))
 
522
        {
 
523
            std::cerr << "Cannot open " << input << " for read.  Exiting..." << std::endl;
 
524
            return false;
 
525
        }
 
526
 
 
527
        if (vm.count("precision")) 
 
528
        {
 
529
            std::vector<std::string> precision_str = vm["precision"].as< std::vector<std::string> >();
 
530
            if (precision_str.size() > 4) {
 
531
                ostringstream oss;
 
532
                oss << "Too many arguments were given to precision. "
 
533
                    << "--precision x y z [t]  or -- precision header  ";
 
534
                throw std::runtime_error(oss.str());
 
535
            }
 
536
            if (precision_str.size() < 3) {
 
537
                ostringstream oss;
 
538
                oss << "At least three arguments must be given to precision. ";
 
539
                throw std::runtime_error(oss.str());
 
540
            }
 
541
 
 
542
            if (verbose)
 
543
            {
 
544
                ostringstream oss;
 
545
                for (std::vector<std::string>::const_iterator i = precision_str.begin();
 
546
                     i != precision_str.end();
 
547
                     i++) 
 
548
                    {
 
549
                        oss << *i << " ";
 
550
                    }
 
551
                    std::cout << "Setting precisions to: " << oss.str() << std::endl;
 
552
            }        
 
553
 
 
554
            precisions[0] = boost::lexical_cast<boost::uint32_t>(precision_str[0]);
 
555
            precisions[1] = boost::lexical_cast<boost::uint32_t>(precision_str[1]);
 
556
            precisions[2] = boost::lexical_cast<boost::uint32_t>(precision_str[2]);
 
557
            
 
558
            if (precision_str.size() == 4)
 
559
            {
 
560
                precisions[3] = boost::lexical_cast<boost::uint32_t>(precision_str[3]);
 
561
    
 
562
            } else {
 
563
                precisions[3] = 8;
 
564
            }
 
565
        } else {
 
566
 
 
567
            precisions[0] = GetStreamPrecision(header.GetScaleX());
 
568
            precisions[1] = GetStreamPrecision(header.GetScaleY());
 
569
            precisions[2] = GetStreamPrecision(header.GetScaleZ());
 
570
            precisions[3] = 8;
 
571
 
 
572
            ostringstream oss;
 
573
            for (boost::array<boost::uint32_t, 4>::const_iterator i = precisions.begin();
 
574
                 i != precisions.end();
 
575
                 i++) 
 
576
                {
 
577
                    oss << *i << " ";
 
578
                }            
 
579
            if (verbose)
 
580
            {
 
581
                std::cout << "Setting precisions from header to " << oss.str() << std::endl;
 
582
            }
 
583
        }    
 
584
 
 
585
        if (vm.count("delimiter")) 
 
586
        {
 
587
            std::string delim = vm["delimiter"].as< string >();
 
588
            std::string tab("\\t");
 
589
            std::string newline("\\n");
 
590
            if (!delim.compare(tab)) 
 
591
            { 
 
592
                delimiter = "\t"; 
 
593
            } else if (!delim.compare(newline))
 
594
            {
 
595
                delimiter = "\n";
 
596
            }
 
597
            if (verbose)
 
598
            {
 
599
                std::cout << "Using delimiter '" << delim << "'"<< std::endl;
 
600
            } 
 
601
            
 
602
        } 
 
603
 
 
604
        liblas::ReaderFactory f;
 
605
        liblas::Reader reader = f.CreateWithStream(ifs);
 
606
 
 
607
        write_points(  reader,
 
608
                    *os,
 
609
                    parse_string,
 
610
                    delimiter,
 
611
                    filters,
 
612
                    transforms,
 
613
                    precisions,
 
614
                    bPrintLabels,
 
615
                    bPrintHeader,
 
616
                    verbose);
 
617
 
 
618
    if (os != 0 && !bUseStdout)
 
619
        delete os;
 
620
 
 
621
    }
 
622
    catch(std::exception& e) {
 
623
        std::cerr << "error: " << e.what() << "\n";
 
624
        return 1;
 
625
    }
 
626
    catch(...) {
 
627
        std::cerr << "Exception of unknown type!\n";
 
628
    }
 
629
    
 
630
    return 0;
 
631
 
 
632
 
 
633
}
 
634
 
 
635
//las2las2 -i lt_srs_rt.las  -o foo.las -c 1,2 -b 2483590,366208,2484000,366612