diff --git a/bu/CopcSupport.cpp b/bu/CopcSupport.cpp index f3093c2..430155a 100644 --- a/bu/CopcSupport.cpp +++ b/bu/CopcSupport.cpp @@ -11,12 +11,14 @@ ****************************************************************************/ #include +#include #include "CopcSupport.hpp" #include #include #include +#include #include @@ -30,23 +32,25 @@ namespace bu { CopcSupport::CopcSupport(const BaseInfo& b) : - m_lazVlr(3, extraByteSize(b.dimInfo), lazperf::VariableChunkSize), - m_ebVlr(extraByteSize(b.dimInfo)), - m_wktVlr(b.srs.getWKT1()) + m_b(b), + m_lazVlr(b.opts.pointFormatId, ebVLRSize(), lazperf::VariableChunkSize), + m_ebVlr(ebVLRCount()), + m_wktVlr(b.srs.getWKT1()), + m_extentVlr() { m_f.open(b.opts.outputName, std::ios::out | std::ios::binary); //ABELL m_header.file_source_id = 0; - m_header.global_encoding = (1 << 4); + m_header.global_encoding = (1 << 4); // Set for WKT //ABELL m_header.creation.day = 1; m_header.creation.year = 1; m_header.header_size = lazperf::header14::Size; - m_header.vlr_count = 3; - m_header.point_format_id = 3; + m_header.vlr_count = 4; + m_header.point_format_id = b.opts.pointFormatId; m_header.point_format_id |= (1 << 7); // Bit for laszip - m_header.point_record_length = lazperf::baseCount(3) + extraByteSize(b.dimInfo); + m_header.point_record_length = lazperf::baseCount(b.opts.pointFormatId) + ebVLRSize(); m_header.scale.x = b.scale[0]; m_header.scale.y = b.scale[1]; m_header.scale.z = b.scale[2]; @@ -56,7 +60,8 @@ CopcSupport::CopcSupport(const BaseInfo& b) : m_header.point_offset = lazperf::header14::Size + lazperf::vlr_header::Size + m_copcVlr.size() + lazperf::vlr_header::Size + m_lazVlr.size() + - lazperf::vlr_header::Size + m_wktVlr.size(); + lazperf::vlr_header::Size + m_wktVlr.size() + + lazperf::vlr_header::Size + m_extentVlr.size(); if (m_header.ebCount()) { m_header.vlr_count++; @@ -67,31 +72,124 @@ CopcSupport::CopcSupport(const BaseInfo& b) : m_chunkOffsetPos = m_header.point_offset; // The actual point data comes after the chunk table offset. m_pointPos = m_chunkOffsetPos + sizeof(uint64_t); + + setEbVLR(); +} + + +void CopcSupport::setEbVLR() +{ + + using DT = pdal::Dimension::Type; + const pdal::Dimension::Type lastypes[] = { + DT::None, DT::Unsigned8, DT::Signed8, DT::Unsigned16, DT::Signed16, + DT::Unsigned32, DT::Signed32, DT::Unsigned64, DT::Signed64, + DT::Float, DT::Double + }; + + VLRInfo info = computeVLRInfo(); + m_ebVlr.items.clear(); + for (FileDimInfo& fdi: info.ebDims) + { + lazperf::eb_vlr::ebfield field; + + field.name = fdi.name; + + uint8_t lastype = 0; + for (size_t i = 0; i < sizeof(lastypes) / sizeof(lastypes[0]); ++i) + if (fdi.type == lastypes[i]) + { + lastype = i; + break; + } + + field.data_type = lastype; + m_ebVlr.items.push_back(field); + } + + + } -int CopcSupport::extraByteSize(const DimInfoList& dims) const + +CopcSupport::VLRInfo::VLRInfo() + : ebVLRSize(0) + , ebVLRCount(0) + , extentVLRCount(0) +{} + + +CopcSupport::VLRInfo CopcSupport::computeVLRInfo() const { using namespace pdal; - // PDRF 3 dim list - Dimension::IdList lasDims { Dimension::Id::X, Dimension::Id::Y, Dimension::Id::Z, + VLRInfo info; + + // Start with PDRF 6 dim list for statistics + Dimension::IdList statsDims = { Dimension::Id::X, Dimension::Id::Y, Dimension::Id::Z, Dimension::Id::Intensity, Dimension::Id::ReturnNumber, Dimension::Id::NumberOfReturns, Dimension::Id::ScanDirectionFlag, Dimension::Id::EdgeOfFlightLine, Dimension::Id::Classification, Dimension::Id::ScanAngleRank, Dimension::Id::UserData, - Dimension::Id::PointSourceId, Dimension::Id::GpsTime, Dimension::Id::Red, - Dimension::Id::Green, Dimension::Id::Blue }; + Dimension::Id::PointSourceId, Dimension::Id::GpsTime }; + + if (m_b.opts.pointFormatId == 7) + { + statsDims.push_back(Dimension::Id::Red); + statsDims.push_back(Dimension::Id::Green); + statsDims.push_back(Dimension::Id::Blue); + } + if (m_b.opts.pointFormatId == 8) + { + statsDims.push_back(Dimension::Id::Red); + statsDims.push_back(Dimension::Id::Green); + statsDims.push_back(Dimension::Id::Blue); + statsDims.push_back(Dimension::Id::Infrared); + } - int extraBytes {0}; PointLayout layout; - for (const FileDimInfo& fdi : dims) + for (const FileDimInfo& fdi : m_b.dimInfo) { Dimension::Id dim = layout.registerOrAssignDim(fdi.name, fdi.type); - if (!Utils::contains(lasDims, dim)) - extraBytes += layout.dimSize(dim); + if (Utils::contains(statsDims, fdi.dim)) + { + info.extentVLRCount++; + info.ebVLRCount++; + } else + { + info.ebVLRSize = info.ebVLRSize + layout.dimSize(dim); + info.extentVLRCount++; + info.ebVLRCount++; + + info.ebDims.push_back(fdi); + statsDims.push_back(fdi.dim); + } } - return extraBytes; + info.statsDims = statsDims; + return info; + } + +int CopcSupport::ebVLRSize() const +{ + VLRInfo info = computeVLRInfo(); + return info.ebVLRSize; +} + +int CopcSupport::ebVLRCount() const +{ + VLRInfo info = computeVLRInfo(); + return info.ebVLRCount; +} + + +int CopcSupport::extentVLRCount() const +{ + VLRInfo info = computeVLRInfo(); + return info.extentVLRCount; +} + + /// \param size Size of the chunk in bytes /// \param count Number of points in the chunk /// \param key Key of the voxel the chunk represents @@ -133,24 +231,49 @@ void CopcSupport::updateHeader(const StatsMap& stats) } catch (const std::out_of_range&) {} + 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; + m_header.points_by_return[i - 1] = 0; } } - if (m_header.point_count_14 > (std::numeric_limits::max)()) - m_header.point_count = 0; + // Don't use old point_count because we are pointSourceId 6, 7, or 8 + m_header.point_count = 0; + + VLRInfo info = computeVLRInfo(); + pdal::PointLayout layout; + for (const FileDimInfo& fdi : m_b.dimInfo) + { + pdal::Dimension::Id dim = layout.registerOrAssignDim(fdi.name, fdi.type); + } + + std::vector extents; + for (const pdal::Dimension::Id& dimId: info.statsDims) + { + if (layout.hasDim(dimId)) + { + std::string name (layout.dimName(dimId)); + double min = stats.at(name).minimum(); + double max = stats.at(name).maximum(); + extents.push_back(copc_extents_vlr::CopcExtent(min, max)); + } + } + + // copy into our VLR: + for (size_t i = 0; i < extents.size(); i++) + { + m_extentVlr.addItem(extents[i]); + } + } + void CopcSupport::writeHeader() { - uint64_t start; - uint64_t end; + uint64_t start (0); + uint64_t end (0); std::ostream& out = m_f; out.seekp(0); @@ -161,27 +284,20 @@ void CopcSupport::writeHeader() m_copcVlr.write(out); m_lazVlr.header().write(out); - start = out.tellp(); m_lazVlr.write(out); - end = out.tellp(); - m_copcVlr.laz_vlr_offset = start; - m_copcVlr.laz_vlr_size = end - start; m_wktVlr.header().write(out); - start = out.tellp(); m_wktVlr.write(out); + + m_extentVlr.header().write(out); + m_extentVlr.write(out); end = out.tellp(); - m_copcVlr.wkt_vlr_offset = start; - m_copcVlr.wkt_vlr_size = end - start; if (m_header.ebCount()) { m_ebVlr.header().write(out); - start = out.tellp(); m_ebVlr.write(out); end = out.tellp(); - m_copcVlr.eb_vlr_offset = start; - m_copcVlr.eb_vlr_size = end - start; } // Rewrite the COPC VLR with the updated positions and seek back to the end of the VLRs. @@ -225,9 +341,9 @@ void CopcSupport::writeHierarchy(const CountMap& counts) m_copcVlr.root_hier_offset = root.offset; m_copcVlr.root_hier_size = root.byteSize; uint64_t endPos = m_f.tellp(); - + // Now write VLR header. - lazperf::evlr_header h { 0, "entwine", 1000, (endPos - beginPos), "EPT Hierarchy" }; + lazperf::evlr_header h { 0, "copc", 1000, (endPos - beginPos), "EPT Hierarchy" }; m_f.seekp(m_header.evlr_offset); h.write(m_f); } @@ -282,5 +398,136 @@ void CopcSupport::emitChildren(const VoxelKey& p, const CountMap& counts, } } + +copc_extents_vlr::copc_extents_vlr() +{} + + +void copc_extents_vlr::addItem(const CopcExtent& item) +{ + items.push_back(item); +} + + +copc_extents_vlr::~copc_extents_vlr() +{} + + +copc_extents_vlr::CopcExtent::CopcExtent(double minimum, double maximum) : + minimum(minimum), + maximum(maximum) +{} + + +copc_extents_vlr copc_extents_vlr::create(std::istream& in, int byteSize) +{ + copc_extents_vlr extentsVlr; + extentsVlr.read(in, byteSize); + return extentsVlr; +} + + +void copc_extents_vlr::read(std::istream& in, int byteSize) +{ + std::vector buf(byteSize); + pdal::LeExtractor s(buf.data(), buf.size()); + in.read(buf.data(), buf.size()); + + int numItems = byteSize / sizeof(CopcExtent); + items.clear(); + for (int i = 0; i < numItems; ++i) + { + double minimum; + double maximum; + + s >> minimum >> maximum; + + CopcExtent field(minimum, maximum); + items.push_back(field); + } +} + + +void copc_extents_vlr::write(std::ostream& out) const +{ + std::vector buf(size()); + pdal::LeInserter s(buf.data(), buf.size()); + + for (auto& i: items) + { + s << i.minimum << i.maximum; + } + + out.write(buf.data(), buf.size()); +} + + +size_t copc_extents_vlr::size() const +{ + return items.size() * sizeof(CopcExtent); +} + + +lazperf::vlr_header copc_extents_vlr::header() const +{ + return lazperf::vlr_header { 0, "copc", 10000, (uint16_t)size(), "COPC extents" }; +} + + +// Initialized in header. +copc_info_vlr::copc_info_vlr() +{} + + +copc_info_vlr::~copc_info_vlr() +{} + + +copc_info_vlr copc_info_vlr::create(std::istream& in) +{ + copc_info_vlr copcVlr; + copcVlr.read(in); + return copcVlr; +} + + +void copc_info_vlr::read(std::istream& in) +{ + std::vector buf(size()); + in.read(buf.data(), buf.size()); + pdal::LeExtractor s(buf.data(), buf.size()); + + s >> center_x >> center_y >> center_z >> halfsize >> spacing; + s >> root_hier_offset >> root_hier_size; + for (int i = 0; i < 13; ++i) + s >> reserved[i]; +} + + +void copc_info_vlr::write(std::ostream& out) const +{ + std::vector buf(size()); + pdal::LeInserter s(buf.data(), buf.size()); + + s << center_x << center_y << center_z << halfsize << spacing; + s << root_hier_offset << root_hier_size; + for (int i = 0; i < 13; ++i) + s << reserved[i]; + out.write(buf.data(), buf.size()); +} + + +size_t copc_info_vlr::size() const +{ + return sizeof(uint64_t) * 20; +} + + +lazperf::vlr_header copc_info_vlr::header() const +{ + return lazperf::vlr_header { 0, "copc", 1, (uint16_t)size(), "COPC info" }; +} + + } // namespace bu } // namespace untwine diff --git a/bu/CopcSupport.hpp b/bu/CopcSupport.hpp index 1cd0020..1f80bca 100644 --- a/bu/CopcSupport.hpp +++ b/bu/CopcSupport.hpp @@ -20,6 +20,7 @@ #include #include + namespace untwine { @@ -30,6 +31,54 @@ using DimInfoList = std::vector; namespace bu { + +struct copc_extents_vlr : public lazperf::vlr +{ +public: + + struct CopcExtent + { + double minimum; + double maximum; + + CopcExtent(double minimum, double maximum); + }; + + std::vector items; + + copc_extents_vlr(); + void addItem(const CopcExtent& item); + virtual ~copc_extents_vlr(); + + static copc_extents_vlr create(std::istream& in, int byteSize); + void read(std::istream& in, int byteSize); + void write(std::ostream& out) const; + virtual size_t size() const; + virtual lazperf::vlr_header header() const; +}; + +struct copc_info_vlr : public lazperf::vlr +{ +public: + double center_x {0.0}; + double center_y {0.0}; + double center_z {0.0}; + double halfsize {0.0}; + double spacing {0.0}; + uint64_t root_hier_offset {0}; + uint64_t root_hier_size {0}; + uint64_t reserved[13] {0}; + + copc_info_vlr(); + virtual ~copc_info_vlr(); + + static copc_info_vlr create(std::istream& in); + void read(std::istream& in); + void write(std::ostream& out) const; + virtual size_t size() const; + virtual lazperf::vlr_header header() const; +}; + class CopcSupport { public: @@ -39,6 +88,7 @@ class CopcSupport int32_t byteSize; int32_t pointCount; }; + using CountMap = std::unordered_map; using Entries = std::vector>; @@ -50,21 +100,42 @@ class CopcSupport void writeHierarchy(const CountMap& counts); private: + + + struct VLRInfo + { + int ebVLRSize {0}; + int ebVLRCount {0}; + int extentVLRCount {0}; + DimInfoList ebDims; + pdal::Dimension::IdList statsDims; + + VLRInfo(); + }; + + BaseInfo m_b; std::ofstream m_f; lazperf::header14 m_header; - lazperf::copc_vlr m_copcVlr; + copc_info_vlr m_copcVlr; lazperf::laz_vlr m_lazVlr; lazperf::eb_vlr m_ebVlr; lazperf::wkt_vlr m_wktVlr; + copc_extents_vlr m_extentVlr; std::vector m_chunkTable; uint64_t m_chunkOffsetPos; uint64_t m_pointPos; std::unordered_map m_hierarchy; - int extraByteSize(const DimInfoList& dims) const; + int ebVLRSize() const; + int ebVLRCount() const; + int extentVLRCount() const; Hierarchy emitRoot(const VoxelKey& root, const CountMap& counts); void emitChildren(const VoxelKey& root, const CountMap& counts, Entries& entries, int stopLevel); + + VLRInfo computeVLRInfo() const; + void setEbVLR(); + }; diff --git a/bu/Processor.cpp b/bu/Processor.cpp index 89dd8d5..c2a7bae 100644 --- a/bu/Processor.cpp +++ b/bu/Processor.cpp @@ -298,30 +298,53 @@ Processor::writeOctantCompressed(const OctantInfo& o, Index& index, IndexIter po // there's no reason why it should change. We should modify things to use a single // layout. - // PDRF 3 dim list + // Start with PDRF 6 dim list Dimension::IdList lasDims { Dimension::Id::X, Dimension::Id::Y, Dimension::Id::Z, Dimension::Id::Intensity, Dimension::Id::ReturnNumber, Dimension::Id::NumberOfReturns, Dimension::Id::ScanDirectionFlag, Dimension::Id::EdgeOfFlightLine, - Dimension::Id::Classification, Dimension::Id::ScanAngleRank, Dimension::Id::UserData, - Dimension::Id::PointSourceId, Dimension::Id::GpsTime, Dimension::Id::Red, - Dimension::Id::Green, Dimension::Id::Blue }; + Dimension::Id::Classification, Dimension::Id::ScanChannel, Dimension::Id::UserData, + Dimension::Id::ScanAngleRank, Dimension::Id::PointSourceId, Dimension::Id::GpsTime }; + + if (m_b.opts.pointFormatId == 7) + { + lasDims.push_back(Dimension::Id::Red); + lasDims.push_back(Dimension::Id::Green); + lasDims.push_back(Dimension::Id::Blue); + } + if (m_b.opts.pointFormatId == 8) + { + lasDims.push_back(Dimension::Id::Red); + lasDims.push_back(Dimension::Id::Green); + lasDims.push_back(Dimension::Id::Blue); + lasDims.push_back(Dimension::Id::Infrared); + } + DimInfoList dims = m_b.dimInfo; m_extraDims.clear(); for (FileDimInfo& fdi : dims) { - fdi.dim = table.layout()->registerOrAssignDim(fdi.name, fdi.type); - if (m_b.opts.stats) + // register dimension if we are in lasDims + Dimension::Id candidate = pdal::Dimension::id(fdi.name); + if (Utils::contains(lasDims, candidate)) { - // For single file output we need the counts by return number. - if (fdi.dim == pdal::Dimension::Id::Classification) - stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::Enumerate, false)}); - else if (fdi.dim == pdal::Dimension::Id::ReturnNumber && m_b.opts.singleFile) - stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::Enumerate, false)}); - else - stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::NoEnum, false)}); - } - if (!Utils::contains(lasDims, fdi.dim)) + // we add this one + fdi.dim = table.layout()->registerOrAssignDim(fdi.name, fdi.type); + if (m_b.opts.stats) + { + // For single file output we need the counts by return number. + if (fdi.dim == pdal::Dimension::Id::Classification) + stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::Enumerate, false)}); + else if (fdi.dim == pdal::Dimension::Id::ReturnNumber && m_b.opts.singleFile) + stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::Enumerate, false)}); + else + stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::NoEnum, false)}); + } + } else + { + fdi.dim = table.layout()->registerOrAssignDim(fdi.name, fdi.type); m_extraDims.push_back(DimType(fdi.dim, fdi.type)); + stats.push_back({fdi.dim, Stats(fdi.name, Stats::EnumType::NoEnum, false)}); + } } table.finalize(); @@ -394,7 +417,7 @@ void Processor::appendCompressed(pdal::PointViewPtr view, const DimInfoList& dim void Processor::flushCompressed(pdal::PointTableRef table, pdal::PointViewPtr view, const OctantInfo& oi, IndexedStats& stats) { - // For single file output we need the stats for + // For single file output we need the stats for if (m_b.opts.stats) { for (pdal::PointId id = 0; id < view->size(); ++id) @@ -415,7 +438,7 @@ void Processor::flushCompressed(pdal::PointTableRef table, pdal::PointViewPtr vi else { std::string filename = m_b.opts.outputName + "/ept-data/" + oi.key().toString() + ".laz"; - writeEptFile(filename, table, view); + writeEptFile(filename, table, view); } } @@ -476,9 +499,9 @@ void Processor::createChunk(const VoxelKey& key, pdal::PointViewPtr view) for (DimType dim : m_extraDims) ebCount += layout->dimSize(dim.m_id); - std::vector buf(lazperf::baseCount(3) + ebCount); + std::vector buf(lazperf::baseCount(m_b.opts.pointFormatId) + ebCount); - lazperf::writer::chunk_compressor compressor(3, ebCount); + lazperf::writer::chunk_compressor compressor(m_b.opts.pointFormatId, ebCount); for (PointId idx = 0; idx < view->size(); ++idx) { PointRef point(*view, idx); @@ -503,11 +526,11 @@ void Processor::fillPointBuf(pdal::PointRef& point, std::vector& buf) LeInserter ostream(buf.data(), buf.size()); -// We're currently only writing PDRF 3. - bool has14PointFormat = false; + // We're only write PDRF 6, 7, or 8. + bool has14PointFormat = true; bool hasTime = true; // m_lasHeader.hasTime(); - bool hasColor = true; // m_lasHeader.hasColor(); - bool hasInfrared = false; // m_lasHeader.hasInfrared(); + bool hasColor = m_b.opts.pointFormatId == 7 || m_b.opts.pointFormatId == 8; // m_lasHeader.hasColor(); + bool hasInfrared = m_b.opts.pointFormatId == 8; // m_lasHeader.hasInfrared(); // static const size_t maxReturnCount = m_lasHeader.maxReturnCount(); diff --git a/cmake/unix_compiler_options.cmake b/cmake/unix_compiler_options.cmake index 40a5834..10e3128 100644 --- a/cmake/unix_compiler_options.cmake +++ b/cmake/unix_compiler_options.cmake @@ -13,15 +13,14 @@ function(untwine_target_compile_settings target) -Wno-noexcept-type ) endif() - set(PDAL_COMPILER_GCC 1) + set(UNTWINE_COMPILER_GCC 1) elseif (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") - set(PDAL_COMPILER_CLANG 1) + set(UNTWINE_COMPILER_CLANG 1) else() message(FATAL_ERROR "Unsupported C++ compiler") endif() target_compile_options(${target} PRIVATE - ${PDAL_CXX_STANDARD} -Wall -Wextra -Wpointer-arith @@ -39,7 +38,7 @@ function(untwine_target_compile_settings target) -Werror ) - if (PDAL_COMPILER_CLANG) + if (UNTWINE_COMPILER_CLANG) target_compile_options(${target} PRIVATE -Wno-unknown-warning-option ) diff --git a/epf/Epf.cpp b/epf/Epf.cpp index f38d621..02cd17c 100644 --- a/epf/Epf.cpp +++ b/epf/Epf.cpp @@ -76,9 +76,15 @@ void Epf::run(ProgressWriter& progress) PointLayoutPtr layout(new PointLayout()); for (const std::string& dimName : allDimNames) { - Dimension::Type type = Dimension::defaultType(Dimension::id(dimName)); - if (type == Dimension::Type::None) + Dimension::Type type; + try + { + type = Dimension::defaultType(Dimension::id(dimName)); + } + catch (pdal::pdal_error&) + { type = Dimension::Type::Double; + } layout->registerOrAssignDim(dimName, type); } layout->finalize(); @@ -156,18 +162,50 @@ void Epf::run(ProgressWriter& progress) void Epf::fillMetadata(const pdal::PointLayoutPtr layout) { + using namespace pdal; + // Info to be passed to sampler. m_b.bounds = m_grid.processingBounds(); m_b.trueBounds = m_grid.conformingBounds(); if (m_srsFileInfo.valid()) m_b.srs = m_srsFileInfo.srs; m_b.pointSize = 0; + + + auto check_dimension_exists = [] (pdal::Dimension::Id dim, DimInfoList const& dimInfo) + { + auto it = std::find_if(dimInfo.begin(), dimInfo.end(), + [&dim](const FileDimInfo& fdi) { return fdi.dim == dim; }); + + if (it == dimInfo.end()) return false; + + return true; + }; + + // Set the pointFormatId based on whether or not colors exist in the + // file + int old (m_b.opts.pointFormatId); + + if (check_dimension_exists(pdal::Dimension::Id::Infrared, m_b.dimInfo)) + { + m_b.opts.pointFormatId = 8; + } else if (check_dimension_exists(pdal::Dimension::Id::Red, m_b.dimInfo) || + check_dimension_exists(pdal::Dimension::Id::Green, m_b.dimInfo) || + check_dimension_exists(pdal::Dimension::Id::Blue, m_b.dimInfo)) + { + m_b.opts.pointFormatId = 7; + } else + { + m_b.opts.pointFormatId = 6; + } + for (pdal::Dimension::Id id : layout->dims()) { FileDimInfo di; di.name = layout->dimName(id); di.type = layout->dimType(id); di.offset = layout->dimOffset(id); + di.dim = id; m_b.pointSize += pdal::Dimension::size(di.type); m_b.dimInfo.push_back(di); } @@ -192,6 +230,7 @@ void Epf::fillMetadata(const pdal::PointLayoutPtr layout) m_b.scale[0] = calcScale(m_b.scale[0], m_b.bounds.minx, m_b.bounds.maxx); m_b.scale[1] = calcScale(m_b.scale[1], m_b.bounds.miny, m_b.bounds.maxy); m_b.scale[2] = calcScale(m_b.scale[2], m_b.bounds.minz, m_b.bounds.maxz); + } PointCount Epf::createFileInfo(const StringList& input, StringList dimNames, diff --git a/untwine/Common.hpp b/untwine/Common.hpp index e131660..15ba37c 100644 --- a/untwine/Common.hpp +++ b/untwine/Common.hpp @@ -31,10 +31,14 @@ struct Options int progressFd; StringList dimNames; bool stats; + int pointFormatId; }; struct BaseInfo { +public: + BaseInfo() {}; + Options opts; pdal::BOX3D bounds; pdal::BOX3D trueBounds; @@ -46,6 +50,7 @@ struct BaseInfo using d3 = std::array; d3 scale { -1.0, -1.0, -1.0 }; d3 offset {}; + }; const std::string MetadataFilename {"info2.txt"}; diff --git a/untwine/FileDimInfo.hpp b/untwine/FileDimInfo.hpp index 600ffc1..6c3ab96 100644 --- a/untwine/FileDimInfo.hpp +++ b/untwine/FileDimInfo.hpp @@ -29,7 +29,9 @@ struct FileDimInfo pdal::Dimension::Type type; int offset; pdal::Dimension::Id dim; + }; + using DimInfoList = std::vector; inline std::ostream& operator<<(std::ostream& out, const FileDimInfo& fdi)