1
/***************************************************************************
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
10
* See LICENSE.txt in this source distribution for more information.
11
**************************************************************************/
13
#include <liblas/liblas.hpp>
14
#include "laskernel.hpp"
15
#include <liblas/utility.hpp>
17
#include <boost/cstdint.hpp>
18
#include <boost/foreach.hpp>
19
#include <boost/array.hpp>
20
#include <boost/lexical_cast.hpp>
24
using namespace liblas;
28
#define compare_no_case(a,b,n) _strnicmp( (a), (b), (n) )
30
#define compare_no_case(a,b,n) strncasecmp( (a), (b), (n) )
34
std::string GetLabels(std::string const& parse_string,
35
std::string const& delimiter)
37
std::ostringstream output;
39
boost::uint32_t i = 0;
43
switch (parse_string[i])
45
/* // the x coordinate */
49
/* // the y coordinate */
53
/* // the z coordinate */
57
/* // the raw x coordinate */
59
output << "\"Raw X\"";
61
/* // the raw y coordinate */
63
output << "\"Raw Y\"";
65
/* // the raw z coordinate */
67
output << "\"Raw Z\"";
73
/* // the intensity */
75
output << "\"Intensity\"";
79
output << "\"Scan Angle\"";
81
/* the number of the return */
83
output << "\"Return Number\"";
85
/* the classification */
87
output << "\"Classification\"";
89
/* the classification name */
91
output << "\"Classification Name\"";
95
output << "\"User Data\"";
97
/* the number of returns of given pulse */
99
output << "\"Number of Returns\"";
101
/* the red channel color */
105
/* the green channel color */
107
output << "\"Green\"";
109
/* the blue channel color */
111
output << "\"Blue\"";
117
output << "\"Point Source ID\"";
119
/* the edge of flight line flag */
121
output << "\"Flight Line Edge\"";
123
/* the direction of scan flag */
125
output << "\"Scan Direction\"";
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)
152
std::ostringstream output;
154
boost::uint32_t i = 0;
155
liblas::Color const& c = p.GetColor();
159
switch (parse_string[i])
161
/* // the x coordinate */
163
output.setf(std::ios_base::fixed, std::ios_base::floatfield);
164
output.precision(precisions[0]); //x precision
166
output.unsetf(std::ios_base::fixed);
167
output.unsetf(std::ios_base::floatfield);
169
/* // the y coordinate */
171
output.setf(std::ios_base::fixed, std::ios_base::floatfield);
172
output.precision(precisions[1]); //y precision
174
output.unsetf(std::ios_base::fixed);
175
output.unsetf(std::ios_base::floatfield);
177
/* // the z coordinate */
179
output.setf(std::ios_base::fixed, std::ios_base::floatfield);
180
output.precision(precisions[2]); //z precision
182
output.unsetf(std::ios_base::fixed);
183
output.unsetf(std::ios_base::floatfield);
185
/* // the raw x coordinate */
187
output << p.GetRawX();
189
/* // the raw y coordinate */
191
output << p.GetRawY();
193
/* // the raw z coordinate */
195
output << p.GetRawZ();
197
/* // the gps-time */
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);
205
/* // the intensity */
207
output << p.GetIntensity();
211
output << (int)p.GetScanAngleRank();
213
/* the number of the return */
215
output << p.GetReturnNumber();
217
/* the classification */
219
output << static_cast<boost::uint32_t>(p.GetClassification().GetClass());
221
/* the classification name */
223
output << p.GetClassification().GetClassName();
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);
234
/* the number of returns of given pulse */
236
output << p.GetNumberOfReturns();
238
/* the red channel color */
240
output << c.GetRed();
242
/* the green channel color */
244
output << c.GetGreen();
246
/* the blue channel color */
248
output << c.GetBlue();
254
output << p.GetPointSourceID();
256
/* the edge of flight line flag */
258
output << p.GetFlightLineEdge();
260
/* the direction of scan flag */
262
output << p.GetScanDirection();
284
std::string GetHeader(liblas::Reader& reader)
286
boost::ignore_unused_variable_warning(reader);
288
std::ostringstream oss;
292
void write_points( liblas::Reader& reader,
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,
304
liblas::Summary summary;
306
reader.SetFilters(filters);
307
reader.SetTransforms(transforms);
311
std::cout << "Writing points:"
316
// Translation of points cloud to features set
318
boost::uint32_t i = 0;
319
boost::uint32_t const size = reader.GetHeader().GetPointRecordsCount();
323
oss << GetHeader(reader);
328
oss << GetLabels(parse_string, delimiter);
332
while (reader.ReadNextPoint())
334
liblas::Point const& p = reader.GetPoint();
335
// summary.AddPoint(p);
336
std::string output = GetPointString(parse_string, delimiter, p, precisions, i);
340
term_progress(std::cout, (i + 1) / static_cast<double>(size));
345
std::cout << std::endl;
350
void OutputHelp( std::ostream & oss, po::options_description const& options)
352
oss << "--------------------------------------------------------------------\n";
353
oss << " las2txt (" << GetFullVersion() << ")\n";
354
oss << "--------------------------------------------------------------------\n";
358
oss <<"\nFor more information, see the full documentation for lasinfo at:\n";
360
oss << " http://liblas.org/utilities/las2txt.html\n";
361
oss << "----------------------------------------------------------\n";
366
int main(int argc, char* argv[])
371
std::string parse_string("xyz");
372
std::string delimiter(",");
373
std::ostream* os = NULL;
375
bool verbose = false;
376
bool output_xml = false;
377
bool bPrintLabels = false;
378
bool bPrintHeader = false;
379
bool bUseStdout = false;
381
std::vector<liblas::FilterPtr> filters;
382
std::vector<liblas::TransformPtr> transforms;
384
liblas::Header header;
385
boost::array<boost::uint32_t, 4> precisions;
386
precisions.assign(0);
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"
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"
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"
420
po::options_description file_options("las2txt options");
421
po::options_description filtering_options = GetFilteringOptions();
422
po::options_description header_options = GetHeaderOptions();
424
po::positional_options_description p;
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")
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")
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);
453
if (vm.count("help"))
455
OutputHelp(std::cout, options);
460
if (vm.count("input"))
462
input = vm["input"].as< string >();
465
std::cout << "Opening " << input << " to fetch Header" << std::endl;
466
if (!liblas::Open(ifs, input.c_str()))
468
std::cerr << "Cannot open " << input << " for read. Exiting..." << std::endl;
471
liblas::ReaderFactory f;
472
liblas::Reader reader = f.CreateWithStream(ifs);
473
header = reader.GetHeader();
475
std::cerr << "Input LAS file not specified!\n";
476
OutputHelp(std::cout, options);
481
if (vm.count("output"))
483
output = vm["output"].as< string >();
485
std::ios::openmode const mode = std::ios::out | std::ios::binary;
486
if (compare_no_case(output.c_str(),"STDOUT",5) == 0)
493
os = new std::ofstream(output.c_str(), mode);
499
std::cerr << "Cannot open " << output << " to write. Exiting..." << std::endl;
512
std::cerr << "Output text file not specified!\n";
513
OutputHelp(std::cout, options);
518
filters = GetFilters(vm, verbose);
521
if (!liblas::Open(ifs, input.c_str()))
523
std::cerr << "Cannot open " << input << " for read. Exiting..." << std::endl;
527
if (vm.count("precision"))
529
std::vector<std::string> precision_str = vm["precision"].as< std::vector<std::string> >();
530
if (precision_str.size() > 4) {
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());
536
if (precision_str.size() < 3) {
538
oss << "At least three arguments must be given to precision. ";
539
throw std::runtime_error(oss.str());
545
for (std::vector<std::string>::const_iterator i = precision_str.begin();
546
i != precision_str.end();
551
std::cout << "Setting precisions to: " << oss.str() << std::endl;
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]);
558
if (precision_str.size() == 4)
560
precisions[3] = boost::lexical_cast<boost::uint32_t>(precision_str[3]);
567
precisions[0] = GetStreamPrecision(header.GetScaleX());
568
precisions[1] = GetStreamPrecision(header.GetScaleY());
569
precisions[2] = GetStreamPrecision(header.GetScaleZ());
573
for (boost::array<boost::uint32_t, 4>::const_iterator i = precisions.begin();
574
i != precisions.end();
581
std::cout << "Setting precisions from header to " << oss.str() << std::endl;
585
if (vm.count("delimiter"))
587
std::string delim = vm["delimiter"].as< string >();
588
std::string tab("\\t");
589
std::string newline("\\n");
590
if (!delim.compare(tab))
593
} else if (!delim.compare(newline))
599
std::cout << "Using delimiter '" << delim << "'"<< std::endl;
604
liblas::ReaderFactory f;
605
liblas::Reader reader = f.CreateWithStream(ifs);
607
write_points( reader,
618
if (os != 0 && !bUseStdout)
622
catch(std::exception& e) {
623
std::cerr << "error: " << e.what() << "\n";
627
std::cerr << "Exception of unknown type!\n";
635
//las2las2 -i lt_srs_rt.las -o foo.las -c 1,2 -b 2483590,366208,2484000,366612