bool LasWriter::writeLasZipBuf(PointRef& point) { #ifdef PDAL_HAVE_LASZIP const bool has14Format = m_lasHeader.has14Format(); const size_t maxReturnCount = m_lasHeader.maxReturnCount(); // we always write the base fields using namespace Dimension; uint8_t returnNumber(1); uint8_t numberOfReturns(1); if (point.hasDim(Id::ReturnNumber)) returnNumber = point.getFieldAs<uint8_t>(Id::ReturnNumber); if (point.hasDim(Id::NumberOfReturns)) numberOfReturns = point.getFieldAs<uint8_t>(Id::NumberOfReturns); if (numberOfReturns > maxReturnCount) { if (m_discardHighReturnNumbers) { // If this return number is too high, pitch the point. if (returnNumber > maxReturnCount) return false; numberOfReturns = maxReturnCount; } } auto converter = [this](double d, Dimension::Id dim) -> int32_t { int32_t i(0); if (!Utils::numericCast(d, i)) throwError("Unable to convert scaled value (" + Utils::toString(d) + ") to " "int32 for dimension '" + Dimension::name(dim) + "' when writing LAS/LAZ file " + m_curFilename + "."); return i; }; double xOrig = point.getFieldAs<double>(Id::X); double yOrig = point.getFieldAs<double>(Id::Y); double zOrig = point.getFieldAs<double>(Id::Z); double x = m_scaling.m_xXform.toScaled(xOrig); double y = m_scaling.m_yXform.toScaled(yOrig); double z = m_scaling.m_zXform.toScaled(zOrig); uint8_t scanChannel = point.getFieldAs<uint8_t>(Id::ScanChannel); uint8_t scanDirectionFlag = point.getFieldAs<uint8_t>(Id::ScanDirectionFlag); uint8_t edgeOfFlightLine = point.getFieldAs<uint8_t>(Id::EdgeOfFlightLine); uint8_t classification = point.getFieldAs<uint8_t>(Id::Classification); uint8_t classFlags = 0; if (point.hasDim(Id::ClassFlags)) classFlags = point.getFieldAs<uint8_t>(Id::ClassFlags); else classFlags = classification >> 5; laszip_point_struct p; p.X = converter(x, Id::X); p.Y = converter(y, Id::Y); p.Z = converter(z, Id::Z); p.intensity = point.getFieldAs<uint16_t>(Id::Intensity); p.scan_direction_flag = scanDirectionFlag; p.edge_of_flight_line = edgeOfFlightLine; if (has14Format) { p.extended_point_type = 1; p.extended_return_number = returnNumber; p.extended_number_of_returns = numberOfReturns; p.extended_scanner_channel = scanChannel; p.extended_scan_angle = roundf(point.getFieldAs<float>(Id::ScanAngleRank) / .006); p.extended_classification_flags = classFlags; p.extended_classification = classification; p.classification = (classification & 0x1F) | (classFlags << 5); // p.scan_angle_rank = point.getFieldAs<int8_t>(Id::ScanAngleRank); } else { p.synthetic_flag = classFlags & 0x1; p.keypoint_flag = (classFlags >> 1) & 0x1; p.withheld_flag = (classFlags >> 2) & 0x1; p.return_number = returnNumber; p.number_of_returns = numberOfReturns; p.scan_angle_rank = point.getFieldAs<int8_t>(Id::ScanAngleRank); p.classification = classification; } p.user_data = point.getFieldAs<uint8_t>(Id::UserData); p.point_source_ID = point.getFieldAs<uint16_t>(Id::PointSourceId); if (m_lasHeader.hasTime()) p.gps_time = point.getFieldAs<double>(Id::GpsTime); if (m_lasHeader.hasColor()) { p.rgb[0] = point.getFieldAs<uint16_t>(Id::Red); p.rgb[1] = point.getFieldAs<uint16_t>(Id::Green); p.rgb[2] = point.getFieldAs<uint16_t>(Id::Blue); } if (m_lasHeader.hasInfrared()) p.rgb[3] = point.getFieldAs<uint16_t>(Id::Infrared); if (m_extraDims.size()) { LeInserter ostream(m_pointBuf.data(), m_pointBuf.size()); Everything e; for (auto& dim : m_extraDims) { point.getField((char *)&e, dim.m_dimType.m_id, dim.m_dimType.m_type); Utils::insertDim(ostream, dim.m_dimType.m_type, e); } assert(m_extraByteLen == ostream.position()); } p.extra_bytes = (laszip_U8 *)m_pointBuf.data(); p.num_extra_bytes = m_extraByteLen; m_summaryData->addPoint(xOrig, yOrig, zOrig, returnNumber); handleLaszip(laszip_set_point(m_laszip, &p)); handleLaszip(laszip_write_point(m_laszip)); #endif return true; }
bool LasWriter::fillPointBuf(PointRef& point, LeInserter& ostream) { bool has14Format = m_lasHeader.has14Format(); static const size_t maxReturnCount = m_lasHeader.maxReturnCount(); // we always write the base fields using namespace Dimension; uint8_t returnNumber(1); uint8_t numberOfReturns(1); if (point.hasDim(Id::ReturnNumber)) returnNumber = point.getFieldAs<uint8_t>(Id::ReturnNumber); if (point.hasDim(Id::NumberOfReturns)) numberOfReturns = point.getFieldAs<uint8_t>(Id::NumberOfReturns); if (numberOfReturns > maxReturnCount) { if (m_discardHighReturnNumbers) { // If this return number is too high, pitch the point. if (returnNumber > maxReturnCount) return false; numberOfReturns = maxReturnCount; } } auto converter = [this](double d, Dimension::Id dim) -> int32_t { int32_t i(0); if (!Utils::numericCast(d, i)) throwError("Unable to convert scaled value (" + Utils::toString(d) + ") to " "int32 for dimension '" + Dimension::name(dim) + "' when writing LAS/LAZ file " + m_curFilename + "."); return i; }; double xOrig = point.getFieldAs<double>(Id::X); double yOrig = point.getFieldAs<double>(Id::Y); double zOrig = point.getFieldAs<double>(Id::Z); double x = m_scaling.m_xXform.toScaled(xOrig); double y = m_scaling.m_yXform.toScaled(yOrig); double z = m_scaling.m_zXform.toScaled(zOrig); ostream << converter(x, Id::X); ostream << converter(y, Id::Y); ostream << converter(z, Id::Z); ostream << point.getFieldAs<uint16_t>(Id::Intensity); uint8_t scanChannel = point.getFieldAs<uint8_t>(Id::ScanChannel); uint8_t scanDirectionFlag = point.getFieldAs<uint8_t>(Id::ScanDirectionFlag); uint8_t edgeOfFlightLine = point.getFieldAs<uint8_t>(Id::EdgeOfFlightLine); if (has14Format) { uint8_t bits = returnNumber | (numberOfReturns << 4); ostream << bits; uint8_t classFlags = point.getFieldAs<uint8_t>(Id::ClassFlags); bits = (classFlags & 0x0F) | ((scanChannel & 0x03) << 4) | ((scanDirectionFlag & 0x01) << 6) | ((edgeOfFlightLine & 0x01) << 7); ostream << bits; } else { uint8_t bits = returnNumber | (numberOfReturns << 3) | (scanDirectionFlag << 6) | (edgeOfFlightLine << 7); ostream << bits; } ostream << point.getFieldAs<uint8_t>(Id::Classification); uint8_t userData = point.getFieldAs<uint8_t>(Id::UserData); if (has14Format) { int16_t scanAngleRank = point.getFieldAs<float>(Id::ScanAngleRank) / .006; ostream << userData << scanAngleRank; } else { int8_t scanAngleRank = point.getFieldAs<int8_t>(Id::ScanAngleRank); ostream << scanAngleRank << userData; } ostream << point.getFieldAs<uint16_t>(Id::PointSourceId); if (m_lasHeader.hasTime()) ostream << point.getFieldAs<double>(Id::GpsTime); if (m_lasHeader.hasColor()) { ostream << point.getFieldAs<uint16_t>(Id::Red); ostream << point.getFieldAs<uint16_t>(Id::Green); ostream << point.getFieldAs<uint16_t>(Id::Blue); } if (m_lasHeader.hasInfrared()) ostream << point.getFieldAs<uint16_t>(Id::Infrared); Everything e; for (auto& dim : m_extraDims) { point.getField((char *)&e, dim.m_dimType.m_id, dim.m_dimType.m_type); Utils::insertDim(ostream, dim.m_dimType.m_type, e); } m_summaryData->addPoint(xOrig, yOrig, zOrig, returnNumber); return true; }