From 50a24c7925137dcd3d41267ca6c9a5ba3e12b7ee Mon Sep 17 00:00:00 2001 From: Shuo Zhong Date: Fri, 22 Aug 2025 22:00:28 -0500 Subject: [PATCH 1/3] Preserve scale and offset when processing las file --- point_io.cpp | 28 ++++++++++++++++++++++++++++ point_io.hpp | 3 +++ 2 files changed, 31 insertions(+) diff --git a/point_io.cpp b/point_io.cpp index 3394e18..6a2b4bb 100644 --- a/point_io.cpp +++ b/point_io.cpp @@ -314,6 +314,14 @@ PointSet *fastPlyReadPointSet(const std::string &filename) { return r; } +template +void readLasMeta(pdal::MetadataNode &lasforward, std::string name, T &val) { + pdal::MetadataNode m = lasforward.findChild(name); + if (m.valid()) { + val = m.value(); + } +} + PointSet *pdalReadPointSet(const std::string &filename) { #ifdef WITH_PDAL std::string labelDimension; @@ -336,6 +344,18 @@ PointSet *pdalReadPointSet(const std::string &filename) { s->prepare(*table); const pdal::PointViewSet pvSet = s->execute(*table); + pdal::MetadataNode lasforward, m; + lasforward = table->privateMetadata("lasforward"); + if (lasforward.valid()) { + readLasMeta(lasforward, "scale_x", r->scales[0]); + readLasMeta(lasforward, "scale_y", r->scales[1]); + readLasMeta(lasforward, "scale_z", r->scales[2]); + readLasMeta(lasforward, "offset_x", r->offsets[0]); + readLasMeta(lasforward, "offset_y", r->offsets[1]); + readLasMeta(lasforward, "offset_z", r->offsets[2]); + } + + r->pointView = *pvSet.begin(); const pdal::PointViewPtr pView = r->pointView; @@ -492,6 +512,14 @@ void pdalSavePointSet(PointSet &pSet, const std::string &filename) { pdal::Stage *s = factory.createStage(driver); pdal::Options opts; opts.add("filename", filename); + if (driver == "writers.las") { + opts.add("scale_x", pSet.scales[0]); + opts.add("scale_y", pSet.scales[1]); + opts.add("scale_z", pSet.scales[2]); + opts.add("offset_x", pSet.offsets[0]); + opts.add("offset_y", pSet.offsets[1]); + opts.add("offset_z", pSet.offsets[2]); + } s->setOptions(opts); s->setInput(reader); diff --git a/point_io.hpp b/point_io.hpp index 241988c..8352262 100644 --- a/point_io.hpp +++ b/point_io.hpp @@ -33,6 +33,9 @@ struct PointSet { std::vector labels; std::vector views; + std::array scales {0.01, 0.01, 0.01}; + std::array offsets {0.0, 0.0, 0.0}; + std::vector pointMap; PointSet *base = nullptr; From 6a0982bb7c400c3c0d246676d6689b58d2d552dd Mon Sep 17 00:00:00 2001 From: Shuo Zhong Date: Sat, 23 Aug 2025 11:12:46 -0500 Subject: [PATCH 2/3] Removed unused variable --- point_io.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/point_io.cpp b/point_io.cpp index 6a2b4bb..c2a8f9b 100644 --- a/point_io.cpp +++ b/point_io.cpp @@ -344,7 +344,7 @@ PointSet *pdalReadPointSet(const std::string &filename) { s->prepare(*table); const pdal::PointViewSet pvSet = s->execute(*table); - pdal::MetadataNode lasforward, m; + pdal::MetadataNode lasforward; lasforward = table->privateMetadata("lasforward"); if (lasforward.valid()) { readLasMeta(lasforward, "scale_x", r->scales[0]); From 1ecfdc43ad8c78d85fbf1582b6ab8d0f1a13720c Mon Sep 17 00:00:00 2001 From: Shuo Zhong Date: Sat, 23 Aug 2025 15:35:58 -0500 Subject: [PATCH 3/3] 1. update changes to be there only when pdal is available 2. prevent edge cases when offsets or scales not exist --- point_io.cpp | 56 ++++++++++++++++++++++++++++++++++++---------------- point_io.hpp | 5 ++--- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/point_io.cpp b/point_io.cpp index c2a8f9b..be1ec8e 100644 --- a/point_io.cpp +++ b/point_io.cpp @@ -314,14 +314,40 @@ PointSet *fastPlyReadPointSet(const std::string &filename) { return r; } +#ifdef WITH_PDAL template -void readLasMeta(pdal::MetadataNode &lasforward, std::string name, T &val) { +bool pdalReadLasMeta(pdal::MetadataNode &lasforward, std::string name, T &val) { pdal::MetadataNode m = lasforward.findChild(name); if (m.valid()) { val = m.value(); + return true; + } else { + return false; } } +void pdalReadLasScaleOffset(pdal::PointTable *table, PointSet *pSet) { + pdal::MetadataNode lasforward; + lasforward = table->privateMetadata("lasforward"); + if (!lasforward.valid()) + return; + bool success = true; + pSet->scales = std::make_unique>(); + success &= pdalReadLasMeta(lasforward, "scale_x", pSet->scales->at(0)); + success &= pdalReadLasMeta(lasforward, "scale_y", pSet->scales->at(1)); + success &= pdalReadLasMeta(lasforward, "scale_z", pSet->scales->at(2)); + if (!success) + pSet->scales = nullptr; + success = true; + pSet->offsets = std::make_unique>(); + success &= pdalReadLasMeta(lasforward, "offset_x", pSet->offsets->at(0)); + success &= pdalReadLasMeta(lasforward, "offset_y", pSet->offsets->at(1)); + success &= pdalReadLasMeta(lasforward, "offset_z", pSet->offsets->at(2)); + if (!success) + pSet->offsets = nullptr; +} +#endif + PointSet *pdalReadPointSet(const std::string &filename) { #ifdef WITH_PDAL std::string labelDimension; @@ -344,18 +370,10 @@ PointSet *pdalReadPointSet(const std::string &filename) { s->prepare(*table); const pdal::PointViewSet pvSet = s->execute(*table); - pdal::MetadataNode lasforward; - lasforward = table->privateMetadata("lasforward"); - if (lasforward.valid()) { - readLasMeta(lasforward, "scale_x", r->scales[0]); - readLasMeta(lasforward, "scale_y", r->scales[1]); - readLasMeta(lasforward, "scale_z", r->scales[2]); - readLasMeta(lasforward, "offset_x", r->offsets[0]); - readLasMeta(lasforward, "offset_y", r->offsets[1]); - readLasMeta(lasforward, "offset_z", r->offsets[2]); + if (driver == "readers.las") { + pdalReadLasScaleOffset(table, r); } - r->pointView = *pvSet.begin(); const pdal::PointViewPtr pView = r->pointView; @@ -513,12 +531,16 @@ void pdalSavePointSet(PointSet &pSet, const std::string &filename) { pdal::Options opts; opts.add("filename", filename); if (driver == "writers.las") { - opts.add("scale_x", pSet.scales[0]); - opts.add("scale_y", pSet.scales[1]); - opts.add("scale_z", pSet.scales[2]); - opts.add("offset_x", pSet.offsets[0]); - opts.add("offset_y", pSet.offsets[1]); - opts.add("offset_z", pSet.offsets[2]); + if (pSet.scales != nullptr) { + opts.add("scale_x", pSet.scales->at(0)); + opts.add("scale_y", pSet.scales->at(1)); + opts.add("scale_z", pSet.scales->at(2)); + } + if (pSet.offsets != nullptr) { + opts.add("offset_x", pSet.offsets->at(0)); + opts.add("offset_y", pSet.offsets->at(1)); + opts.add("offset_z", pSet.offsets->at(2)); + } } s->setOptions(opts); s->setInput(reader); diff --git a/point_io.hpp b/point_io.hpp index 8352262..812cf19 100644 --- a/point_io.hpp +++ b/point_io.hpp @@ -33,9 +33,6 @@ struct PointSet { std::vector labels; std::vector views; - std::array scales {0.01, 0.01, 0.01}; - std::array offsets {0.0, 0.0, 0.0}; - std::vector pointMap; PointSet *base = nullptr; @@ -43,6 +40,8 @@ struct PointSet { #ifdef WITH_PDAL pdal::PointViewPtr pointView = nullptr; + std::unique_ptr> scales = nullptr; + std::unique_ptr> offsets = nullptr; #endif template