24#include "qgspointcloudexpression.h"
31using namespace Qt::StringLiterals;
38 const std::size_t requestedPointRecordSize = requestedAttributes.
pointRecordSize();
39 const int count = dataUncompressed.size() / pointRecordSize;
41 data.resize( requestedPointRecordSize * count );
42 char *destinationBuffer = data.data();
43 const char *s = dataUncompressed.data();
45 const QVector<QgsPointCloudAttribute> requestedAttributesVector = requestedAttributes.
attributes();
52 : inputOffset( inputOffset )
53 , inputSize( inputSize )
54 , inputType( inputType )
55 , requestedSize( requestedSize )
56 , requestedType( requestedType )
66 std::vector< AttributeData > attributeData;
67 attributeData.reserve( requestedAttributesVector.size() );
70 int inputAttributeOffset;
72 if ( !inputAttribute )
76 attributeData.emplace_back( AttributeData( inputAttributeOffset, inputAttribute->
size(), inputAttribute->
type(),
77 requestedAttribute.size(), requestedAttribute.type() ) );
80 int skippedPoints = 0;
81 auto block = std::make_unique< QgsPointCloudBlock >(
87 const bool filterIsValid = filterExpression.isValid();
88 if ( !filterExpression.prepare( block.get() ) && filterIsValid )
91 block->setPointCount( 0 );
95 int xAttributeOffset, yAttributeOffset;
98 const bool hasFilterRect = !filterRect.
isEmpty();
101 attributeX = requestedAttributes.
find(
"X"_L1, xAttributeOffset );
102 attributeY = requestedAttributes.
find(
"Y"_L1, yAttributeOffset );
110 size_t outputOffset = 0;
111 for (
int i = 0; i < count; ++i )
113 for (
const AttributeData &attribute : attributeData )
115 lazSerialize_( destinationBuffer, outputOffset,
116 attribute.requestedType, s,
117 attribute.inputType, attribute.inputSize, i * pointRecordSize + attribute.inputOffset );
119 outputOffset += attribute.requestedSize;
123 bool skipThisPoint =
false;
124 if ( hasFilterRect && attributeX && attributeY )
126 const double x = attributeX->
convertValueToDouble( destinationBuffer + outputOffset - requestedPointRecordSize + xAttributeOffset );
127 const double y = attributeY->
convertValueToDouble( destinationBuffer + outputOffset - requestedPointRecordSize + yAttributeOffset );
129 skipThisPoint =
true;
131 if ( !skipThisPoint && filterIsValid )
134 double eval = filterExpression.evaluate( i - skippedPoints );
135 if ( !eval || std::isnan( eval ) )
136 skipThisPoint =
true;
141 outputOffset -= requestedPointRecordSize;
145 block->setPointCount( count - skippedPoints );
151 if ( ! QFile::exists( filename ) )
155 const bool r = f.open( QIODevice::ReadOnly );
159 const QByteArray dataUncompressed = f.read( f.size() );
160 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
165 return decompressBinary_( data, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
170QByteArray decompressZtdStream(
const QByteArray &dataCompressed )
175 const int MAXSIZE = 10000000;
176 QByteArray dataUncompressed;
177 dataUncompressed.resize( MAXSIZE );
179 ZSTD_DStream *strm = ZSTD_createDStream();
180 ZSTD_initDStream( strm );
182 ZSTD_inBuffer m_inBuf;
183 m_inBuf.src =
reinterpret_cast<const void *
>( dataCompressed.constData() );
184 m_inBuf.size = dataCompressed.size();
187 ZSTD_outBuffer outBuf {
reinterpret_cast<void *
>( dataUncompressed.data() ), MAXSIZE, 0 };
188 const size_t ret = ZSTD_decompressStream( strm, &outBuf, &m_inBuf );
189 Q_ASSERT( !ZSTD_isError( ret ) );
190 Q_ASSERT( outBuf.pos );
191 Q_ASSERT( outBuf.pos < outBuf.size );
193 ZSTD_freeDStream( strm );
194 dataUncompressed.resize( outBuf.pos );
195 return dataUncompressed;
200 if ( ! QFile::exists( filename ) )
204 const bool r = f.open( QIODevice::ReadOnly );
208 const QByteArray dataCompressed = f.readAll();
209 const QByteArray dataUncompressed = decompressZtdStream( dataCompressed );
210 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
215 const QByteArray dataUncompressed = decompressZtdStream( data );
216 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.