| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- //##########################################################################
- //# #
- //# CLOUDCOMPARE PLUGIN: LAS-IO Plugin #
- //# #
- //# This program is free software; you can redistribute it and/or modify #
- //# it under the terms of the GNU General Public License as published by #
- //# the Free Software Foundation; version 2 of the License. #
- //# #
- //# This program is distributed in the hope that it will be useful, #
- //# but WITHOUT ANY WARRANTY; without even the implied warranty of #
- //# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
- //# GNU General Public License for more details. #
- //# #
- //# COPYRIGHT: Thomas Montaigu #
- //# #
- //##########################################################################
- #include "LasScalarFieldSaver.h"
- #include <ccScalarField.h>
- #include <laszip/laszip_api.h>
- LasScalarFieldSaver::LasScalarFieldSaver(std::vector<LasScalarField>&& standardFields,
- std::vector<LasExtraScalarField>&& extraFields)
- : m_standardFields(standardFields)
- , m_extraFields(extraFields)
- {
- }
- void LasScalarFieldSaver::handleScalarFields(size_t pointIndex, laszip_point& point)
- {
- for (const LasScalarField& field : m_standardFields)
- {
- Q_ASSERT_X(field.sf != nullptr, __func__, "LasScalarField has a null ptr to ccScalarField");
- ScalarType value = field.sf->getValue(pointIndex);
- value = std::max(field.range.min, value);
- value = std::min(field.range.max, value);
- switch (field.id)
- {
- case LasScalarField::Intensity:
- if (field.sf)
- {
- point.intensity = static_cast<laszip_U16>(value);
- }
- break;
- case LasScalarField::ReturnNumber:
- if (field.sf)
- {
- point.return_number = static_cast<laszip_U8>(value);
- }
- break;
- case LasScalarField::NumberOfReturns:
- if (field.sf)
- {
- point.number_of_returns = static_cast<laszip_U8>(value);
- }
- break;
- case LasScalarField::ScanDirectionFlag:
- if (field.sf)
- {
- point.scan_direction_flag = (static_cast<laszip_U8>(value) != 0);
- }
- break;
- case LasScalarField::EdgeOfFlightLine:
- if (field.sf)
- {
- point.edge_of_flight_line = (static_cast<laszip_U8>(value) != 0);
- }
- break;
- case LasScalarField::Classification:
- if (field.sf)
- {
- // Before entering the switch, the value is 'clamped',
- // for the following to work we need the non-clamped value
- laszip_U8 valueU8 = static_cast<laszip_U8>(field.sf->getValue(pointIndex));
- point.classification = valueU8 & 31;
- if (!m_classificationWasDecomposed)
- {
- point.synthetic_flag = (valueU8 >> 5) & 1;
- point.keypoint_flag = (valueU8 >> 6) & 1;
- point.withheld_flag = (valueU8 >> 7) & 1;
- }
- }
- break;
- case LasScalarField::SyntheticFlag:
- if (field.sf)
- {
- point.synthetic_flag = (static_cast<laszip_U8>(value) != 0);
- }
- break;
- case LasScalarField::KeypointFlag:
- if (field.sf)
- {
- point.keypoint_flag = (static_cast<laszip_U8>(value) != 0);
- }
- break;
- case LasScalarField::WithheldFlag:
- if (field.sf)
- {
- point.withheld_flag = (static_cast<laszip_U8>(value) != 0);
- }
- break;
- case LasScalarField::ScanAngleRank:
- if (field.sf)
- {
- point.scan_angle_rank = static_cast<laszip_I8>(value);
- }
- case LasScalarField::UserData:
- if (field.sf)
- {
- point.user_data = static_cast<laszip_U8>(value);
- }
- break;
- case LasScalarField::PointSourceId:
- if (field.sf)
- {
- point.point_source_ID = static_cast<laszip_U16>(value);
- }
- break;
- case LasScalarField::GpsTime:
- if (field.sf)
- {
- point.gps_time = static_cast<laszip_F64>(value);
- }
- break;
- case LasScalarField::ExtendedScanAngle:
- if (field.sf)
- {
- point.extended_scan_angle = static_cast<laszip_I16>(value / SCAN_ANGLE_SCALE);
- }
- break;
- case LasScalarField::ExtendedScannerChannel:
- if (field.sf)
- {
- point.extended_scanner_channel = static_cast<laszip_U8>(value);
- }
- break;
- case LasScalarField::OverlapFlag:
- if (field.sf)
- {
- point.extended_classification_flags |= (static_cast<laszip_U8>(value) != 0) ? LasDetails::OVERLAP_FLAG_BIT_MASK : 0;
- }
- break;
- case LasScalarField::ExtendedClassification:
- if (field.sf)
- {
- point.extended_classification = static_cast<laszip_U8>(value);
- }
- break;
- case LasScalarField::ExtendedReturnNumber:
- if (field.sf)
- {
- point.extended_return_number = static_cast<laszip_U16>(value);
- }
- break;
- case LasScalarField::ExtendedNumberOfReturns:
- if (field.sf)
- {
- point.extended_number_of_returns = static_cast<laszip_U16>(value);
- }
- break;
- case LasScalarField::NearInfrared:
- if (field.sf)
- {
- point.rgb[3] = static_cast<laszip_U16>(value);
- }
- break;
- }
- }
- }
- void LasScalarFieldSaver::handleExtraFields(size_t pointIndex, laszip_point& point)
- {
- if (point.num_extra_bytes == 0 || point.extra_bytes == nullptr)
- {
- return;
- }
- ScalarType values[LasExtraScalarField::MAX_DIM_SIZE] = {0.0};
- for (const LasExtraScalarField& extraField : m_extraFields)
- {
- laszip_U8* dataStart = point.extra_bytes + extraField.byteOffset;
- assert(extraField.byteOffset < static_cast<unsigned>(point.num_extra_bytes));
- assert(extraField.byteOffset + extraField.byteSize() <= static_cast<unsigned>(point.num_extra_bytes));
- for (size_t elemIndex{0}; elemIndex < extraField.numElements(); ++elemIndex)
- {
- values[elemIndex] = extraField.scalarFields[elemIndex]->getValue(pointIndex);
- }
- if (extraField.scaleIsRelevant() || extraField.offsetIsRelevant())
- {
- assert(extraField.numElements() <= 3);
- for (size_t elemIndex{0}; elemIndex < extraField.numElements(); ++elemIndex)
- {
- values[elemIndex] = (values[elemIndex] - extraField.offsets[elemIndex]) / extraField.scales[elemIndex];
- }
- }
- for (unsigned i = 0; i < extraField.numElements(); i++)
- {
- switch (extraField.type)
- {
- case LasExtraScalarField::u8:
- WriteScalarValueAs<uint8_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::u16:
- WriteScalarValueAs<uint16_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::u32:
- WriteScalarValueAs<uint32_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::u64:
- WriteScalarValueAs<uint64_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::i8:
- WriteScalarValueAs<int8_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::i16:
- WriteScalarValueAs<int16_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::i32:
- WriteScalarValueAs<int32_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::i64:
- WriteScalarValueAs<int64_t>(values[i], dataStart);
- break;
- case LasExtraScalarField::f32:
- WriteScalarValueAs<float>(values[i], dataStart);
- break;
- case LasExtraScalarField::f64:
- WriteScalarValueAs<double>(values[i], dataStart);
- break;
- case LasExtraScalarField::Undocumented:
- case LasExtraScalarField::Invalid:
- break;
- }
- dataStart += extraField.elementSize();
- }
- }
- }
|