diff --git a/io/LasReader.cpp b/io/LasReader.cpp index 6ba84d63cd..9351fd00a1 100644 --- a/io/LasReader.cpp +++ b/io/LasReader.cpp @@ -138,6 +138,11 @@ const LasHeader& LasReader::header() const return d->apiHeader; } +const las::Header& LasReader::lasHeader() const +{ + return d->header; +} + uint64_t LasReader::vlrData(const std::string& userId, uint16_t recordId, char const * & data) { const las::Vlr *vlr = las::findVlr(userId, recordId, d->vlrs); diff --git a/io/LasReader.hpp b/io/LasReader.hpp index 3cbeb572fd..d09ffb9efd 100644 --- a/io/LasReader.hpp +++ b/io/LasReader.hpp @@ -60,6 +60,8 @@ class LasHeader; class PDAL_DLL LasReader : public Reader, public Streamable { + friend class LasTester; + protected: class LasStreamIf { @@ -121,6 +123,8 @@ class PDAL_DLL LasReader : public Reader, public Streamable void loadExtraDims(LeExtractor& istream, PointRef& data); point_count_t readFileBlock(std::vector& buf, point_count_t maxPoints); + const las::Header& lasHeader() const; + struct Options; struct Private; std::unique_ptr d; diff --git a/io/private/copcwriter/Output.cpp b/io/private/copcwriter/Output.cpp index 955a8f2397..5f64e89612 100644 --- a/io/private/copcwriter/Output.cpp +++ b/io/private/copcwriter/Output.cpp @@ -80,6 +80,10 @@ Output::Output(const BaseInfo& b) : b(b) m_header.minz = b.stats[(int)stats::Index::Z].minimum(); m_header.maxz = b.stats[(int)stats::Index::Z].maximum(); + // legacy point counts are all zero, since COPC is LAS 1.4 only. + std::fill(std::begin(m_header.points_by_return), std::end(m_header.points_by_return), 0); + m_header.point_count = 0; + for (int i = 1; i <= 15; ++i) { point_count_t count = 0; @@ -91,18 +95,8 @@ Output::Output(const BaseInfo& b) : b(b) {} m_header.points_by_return_14[i - 1] = count; - if (i <= 5) - { - if (m_header.points_by_return_14[i] <= (std::numeric_limits::max)()) - m_header.points_by_return[i - 1] = m_header.points_by_return_14[i - 1]; - else - m_header.points_by_return[i - 1] = 0; - } } - if (m_header.point_count_14 > (std::numeric_limits::max)()) - m_header.point_count = 0; - // Note that only these VLRs go in the standard VLR area. The rest are written as // extended VLRs. setupVlrs(); @@ -231,7 +225,6 @@ uint64_t Output::newChunk(const VoxelKey& key, int32_t size, int32_t count) m_pointPos += size; assert(count <= (std::numeric_limits::max)() && count >= 0); m_chunkTable.push_back({(uint64_t)count, (uint64_t)size}); - m_header.point_count += count; m_header.point_count_14 += count; m_hierarchy[key] = { chunkStart, size, count }; return chunkStart; diff --git a/test/unit/io/LasWriterTest.cpp b/test/unit/io/LasWriterTest.cpp index c436abd893..7b45e19c6c 100644 --- a/test/unit/io/LasWriterTest.cpp +++ b/test/unit/io/LasWriterTest.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,8 @@ class LasTester public: const las::Header& header(LasWriter& w) { return w.header(); } + const las::Header& header(LasReader& r) + { return r.lasHeader(); } SpatialReference srs(LasWriter& w) { return w.m_srs; } void addVlr(LasWriter& w, const std::string& userId, uint16_t recordId, @@ -1989,4 +1992,39 @@ TEST(LasWriterTest, issue2235) EXPECT_NE(h46.ePointsByReturn[i], 0); } } + + // test for COPC too + { + Options copcWriterOps; + copcWriterOps.add("filename", Support::temppath("out_4_6.copc.laz")); + + CopcWriter copcWriter; + copcWriter.setInput(reader); + copcWriter.setOptions(copcWriterOps); + + PointTable tableCopc; + copcWriter.prepare(tableCopc); + copcWriter.execute(tableCopc); + + Options copcReaderOpts; + copcReaderOpts.add("filename", Support::temppath("out_4_6.copc.laz")); + + LasReader readerCopc; + readerCopc.setOptions(copcReaderOpts); + + PointTable tableCopcR; + readerCopc.prepare(tableCopcR); + + const las::Header& headerCopc = tester.header(readerCopc); + + EXPECT_EQ(headerCopc.legacyPointCount, 0); + EXPECT_NE(headerCopc.pointCount(), 0); + + for (int i=0; i