24#include "qgspointcloudexpression.h"
31using namespace Qt::StringLiterals;
35std::unique_ptr<QgsPointCloudBlock> decompressBinary_(
36 const QByteArray &dataUncompressed,
41 QgsPointCloudExpression &filterExpression,
46 const std::size_t requestedPointRecordSize = requestedAttributes.
pointRecordSize();
47 const int count = dataUncompressed.size() / pointRecordSize;
49 data.resize( requestedPointRecordSize * count );
50 char *destinationBuffer = data.data();
51 const char *s = dataUncompressed.data();
53 const QVector<QgsPointCloudAttribute> requestedAttributesVector = requestedAttributes.
attributes();
60 : inputOffset( inputOffset )
61 , inputSize( inputSize )
62 , inputType( inputType )
63 , requestedSize( requestedSize )
64 , requestedType( requestedType )
74 std::vector< AttributeData > attributeData;
75 attributeData.reserve( requestedAttributesVector.size() );
78 int inputAttributeOffset;
80 if ( !inputAttribute )
84 attributeData.emplace_back( AttributeData( inputAttributeOffset, inputAttribute->
size(), inputAttribute->
type(), requestedAttribute.size(), requestedAttribute.type() ) );
87 int skippedPoints = 0;
88 auto block = std::make_unique< QgsPointCloudBlock >( count, requestedAttributes, data, scale, offset );
90 const bool filterIsValid = filterExpression.isValid();
91 if ( !filterExpression.prepare( block.get() ) && filterIsValid )
94 block->setPointCount( 0 );
98 int xAttributeOffset, yAttributeOffset;
101 const bool hasFilterRect = !filterRect.
isEmpty();
104 attributeX = requestedAttributes.
find(
"X"_L1, xAttributeOffset );
105 attributeY = requestedAttributes.
find(
"Y"_L1, yAttributeOffset );
113 size_t outputOffset = 0;
114 for (
int i = 0; i < count; ++i )
116 for (
const AttributeData &attribute : attributeData )
118 lazSerialize_( destinationBuffer, outputOffset, attribute.requestedType, s, attribute.inputType, attribute.inputSize, i * pointRecordSize + attribute.inputOffset );
120 outputOffset += attribute.requestedSize;
124 bool skipThisPoint =
false;
125 if ( hasFilterRect && attributeX && attributeY )
127 const double x = attributeX->
convertValueToDouble( destinationBuffer + outputOffset - requestedPointRecordSize + xAttributeOffset );
128 const double y = attributeY->
convertValueToDouble( destinationBuffer + outputOffset - requestedPointRecordSize + yAttributeOffset );
130 skipThisPoint =
true;
132 if ( !skipThisPoint && filterIsValid )
135 double eval = filterExpression.evaluate( i - skippedPoints );
136 if ( !eval || std::isnan( eval ) )
137 skipThisPoint =
true;
142 outputOffset -= requestedPointRecordSize;
146 block->setPointCount( count - skippedPoints );
150std::unique_ptr<QgsPointCloudBlock> QgsEptDecoder::decompressBinary(
151 const QString &filename,
156 QgsPointCloudExpression &filterExpression,
160 if ( !QFile::exists( filename ) )
164 const bool r = f.open( QIODevice::ReadOnly );
168 const QByteArray dataUncompressed = f.read( f.size() );
169 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
172std::unique_ptr<QgsPointCloudBlock> QgsEptDecoder::decompressBinary(
173 const QByteArray &data,
178 QgsPointCloudExpression &filterExpression,
182 return decompressBinary_( data, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
187QByteArray decompressZtdStream(
const QByteArray &dataCompressed )
192 const int MAXSIZE = 10000000;
193 QByteArray dataUncompressed;
194 dataUncompressed.resize( MAXSIZE );
196 ZSTD_DStream *strm = ZSTD_createDStream();
197 ZSTD_initDStream( strm );
199 ZSTD_inBuffer m_inBuf;
200 m_inBuf.src =
reinterpret_cast<const void *
>( dataCompressed.constData() );
201 m_inBuf.size = dataCompressed.size();
204 ZSTD_outBuffer outBuf {
reinterpret_cast<void *
>( dataUncompressed.data() ), MAXSIZE, 0 };
205 const size_t ret = ZSTD_decompressStream( strm, &outBuf, &m_inBuf );
206 Q_ASSERT( !ZSTD_isError( ret ) );
207 Q_ASSERT( outBuf.pos );
208 Q_ASSERT( outBuf.pos < outBuf.size );
210 ZSTD_freeDStream( strm );
211 dataUncompressed.resize( outBuf.pos );
212 return dataUncompressed;
215std::unique_ptr<QgsPointCloudBlock> QgsEptDecoder::decompressZStandard(
216 const QString &filename,
221 QgsPointCloudExpression &filterExpression,
225 if ( !QFile::exists( filename ) )
229 const bool r = f.open( QIODevice::ReadOnly );
233 const QByteArray dataCompressed = f.readAll();
234 const QByteArray dataUncompressed = decompressZtdStream( dataCompressed );
235 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
238std::unique_ptr<QgsPointCloudBlock> QgsEptDecoder::decompressZStandard(
239 const QByteArray &data,
244 QgsPointCloudExpression &filterExpression,
248 const QByteArray dataUncompressed = decompressZtdStream( data );
249 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
A 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.
double convertValueToDouble(const char *ptr) const
Returns the attribute's value as a double for data pointed to by ptr.
A rectangle specified with double values.
bool contains(const QgsRectangle &rect) const
Returns true when rectangle contains other rectangle.
void setYMinimum(double y)
Set the minimum y value.
void setXMinimum(double x)
Set the minimum x value.
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
A 3D vector (similar to QVector3D) with the difference that it uses double precision instead of singl...
double y() const
Returns Y coordinate.
double x() const
Returns X coordinate.