31#include <QElapsedTimer>
32#include <QTemporaryFile>
37#include "lazperf/las.hpp"
45 const std::size_t requestedPointRecordSize = requestedAttributes.
pointRecordSize();
46 const int count = dataUncompressed.size() / pointRecordSize;
48 data.resize( requestedPointRecordSize * count );
49 char *destinationBuffer = data.data();
50 const char *s = dataUncompressed.data();
52 const QVector<QgsPointCloudAttribute> requestedAttributesVector = requestedAttributes.
attributes();
59 : inputOffset( inputOffset )
60 , inputSize( inputSize )
61 , inputType( inputType )
62 , requestedSize( requestedSize )
63 , requestedType( requestedType )
73 std::vector< AttributeData > attributeData;
74 attributeData.reserve( requestedAttributesVector.size() );
77 int inputAttributeOffset;
79 if ( !inputAttribute )
83 attributeData.emplace_back( AttributeData( inputAttributeOffset, inputAttribute->
size(), inputAttribute->
type(),
84 requestedAttribute.size(), requestedAttribute.type() ) );
87 int skippedPoints = 0;
88 std::unique_ptr< QgsPointCloudBlock > block = std::make_unique< QgsPointCloudBlock >(
94 const bool filterIsValid = filterExpression.isValid();
95 if ( !filterExpression.prepare( block.get() ) && filterIsValid )
98 block->setPointCount( 0 );
99 return block.release();
103 size_t outputOffset = 0;
104 for (
int i = 0; i < count; ++i )
106 for (
const AttributeData &attribute : attributeData )
108 _lazSerialize( destinationBuffer, outputOffset,
109 attribute.requestedType, s,
110 attribute.inputType, attribute.inputSize, i * pointRecordSize + attribute.inputOffset );
112 outputOffset += attribute.requestedSize;
119 double eval = filterExpression.evaluate( i - skippedPoints );
120 if ( !eval || std::isnan( eval ) )
123 outputOffset -= requestedPointRecordSize;
128 block->setPointCount( count - skippedPoints );
129 return block.release();
134 if ( ! QFile::exists( filename ) )
138 const bool r = f.open( QIODevice::ReadOnly );
142 const QByteArray dataUncompressed = f.read( f.size() );
143 return _decompressBinary( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression );
148 return _decompressBinary( data, attributes, requestedAttributes, scale, offset, filterExpression );
153QByteArray decompressZtdStream(
const QByteArray &dataCompressed )
158 const int MAXSIZE = 10000000;
159 QByteArray dataUncompressed;
160 dataUncompressed.resize( MAXSIZE );
162 ZSTD_DStream *strm = ZSTD_createDStream();
163 ZSTD_initDStream( strm );
165 ZSTD_inBuffer m_inBuf;
166 m_inBuf.src =
reinterpret_cast<const void *
>( dataCompressed.constData() );
167 m_inBuf.size = dataCompressed.size();
170 ZSTD_outBuffer outBuf {
reinterpret_cast<void *
>( dataUncompressed.data() ), MAXSIZE, 0 };
171 const size_t ret = ZSTD_decompressStream( strm, &outBuf, &m_inBuf );
172 Q_ASSERT( !ZSTD_isError( ret ) );
173 Q_ASSERT( outBuf.pos );
174 Q_ASSERT( outBuf.pos < outBuf.size );
176 ZSTD_freeDStream( strm );
177 dataUncompressed.resize( outBuf.pos );
178 return dataUncompressed;
183 if ( ! QFile::exists( filename ) )
187 const bool r = f.open( QIODevice::ReadOnly );
191 const QByteArray dataCompressed = f.readAll();
192 const QByteArray dataUncompressed = decompressZtdStream( dataCompressed );
193 return _decompressBinary( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression );
198 const QByteArray dataUncompressed = decompressZtdStream( data );
199 return _decompressBinary( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression );
Collection of point cloud attributes.
int pointRecordSize() const
Returns total size of record.
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
QVector< QgsPointCloudAttribute > attributes() const
Returns all attributes.
Attribute for point cloud data pair of name and size in bytes.
DataType
Systems of unit measurement.
int size() const
Returns size of the attribute in bytes.
DataType type() const
Returns the data type.
Base class for storing raw data from point cloud nodes.