From 9b438bcaab3a04b4aaa4ec623e30c3efe81898fc Mon Sep 17 00:00:00 2001 From: Andrew Bell Date: Tue, 9 Feb 2021 13:21:23 -0500 Subject: [PATCH] Remove LASzip from public headers (#3347) * Move some private stuff from the LasReader header file to a struct in the cpp file. * Fix guarded LAZperf code. * Use args for guardec compression. * Fix compression name. --- io/LasReader.cpp | 300 ++++++++++++++++++++------------- io/LasReader.hpp | 58 ++----- test/unit/apps/pc2pcTest.cpp | 1 + test/unit/io/LasReaderTest.cpp | 1 + 4 files changed, 201 insertions(+), 159 deletions(-) diff --git a/io/LasReader.cpp b/io/LasReader.cpp index b654017dd2..a1834e5857 100644 --- a/io/LasReader.cpp +++ b/io/LasReader.cpp @@ -34,7 +34,9 @@ #include +#include "LasHeader.hpp" #include "LasReader.hpp" +#include "LasUtils.hpp" #include #include @@ -51,6 +53,14 @@ #include "LasHeader.hpp" #include "LasVLR.hpp" +#ifdef PDAL_HAVE_LASZIP +#include +#else +using laszip_POINTER = void *; +using laszip_point_struct = void *; +struct laszip_point; +#endif + namespace pdal { @@ -65,14 +75,41 @@ struct invalid_stream : public std::runtime_error } // unnamed namespace -LasReader::LasReader() : m_decompressor(nullptr), m_index(0) +struct LasReader::Args +{ +public: + StringList extraDimSpec; + std::string compression; + bool useEbVlr; + StringList ignoreVLROption; + bool fixNames; +}; + +struct LasReader::Private +{ + typedef std::vector IgnoreVLRList; + + LasHeader header; + laszip_POINTER laszip; + laszip_point_struct *laszipPoint; + LazPerfVlrDecompressor *decompressor; + std::vector decompressorBuf; + point_count_t index; + IgnoreVLRList ignoreVLRs; + std::vector extraDims; + + Private() : decompressor(nullptr), index(0) + {} +}; + +LasReader::LasReader() : m_args(new Args), m_p(new Private) {} LasReader::~LasReader() { #ifdef PDAL_HAVE_LAZPERF - delete m_decompressor; + delete m_p->decompressor; #endif } @@ -80,13 +117,13 @@ LasReader::~LasReader() void LasReader::addArgs(ProgramArgs& args) { args.add("extra_dims", "Dimensions to assign to extra byte data", - m_extraDimSpec); - args.add("compression", "Decompressor to use", m_compression, "EITHER"); + m_args->extraDimSpec); + args.add("compression", "Decompressor to use", m_args->compression, "EITHER"); args.add("use_eb_vlr", "Use extra bytes VLR for 1.0 - 1.3 files", - m_useEbVlr); - args.add("ignore_vlr", "VLR userid/recordid to ignore", m_ignoreVLROption); + m_args->useEbVlr); + args.add("ignore_vlr", "VLR userid/recordid to ignore", m_args->ignoreVLROption); args.add("fix_dims", "Make invalid dimension names valid by changing " - "invalid characters to '_'", m_fixNames, true); + "invalid characters to '_'", m_args->fixNames, true); } @@ -103,6 +140,21 @@ CREATE_STATIC_STAGE(LasReader, s_info) std::string LasReader::getName() const { return s_info.name; } +const LasHeader& LasReader::header() const +{ + return m_p->header; +} + +point_count_t LasReader::getNumPoints() const +{ + return m_p->header.pointCount(); +} + +void LasReader::initialize(PointTableRef table) +{ + initializeLocal(table, m_metadata); +} + QuickInfo LasReader::inspect() { QuickInfo qi; @@ -115,9 +167,9 @@ QuickInfo LasReader::inspect() Dimension::IdList dims = layout->dims(); for (auto di = dims.begin(); di != dims.end(); ++di) qi.m_dimNames.push_back(layout->dimName(*di)); - if (!Utils::numericCast(m_header.pointCount(), qi.m_pointCount)) + if (!Utils::numericCast(m_p->header.pointCount(), qi.m_pointCount)) qi.m_pointCount = (std::numeric_limits::max)(); - qi.m_bounds = m_header.getBounds(); + qi.m_bounds = m_p->header.getBounds(); qi.m_srs = getSpatialReference(); qi.m_valid = true; @@ -129,7 +181,7 @@ QuickInfo LasReader::inspect() void LasReader::handleCompressionOption() { - std::string compression = Utils::toupper(m_compression); + std::string compression = Utils::toupper(m_args->compression); #if defined(PDAL_HAVE_LAZPERF) && defined(PDAL_HAVE_LASZIP) if (compression == "EITHER") compression = "LASZIP"; @@ -152,11 +204,11 @@ void LasReader::handleCompressionOption() #if defined(PDAL_HAVE_LAZPERF) || defined(PDAL_HAVE_LASZIP) if (compression != "LAZPERF" && compression != "LASZIP") throwError("Invalid value for option for compression: '" + - m_compression + "'. Value values are 'lazperf' and 'laszip'."); + m_args->compression + "'. Value values are 'lazperf' and 'laszip'."); #endif // Set case-corrected value. - m_compression = compression; + m_args->compression = compression; } void LasReader::createStream() @@ -178,7 +230,7 @@ void LasReader::initializeLocal(PointTableRef table, MetadataNode& m) { try { - m_extraDims = LasUtils::parse(m_extraDimSpec, false); + m_p->extraDims = LasUtils::parse(m_args->extraDimSpec, false); } catch (const LasUtils::error& err) { @@ -187,14 +239,14 @@ void LasReader::initializeLocal(PointTableRef table, MetadataNode& m) try { - m_ignoreVLRs = LasUtils::parseIgnoreVLRs(m_ignoreVLROption); + m_p->ignoreVLRs = LasUtils::parseIgnoreVLRs(m_args->ignoreVLROption); } catch (const LasUtils::error& err) { throwError(err.what()); } - m_header.initialize(log(), FileUtils::fileSize(m_filename)); + m_p->header.initialize(log(), FileUtils::fileSize(m_filename)); createStream(); std::istream *stream(m_streamIf->m_istream); @@ -203,32 +255,32 @@ void LasReader::initializeLocal(PointTableRef table, MetadataNode& m) try { // This also reads the extended VLRs at the end of the data. - in >> m_header; + in >> m_p->header; } catch (const LasHeader::error& e) { throwError(e.what()); } - for (auto i: m_ignoreVLRs) + for (auto i: m_p->ignoreVLRs) { if (i.m_recordId) - m_header.removeVLR(i.m_userId, i.m_recordId); + m_p->header.removeVLR(i.m_userId, i.m_recordId); else - m_header.removeVLR(i.m_userId); + m_p->header.removeVLR(i.m_userId); } - if (m_header.compressed()) + if (m_p->header.compressed()) handleCompressionOption(); #ifdef PDAL_HAVE_LASZIP - m_laszip = nullptr; + m_p->laszip = nullptr; #endif - if (!m_header.pointFormatSupported()) + if (!m_p->header.pointFormatSupported()) throwError("Unsupported LAS input point format: " + - Utils::toString((int)m_header.pointFormat()) + "."); + Utils::toString((int)m_p->header.pointFormat()) + "."); - if (m_header.versionAtLeast(1, 4) || m_useEbVlr) + if (m_p->header.versionAtLeast(1, 4) || m_args->useEbVlr) readExtraBytesVlr(); setSrs(m); MetadataNode forward = table.privateMetadata("lasforward"); @@ -245,7 +297,7 @@ void LasReader::handleLaszip(int result) if (result) { char *buf; - laszip_get_error(m_laszip, &buf); + laszip_get_error(m_p->laszip, &buf); throwError(buf); } #endif @@ -257,33 +309,33 @@ void LasReader::ready(PointTableRef table) createStream(); std::istream *stream(m_streamIf->m_istream); - m_index = 0; - if (m_header.compressed()) + m_p->index = 0; + if (m_p->header.compressed()) { #ifdef PDAL_HAVE_LASZIP - if (m_compression == "LASZIP") + if (m_args->compression == "LASZIP") { laszip_BOOL compressed; - handleLaszip(laszip_create(&m_laszip)); - handleLaszip(laszip_open_reader_stream(m_laszip, *stream, + handleLaszip(laszip_create(&m_p->laszip)); + handleLaszip(laszip_open_reader_stream(m_p->laszip, *stream, &compressed)); - handleLaszip(laszip_get_point_pointer(m_laszip, &m_laszipPoint)); + handleLaszip(laszip_get_point_pointer(m_p->laszip, &m_p->laszipPoint)); } #endif #ifdef PDAL_HAVE_LAZPERF - if (m_compression == "LAZPERF") + if (m_args->compression == "LAZPERF") { - delete m_decompressor; + delete m_p->decompressor; - const LasVLR *vlr = m_header.findVlr(LASZIP_USER_ID, + const LasVLR *vlr = m_p->header.findVlr(LASZIP_USER_ID, LASZIP_RECORD_ID); if (!vlr) throwError("LAZ file missing required laszip VLR."); - m_decompressor = new LazPerfVlrDecompressor(*stream, - vlr->data(), m_header.pointOffset()); - m_decompressorBuf.resize(m_decompressor->pointSize()); + m_p->decompressor = new LazPerfVlrDecompressor(*stream, + vlr->data(), m_p->header.pointOffset()); + m_p->decompressorBuf.resize(m_p->decompressor->pointSize()); } #endif @@ -293,7 +345,7 @@ void LasReader::ready(PointTableRef table) #endif } else - stream->seekg(m_header.pointOffset()); + stream->seekg(m_p->header.pointOffset()); } @@ -347,104 +399,104 @@ void addForwardMetadata(MetadataNode& forward, MetadataNode& m, void LasReader::extractHeaderMetadata(MetadataNode& forward, MetadataNode& m) { - m.add("compressed", m_header.compressed(), + m.add("compressed", m_p->header.compressed(), "true if this LAS file is compressed"); - addForwardMetadata(forward, m, "major_version", m_header.versionMajor(), + addForwardMetadata(forward, m, "major_version", m_p->header.versionMajor(), "The major LAS version for the file, always 1 for now"); - addForwardMetadata(forward, m, "minor_version", m_header.versionMinor(), + addForwardMetadata(forward, m, "minor_version", m_p->header.versionMinor(), "The minor LAS version for the file"); - addForwardMetadata(forward, m, "dataformat_id", m_header.pointFormat(), + addForwardMetadata(forward, m, "dataformat_id", m_p->header.pointFormat(), "LAS Point Data Format"); - if (m_header.versionAtLeast(1, 1)) + if (m_p->header.versionAtLeast(1, 1)) addForwardMetadata(forward, m, "filesource_id", - m_header.fileSourceId(), "File Source ID (Flight Line Number " + m_p->header.fileSourceId(), "File Source ID (Flight Line Number " "if this file was derived from an original flight line)."); - if (m_header.versionAtLeast(1, 2)) + if (m_p->header.versionAtLeast(1, 2)) { // For some reason we've written global encoding as a base 64 // encoded value in the past. In an effort to standardize things, // I'm writing this as a special value, and will also write // global_encoding like we write all other header metadata. - uint16_t globalEncoding = m_header.globalEncoding(); + uint16_t globalEncoding = m_p->header.globalEncoding(); m.addEncoded("global_encoding_base64", (uint8_t *)&globalEncoding, sizeof(globalEncoding), "Global Encoding: general property bit field."); addForwardMetadata(forward, m, "global_encoding", - m_header.globalEncoding(), + m_p->header.globalEncoding(), "Global Encoding: general property bit field."); } - addForwardMetadata(forward, m, "project_id", m_header.projectId(), + addForwardMetadata(forward, m, "project_id", m_p->header.projectId(), "Project ID."); - addForwardMetadata(forward, m, "system_id", m_header.systemId(), + addForwardMetadata(forward, m, "system_id", m_p->header.systemId(), "Generating system ID."); - addForwardMetadata(forward, m, "software_id", m_header.softwareId(), + addForwardMetadata(forward, m, "software_id", m_p->header.softwareId(), "Generating software description."); - addForwardMetadata(forward, m, "creation_doy", m_header.creationDOY(), + addForwardMetadata(forward, m, "creation_doy", m_p->header.creationDOY(), "Day, expressed as an unsigned short, on which this file was created. " "Day is computed as the Greenwich Mean Time (GMT) day. January 1 is " "considered day 1."); - addForwardMetadata(forward, m, "creation_year", m_header.creationYear(), + addForwardMetadata(forward, m, "creation_year", m_p->header.creationYear(), "The year, expressed as a four digit number, in which the file was " "created."); - addForwardMetadata(forward, m, "scale_x", m_header.scaleX(), + addForwardMetadata(forward, m, "scale_x", m_p->header.scaleX(), "The scale factor for X values.", 15); - addForwardMetadata(forward, m, "scale_y", m_header.scaleY(), + addForwardMetadata(forward, m, "scale_y", m_p->header.scaleY(), "The scale factor for Y values.", 15); - addForwardMetadata(forward, m, "scale_z", m_header.scaleZ(), + addForwardMetadata(forward, m, "scale_z", m_p->header.scaleZ(), "The scale factor for Z values.", 15); - addForwardMetadata(forward, m, "offset_x", m_header.offsetX(), + addForwardMetadata(forward, m, "offset_x", m_p->header.offsetX(), "The offset for X values.", 15); - addForwardMetadata(forward, m, "offset_y", m_header.offsetY(), + addForwardMetadata(forward, m, "offset_y", m_p->header.offsetY(), "The offset for Y values.", 15); - addForwardMetadata(forward, m, "offset_z", m_header.offsetZ(), + addForwardMetadata(forward, m, "offset_z", m_p->header.offsetZ(), "The offset for Z values.", 15); - m.add("point_length", m_header.pointLen(), + m.add("point_length", m_p->header.pointLen(), "The size, in bytes, of each point records."); - m.add("header_size", m_header.vlrOffset(), + m.add("header_size", m_p->header.vlrOffset(), "The size, in bytes, of the header block, including any extension " "by specific software."); - m.add("dataoffset", m_header.pointOffset(), + m.add("dataoffset", m_p->header.pointOffset(), "The actual number of bytes from the beginning of the file to the " "first field of the first point record data field. This data offset " "must be updated if any software adds data from the Public Header " "Block or adds/removes data to/from the Variable Length Records."); - m.add("minx", m_header.minX(), + m.add("minx", m_p->header.minX(), "The max and min data fields are the actual unscaled extents of the " "LAS point file data, specified in the coordinate system of the LAS " "data."); - m.add("miny", m_header.minY(), + m.add("miny", m_p->header.minY(), "The max and min data fields are the actual unscaled extents of the " "LAS point file data, specified in the coordinate system of the LAS " "data."); - m.add("minz", m_header.minZ(), + m.add("minz", m_p->header.minZ(), "The max and min data fields are the actual unscaled extents of the " "LAS point file data, specified in the coordinate system of the LAS " "data."); - m.add("maxx", m_header.maxX(), + m.add("maxx", m_p->header.maxX(), "The max and min data fields are the actual unscaled extents of the " "LAS point file data, specified in the coordinate system of the LAS " "data."); - m.add("maxy", m_header.maxY(), + m.add("maxy", m_p->header.maxY(), "The max and min data fields are the actual unscaled extents of the " "LAS point file data, specified in the coordinate system of the LAS " "data."); - m.add("maxz", m_header.maxZ(), + m.add("maxz", m_p->header.maxZ(), "The max and min data fields are the actual unscaled extents of the " "LAS point file data, specified in the coordinate system of the LAS " "data."); m.add("count", - m_header.pointCount(), "This field contains the total " + m_p->header.pointCount(), "This field contains the total " "number of point records within the file."); - m.add("gtiff", m_header.geotiffPrint(), + m.add("gtiff", m_p->header.geotiffPrint(), "GTifPrint output of GeoTIFF keys"); // PDAL metadata VLR - const LasVLR *vlr = m_header.findVlr("PDAL", 12); + const LasVLR *vlr = m_p->header.findVlr("PDAL", 12); if (vlr) { const char *pos = vlr->data(); @@ -454,7 +506,7 @@ void LasReader::extractHeaderMetadata(MetadataNode& forward, MetadataNode& m) } // // PDAL pipeline VLR - vlr = m_header.findVlr("PDAL", 13); + vlr = m_p->header.findVlr("PDAL", 13); if (vlr) { const char *pos = vlr->data(); @@ -467,7 +519,7 @@ void LasReader::extractHeaderMetadata(MetadataNode& forward, MetadataNode& m) void LasReader::readExtraBytesVlr() { - const LasVLR *vlr = m_header.findVlr(SPEC_USER_ID, + const LasVLR *vlr = m_p->header.findVlr(SPEC_USER_ID, EXTRA_BYTES_RECORD_ID); if (!vlr) return; @@ -496,17 +548,17 @@ void LasReader::readExtraBytesVlr() for (auto& ed : eds) extraDims.push_back(std::move(ed)); } - if (m_extraDims.size() && m_extraDims != extraDims) + if (m_p->extraDims.size() && m_p->extraDims != extraDims) log()->get(LogLevel::Warning) << "Extra byte dimensions specified " "in pipeline and VLR don't match. Ignoring pipeline-specified " "dimensions"; - m_extraDims = extraDims; + m_p->extraDims = extraDims; } void LasReader::setSrs(MetadataNode& m) { - setSpatialReference(m, m_header.srs()); + setSpatialReference(m, m_p->header.srs()); } @@ -515,7 +567,7 @@ void LasReader::extractVlrMetadata(MetadataNode& forward, MetadataNode& m) static const size_t DATA_LEN_MAX = 1000000; int i = 0; - for (auto vlr : m_header.vlrs()) + for (auto vlr : m_p->header.vlrs()) { if (vlr.dataLen() > DATA_LEN_MAX) continue; @@ -563,30 +615,30 @@ void LasReader::addDimensions(PointLayoutPtr layout) layout->registerDim(Id::UserData, Type::Unsigned8); layout->registerDim(Id::PointSourceId, Type::Unsigned16); - if (m_header.hasTime()) + if (m_p->header.hasTime()) layout->registerDim(Id::GpsTime, Type::Double); - if (m_header.hasColor()) + if (m_p->header.hasColor()) { layout->registerDim(Id::Red, Type::Unsigned16); layout->registerDim(Id::Green, Type::Unsigned16); layout->registerDim(Id::Blue, Type::Unsigned16); } - if (m_header.hasInfrared()) + if (m_p->header.hasInfrared()) layout->registerDim(Id::Infrared); - if (m_header.has14Format()) + if (m_p->header.has14Format()) { layout->registerDim(Id::ScanChannel); layout->registerDim(Id::ClassFlags); } - for (auto& dim : m_extraDims) + for (auto& dim : m_p->extraDims) { Dimension::Type type = dim.m_dimType.m_type; if (type == Dimension::Type::None) continue; if (dim.m_dimType.m_xform.nonstandard()) type = Dimension::Type::Double; - if (m_fixNames) + if (m_args->fixNames) dim.m_name = Dimension::fixName(dim.m_name); dim.m_dimType.m_id = layout->registerOrAssignDim(dim.m_name, type); } @@ -595,26 +647,26 @@ void LasReader::addDimensions(PointLayoutPtr layout) bool LasReader::processOne(PointRef& point) { - if (m_index >= getNumPoints()) + if (m_p->index >= getNumPoints()) return false; - size_t pointLen = m_header.pointLen(); + size_t pointLen = m_p->header.pointLen(); - if (m_header.compressed()) + if (m_p->header.compressed()) { #ifdef PDAL_HAVE_LASZIP - if (m_compression == "LASZIP") + if (m_args->compression == "LASZIP") { - handleLaszip(laszip_read_point(m_laszip)); - loadPoint(point, *m_laszipPoint); + handleLaszip(laszip_read_point(m_p->laszip)); + loadPoint(point); } #endif #ifdef PDAL_HAVE_LAZPERF - if (m_compression == "LAZPERF") + if (m_args->compression == "LAZPERF") { - m_decompressor->decompress(m_decompressorBuf.data()); - loadPoint(point, m_decompressorBuf.data(), pointLen); + m_p->decompressor->decompress(m_p->decompressorBuf.data()); + loadPoint(point, m_p->decompressorBuf.data(), pointLen); } #endif #if !defined(PDAL_HAVE_LAZPERF) && !defined(PDAL_HAVE_LASZIP) @@ -624,26 +676,26 @@ bool LasReader::processOne(PointRef& point) } // compression else { - std::vector buf(m_header.pointLen()); + std::vector buf(m_p->header.pointLen()); m_streamIf->m_istream->read(buf.data(), pointLen); loadPoint(point, buf.data(), pointLen); } - m_index++; + m_p->index++; return true; } point_count_t LasReader::read(PointViewPtr view, point_count_t count) { - size_t pointLen = m_header.pointLen(); - count = (std::min)(count, getNumPoints() - m_index); + size_t pointLen = m_p->header.pointLen(); + count = (std::min)(count, getNumPoints() - m_p->index); PointId i = 0; - if (m_header.compressed()) + if (m_p->header.compressed()) { #if defined(PDAL_HAVE_LAZPERF) || defined(PDAL_HAVE_LASZIP) - if (m_compression == "LASZIP" || m_compression == "LAZPERF") + if (m_args->compression == "LASZIP" || m_args->compression == "LAZPERF") { for (i = 0; i < count; i++) { @@ -690,7 +742,7 @@ point_count_t LasReader::read(PointViewPtr view, point_count_t count) catch (invalid_stream&) {} } - m_index += i; + m_p->index += i; return (point_count_t)i; } @@ -700,7 +752,7 @@ point_count_t LasReader::readFileBlock(std::vector& buf, { std::istream *stream(m_streamIf->m_istream); - size_t ptLen = m_header.pointLen(); + size_t ptLen = m_p->header.pointLen(); point_count_t blockpoints = buf.size() / ptLen; blockpoints = (std::min)(maxpoints, blockpoints); @@ -720,19 +772,19 @@ point_count_t LasReader::readFileBlock(std::vector& buf, #ifdef PDAL_HAVE_LASZIP -void LasReader::loadPoint(PointRef& point, laszip_point& p) +void LasReader::loadPoint(PointRef& point) { - if (m_header.has14Format()) - loadPointV14(point, p); + if (m_p->header.has14Format()) + loadPointV14(point); else - loadPointV10(point, p); + loadPointV10(point); } #endif // PDAL_HAVE_LASZIP void LasReader::loadPoint(PointRef& point, char *buf, size_t bufsize) { - if (m_header.has14Format()) + if (m_p->header.has14Format()) loadPointV14(point, buf, bufsize); else loadPointV10(point, buf, bufsize); @@ -740,9 +792,12 @@ void LasReader::loadPoint(PointRef& point, char *buf, size_t bufsize) #ifdef PDAL_HAVE_LASZIP -void LasReader::loadPointV10(PointRef& point, laszip_point& p) +void LasReader::loadPointV10(PointRef& point) { - const LasHeader& h = m_header; + // We used to pass the laszip point as an argument, but this allows us to keep + // any laszip information out of LasReader.hpp. + laszip_point& p = *m_p->laszipPoint; + const LasHeader& h = m_p->header; double x = p.X * h.scaleX() + h.offsetX(); double y = p.Y * h.scaleY() + h.offsetY(); @@ -773,7 +828,7 @@ void LasReader::loadPointV10(PointRef& point, laszip_point& p) point.setField(Dimension::Id::Blue, p.rgb[2]); } - if (m_extraDims.size()) + if (m_p->extraDims.size()) { LeExtractor extractor((const char *)p.extra_bytes, p.num_extra_bytes); loadExtraDims(extractor, point); @@ -788,7 +843,7 @@ void LasReader::loadPointV10(PointRef& point, char *buf, size_t bufsize) int32_t xi, yi, zi; istream >> xi >> yi >> zi; - const LasHeader& h = m_header; + const LasHeader& h = m_p->header; double x = xi * h.scaleX() + h.offsetX(); double y = yi * h.scaleY() + h.offsetY(); @@ -838,15 +893,18 @@ void LasReader::loadPointV10(PointRef& point, char *buf, size_t bufsize) point.setField(Dimension::Id::Blue, blue); } - if (m_extraDims.size()) + if (m_p->extraDims.size()) loadExtraDims(istream, point); } #ifdef PDAL_HAVE_LASZIP -void LasReader::loadPointV14(PointRef& point, laszip_point& p) +void LasReader::loadPointV14(PointRef& point) { - const LasHeader& h = m_header; + // We used to pass the laszip point as an argument, but this allows us to keep + // any laszip information out of LasReader.hpp. + laszip_point& p = *m_p->laszipPoint; + const LasHeader& h = m_p->header; double x = p.X * h.scaleX() + h.offsetX(); double y = p.Y * h.scaleY() + h.offsetY(); @@ -881,7 +939,7 @@ void LasReader::loadPointV14(PointRef& point, laszip_point& p) point.setField(Dimension::Id::Infrared, p.rgb[3]); } - if (m_extraDims.size()) + if (m_p->extraDims.size()) { LeExtractor extractor((const char *)p.extra_bytes, p.num_extra_bytes); loadExtraDims(extractor, point); @@ -897,7 +955,7 @@ void LasReader::loadPointV14(PointRef& point, char *buf, size_t bufsize) int32_t xi, yi, zi; istream >> xi >> yi >> zi; - const LasHeader& h = m_header; + const LasHeader& h = m_p->header; double x = xi * h.scaleX() + h.offsetX(); double y = yi * h.scaleY() + h.offsetY(); @@ -955,14 +1013,14 @@ void LasReader::loadPointV14(PointRef& point, char *buf, size_t bufsize) point.setField(Dimension::Id::Infrared, nearInfraRed); } - if (m_extraDims.size()) + if (m_p->extraDims.size()) loadExtraDims(istream, point); } void LasReader::loadExtraDims(LeExtractor& istream, PointRef& point) { - for (auto& dim : m_extraDims) + for (auto& dim : m_p->extraDims) { // Dimension type of None is undefined and unprocessed if (dim.m_dimType.m_type == Dimension::Type::None) @@ -988,13 +1046,19 @@ void LasReader::loadExtraDims(LeExtractor& istream, PointRef& point) void LasReader::done(PointTableRef) { #ifdef PDAL_HAVE_LASZIP - if (m_laszip) + if (m_p->laszip) { - handleLaszip(laszip_close_reader(m_laszip)); - handleLaszip(laszip_destroy(m_laszip)); + handleLaszip(laszip_close_reader(m_p->laszip)); + handleLaszip(laszip_destroy(m_p->laszip)); } #endif m_streamIf.reset(); } +bool LasReader::eof() +{ + return m_p->index >= getNumPoints(); +} + + } // namespace pdal diff --git a/io/LasReader.hpp b/io/LasReader.hpp index 7780b551e9..00c9ab5994 100644 --- a/io/LasReader.hpp +++ b/io/LasReader.hpp @@ -34,23 +34,15 @@ #pragma once +#include + #include #include #include #include #include -#ifdef PDAL_HAVE_LASZIP -#include -#else -using laszip_POINTER = void *; -using laszip_point_struct = void *; -struct laszip_point; -#endif - -#include "LasError.hpp" -#include "LasHeader.hpp" -#include "LasUtils.hpp" +//#include "LasError.hpp" namespace pdal { @@ -87,13 +79,13 @@ class PDAL_DLL LasReader : public Reader, public Streamable public: LasReader(); ~LasReader(); + LasReader& operator=(const LasReader&) = delete; + LasReader(const LasReader&) = delete; std::string getName() const; - const LasHeader& header() const - { return m_header; } - point_count_t getNumPoints() const - { return m_header.pointCount(); } + const LasHeader& header() const; + point_count_t getNumPoints() const; protected: virtual void createStream(); @@ -101,26 +93,8 @@ class PDAL_DLL LasReader : public Reader, public Streamable std::unique_ptr m_streamIf; private: - typedef std::vector IgnoreVLRList; - - LasHeader m_header; - laszip_POINTER m_laszip; - laszip_point_struct *m_laszipPoint; - - LazPerfVlrDecompressor *m_decompressor; - std::vector m_decompressorBuf; - point_count_t m_index; - StringList m_extraDimSpec; - std::vector m_extraDims; - IgnoreVLRList m_ignoreVLRs; - std::string m_compression; - StringList m_ignoreVLROption; - bool m_useEbVlr; - bool m_fixNames; - virtual void addArgs(ProgramArgs& args); - virtual void initialize(PointTableRef table) - { initializeLocal(table, m_metadata); } + virtual void initialize(PointTableRef table); virtual void initializeLocal(PointTableRef table, MetadataNode& m); virtual void addDimensions(PointLayoutPtr layout); virtual QuickInfo inspect(); @@ -128,17 +102,16 @@ class PDAL_DLL LasReader : public Reader, public Streamable virtual point_count_t read(PointViewPtr view, point_count_t count); virtual bool processOne(PointRef& point); virtual void done(PointTableRef table); - virtual bool eof() - { return m_index >= getNumPoints(); } + virtual bool eof(); void handleCompressionOption(); void setSrs(MetadataNode& m); void readExtraBytesVlr(); void extractHeaderMetadata(MetadataNode& forward, MetadataNode& m); void extractVlrMetadata(MetadataNode& forward, MetadataNode& m); - void loadPoint(PointRef& point, laszip_point& p); - void loadPointV10(PointRef& point, laszip_point& p); - void loadPointV14(PointRef& point, laszip_point& p); + void loadPoint(PointRef& point); + void loadPointV10(PointRef& point); + void loadPointV14(PointRef& point); void loadPoint(PointRef& point, char *buf, size_t bufsize); void loadPointV10(PointRef& point, char *buf, size_t bufsize); void loadPointV14(PointRef& point, char *buf, size_t bufsize); @@ -147,8 +120,11 @@ class PDAL_DLL LasReader : public Reader, public Streamable point_count_t maxPoints); void handleLaszip(int result); - LasReader& operator=(const LasReader&); // not implemented - LasReader(const LasReader&); // not implemented + struct Args; + std::unique_ptr m_args; + + struct Private; + std::unique_ptr m_p; }; } // namespace pdal diff --git a/test/unit/apps/pc2pcTest.cpp b/test/unit/apps/pc2pcTest.cpp index 773443bc59..2493c64551 100644 --- a/test/unit/apps/pc2pcTest.cpp +++ b/test/unit/apps/pc2pcTest.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include "Support.hpp" using namespace pdal; diff --git a/test/unit/io/LasReaderTest.cpp b/test/unit/io/LasReaderTest.cpp index 0cd2e9b809..dcce7c5660 100644 --- a/test/unit/io/LasReaderTest.cpp +++ b/test/unit/io/LasReaderTest.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include "Support.hpp"