예제 #1
0
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;
}
예제 #2
0
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;
}