From 9616af287e8e7864cd4796de698b03dbd1b1fb01 Mon Sep 17 00:00:00 2001 From: Andrew Bell Date: Mon, 12 Oct 2015 13:35:42 -0500 Subject: [PATCH] Add support for 'all' 'extra-dims' in LasWriter. --- doc/stages/writers.las.rst | 5 ++ io/las/LasHeader.cpp | 29 +++++++- io/las/LasHeader.hpp | 2 + io/las/LasUtils.cpp | 16 +++++ io/las/LasWriter.cpp | 17 +++++ test/data/bpf/simple-extra.bpf | Bin 0 -> 82180 bytes test/unit/io/las/LasWriterTest.cpp | 106 +++++++++++++++-------------- 7 files changed, 123 insertions(+), 52 deletions(-) create mode 100644 test/data/bpf/simple-extra.bpf diff --git a/doc/stages/writers.las.rst b/doc/stages/writers.las.rst index 6b8f25e701..fbdaaed5db 100644 --- a/doc/stages/writers.las.rst +++ b/doc/stages/writers.las.rst @@ -152,5 +152,10 @@ extra_dims bytes VLR (User ID: LASF_Spec, Record ID: 4), is created that describes the extra dimensions specified by this option. + The special value 'all' can be used in place of a dimension/type list + to request + that all dimensions that can't be stored in the predefined LAS point + record get added as extra data at the end of each point record. + .. _LAS format: http://asprs.org/Committee-General/LASer-LAS-File-Format-Exchange-Activities.html diff --git a/io/las/LasHeader.cpp b/io/las/LasHeader.cpp index 243c4e5743..b136abed31 100644 --- a/io/las/LasHeader.cpp +++ b/io/las/LasHeader.cpp @@ -90,7 +90,7 @@ void LasHeader::setSummary(const SummaryData& summary) { m_pointCount = summary.getTotalNumPoints(); for (size_t num = 0; num < RETURN_COUNT; ++num) - m_pointCountByReturn[num] = summary.getReturnCount(num); + m_pointCountByReturn[num] = (int)summary.getReturnCount(num); m_bounds = summary.getBounds(); } @@ -197,6 +197,33 @@ void LasHeader::put(OLeStream& out, boost::uuids::uuid uuid) } +Dimension::IdList LasHeader::usedDims() const +{ + using namespace Dimension; + + Dimension::Id::Enum dims[] = { Id::ReturnNumber, Id::NumberOfReturns, + Id::X, Id::Y, Id::Z, Id::Intensity, Id::ScanChannel, + Id::ScanDirectionFlag, Id::EdgeOfFlightLine, Id::Classification, + Id::UserData, Id::ScanAngleRank, Id::PointSourceId }; + + // This mess is because MSVC doesn't support initializer lists. + Dimension::IdList ids; + std::copy(std::begin(dims), std::end(dims), std::back_inserter(ids)); + + if (hasTime()) + ids.push_back(Id::GpsTime); + if (hasColor()) + { + ids.push_back(Id::Red); + ids.push_back(Id::Green); + ids.push_back(Id::Blue); + } + if (hasInfrared()) + ids.push_back(Id::Infrared); + + return ids; +} + ILeStream& operator>>(ILeStream& in, LasHeader& h) { uint8_t versionMajor; diff --git a/io/las/LasHeader.hpp b/io/las/LasHeader.hpp index c8513fb807..02aff4b251 100644 --- a/io/las/LasHeader.hpp +++ b/io/las/LasHeader.hpp @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -366,6 +367,7 @@ class PDAL_DLL LasHeader void setSummary(const SummaryData& summary); bool valid() const; + Dimension::IdList usedDims() const; friend ILeStream& operator>>(ILeStream&, LasHeader& h); friend OLeStream& operator<<(OLeStream&, const LasHeader& h); diff --git a/io/las/LasUtils.cpp b/io/las/LasUtils.cpp index a84a1fc76f..5e5288c174 100644 --- a/io/las/LasUtils.cpp +++ b/io/las/LasUtils.cpp @@ -185,9 +185,16 @@ namespace LasUtils std::vector parse(const StringList& dimString) { std::vector extraDims; + bool all = false; for (auto& dim : dimString) { + if (dim == "all") + { + all = true; + continue; + } + StringList s = Utils::split2(dim, '='); if (s.size() != 2) { @@ -211,6 +218,15 @@ std::vector parse(const StringList& dimString) ExtraDim ed(s[0], type); extraDims.push_back(ed); } + + if (all) + { + if (extraDims.size()) + throw (pdal_error("Can't specify specific extra dimensions with " + "special 'all' keyword.")); + extraDims.push_back(ExtraDim("all", Dimension::Type::None)); + } + return extraDims; } diff --git a/io/las/LasWriter.cpp b/io/las/LasWriter.cpp index 42a4168247..01202e0d2a 100644 --- a/io/las/LasWriter.cpp +++ b/io/las/LasWriter.cpp @@ -156,6 +156,23 @@ void LasWriter::processOptions(const Options& options) void LasWriter::prepared(PointTableRef table) { + PointLayoutPtr layout = table.layout(); + + // If we've asked for all dimensions, add to extraDims all dimensions + // in the layout that aren't already destined for LAS output. + if (m_extraDims.size() == 1 && m_extraDims[0].m_name == "all") + { + m_extraDims.clear(); + Dimension::IdList ids = m_lasHeader.usedDims(); + DimTypeList dimTypes = layout->dimTypes(); + for (auto& dt : dimTypes) + { + if (!Utils::contains(ids, dt.m_id)) + m_extraDims.push_back( + ExtraDim(layout->dimName(dt.m_id), dt.m_type)); + } + } + m_extraByteLen = 0; for (auto& dim : m_extraDims) { diff --git a/test/data/bpf/simple-extra.bpf b/test/data/bpf/simple-extra.bpf new file mode 100644 index 0000000000000000000000000000000000000000..3508c11fd33bb7db3c865b716e915905cffd1849 GIT binary patch literal 82180 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 #include #include +#include #include #include @@ -232,6 +233,60 @@ TEST(LasWriterTest, extra_dims) } } +TEST(LasWriterTest, all_extra_dims) +{ + Options readerOps; + + readerOps.add("filename", Support::datapath("bpf/simple-extra.bpf")); + BpfReader reader; + reader.setOptions(readerOps); + + FileUtils::deleteFile(Support::temppath("simple.las")); + + Options writerOps; + writerOps.add("extra_dims", "all"); + writerOps.add("filename", Support::temppath("simple.las")); + writerOps.add("minor_version", 4); + LasWriter writer; + writer.setInput(reader); + writer.setOptions(writerOps); + + PointTable table; + writer.prepare(table); + writer.execute(table); + + Options ops; + ops.add("filename", Support::temppath("simple.las")); + + LasReader r; + r.setOptions(ops); + + PointTable t2; + r.prepare(t2); + Dimension::Id::Enum foo = t2.layout()->findDim("Foo"); + Dimension::Id::Enum bar = t2.layout()->findDim("Bar"); + Dimension::Id::Enum baz = t2.layout()->findDim("Baz"); + + PointViewSet s = r.execute(t2); + EXPECT_EQ(s.size(), 1u); + PointViewPtr v = *s.begin(); + + // We test for floats instead of doubles because when X, Y and Z + // get written, they are written scaled, which loses precision. The + // foo, bar and baz values are written as full-precision doubles. + for (PointId i = 0; i < v->size(); ++i) + { + using namespace Dimension; + + EXPECT_FLOAT_EQ(v->getFieldAs(Id::X, i), + v->getFieldAs(foo, i)); + EXPECT_FLOAT_EQ(v->getFieldAs(Id::Y, i), + v->getFieldAs(bar, i)); + EXPECT_FLOAT_EQ(v->getFieldAs(Id::Z, i), + v->getFieldAs(baz, i)); + } +} + // Merge a couple of 1.4 LAS files with point formats 1 and 6. Write the // output with version 3. Verify that you get point format 3 (default), // LAS 1.3 output and other header data forwarded. @@ -591,57 +646,6 @@ TEST(LasWriterTest, simple) } **/ -//ABELL -/** -TEST(LasWriterTest, LasWriterTest_test_simple_laz) -{ - PointTable table; - - WriterOpts writerOpts; - writerOpts.add("compressed", true); - writerOpts.add("creation_year", 0); - writerOpts.add("creation_doy", 0); - writerOpts.add("system_id", ""); - writerOpts.add("software_id", "TerraScan"); - - - // remove file from earlier run, if needed - FileUtils::deleteFile("laszip/LasWriterTest_test_simple_laz.laz"); - - LasReader reader(Support::datapath("laszip/basefile.las")); - - std::ostream* ofs = FileUtils::createFile( - Support::temppath("LasWriterTest_test_simple_laz.laz")); - - // need to scope the writer, so that's it dtor can use the stream - std::shared_ptr writer(new LasWriter)(ofs); - writer->setOptions(writer); - writer->setInput(&reader); - - writer->prepare(table); - writer->execute(table); - - FileUtils::closeFile(ofs); - - { - LasReader reader( - Support::temppath("LasWriterTest_test_simple_laz.laz")); - } - - // these two files only differ by the description string in the VLR. - // This now skips the entire LASzip VLR for comparison. - const uint32_t numdiffs =Support::diff_files( - Support::temppath("LasWriterTest_test_simple_laz.laz"), - Support::datapath("laszip/laszip-generated.laz"), - 227, 106); - EXPECT_EQ(numdiffs, 0u); - - if (numdiffs == 0) - FileUtils::deleteFile( - Support::temppath("LasWriterTest_test_simple_laz.laz")); -} -**/ - //ABELL /** static void test_a_format(const std::string& refFile, uint8_t majorVersion,