22#include "qgspointcloudexpression.h"
35 const std::size_t requestedPointRecordSize = requestedAttributes.
pointRecordSize();
36 const int count = dataUncompressed.size() / pointRecordSize;
38 data.resize( requestedPointRecordSize * count );
39 char *destinationBuffer = data.data();
40 const char *s = dataUncompressed.data();
42 const QVector<QgsPointCloudAttribute> requestedAttributesVector = requestedAttributes.
attributes();
49 : inputOffset( inputOffset )
50 , inputSize( inputSize )
51 , inputType( inputType )
52 , requestedSize( requestedSize )
53 , requestedType( requestedType )
63 std::vector< AttributeData > attributeData;
64 attributeData.reserve( requestedAttributesVector.size() );
67 int inputAttributeOffset;
69 if ( !inputAttribute )
73 attributeData.emplace_back( AttributeData( inputAttributeOffset, inputAttribute->
size(), inputAttribute->
type(),
74 requestedAttribute.size(), requestedAttribute.type() ) );
77 int skippedPoints = 0;
78 std::unique_ptr< QgsPointCloudBlock > block = std::make_unique< QgsPointCloudBlock >(
84 const bool filterIsValid = filterExpression.isValid();
85 if ( !filterExpression.prepare( block.get() ) && filterIsValid )
88 block->setPointCount( 0 );
92 int xAttributeOffset, yAttributeOffset;
95 const bool hasFilterRect = !filterRect.
isEmpty();
98 attributeX = requestedAttributes.
find( QLatin1String(
"X" ), xAttributeOffset );
99 attributeY = requestedAttributes.
find( QLatin1String(
"Y" ), yAttributeOffset );
107 size_t outputOffset = 0;
108 for (
int i = 0; i < count; ++i )
110 for (
const AttributeData &attribute : attributeData )
112 lazSerialize_( destinationBuffer, outputOffset,
113 attribute.requestedType, s,
114 attribute.inputType, attribute.inputSize, i * pointRecordSize + attribute.inputOffset );
116 outputOffset += attribute.requestedSize;
120 bool skipThisPoint =
false;
121 if ( hasFilterRect && attributeX && attributeY )
123 const double x = attributeX->
convertValueToDouble( destinationBuffer + outputOffset - requestedPointRecordSize + xAttributeOffset );
124 const double y = attributeY->
convertValueToDouble( destinationBuffer + outputOffset - requestedPointRecordSize + yAttributeOffset );
126 skipThisPoint =
true;
128 if ( !skipThisPoint && filterIsValid )
131 double eval = filterExpression.evaluate( i - skippedPoints );
132 if ( !eval || std::isnan( eval ) )
133 skipThisPoint =
true;
138 outputOffset -= requestedPointRecordSize;
142 block->setPointCount( count - skippedPoints );
148 if ( ! QFile::exists( filename ) )
152 const bool r = f.open( QIODevice::ReadOnly );
156 const QByteArray dataUncompressed = f.read( f.size() );
157 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
162 return decompressBinary_( data, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
167QByteArray decompressZtdStream(
const QByteArray &dataCompressed )
172 const int MAXSIZE = 10000000;
173 QByteArray dataUncompressed;
174 dataUncompressed.resize( MAXSIZE );
176 ZSTD_DStream *strm = ZSTD_createDStream();
177 ZSTD_initDStream( strm );
179 ZSTD_inBuffer m_inBuf;
180 m_inBuf.src =
reinterpret_cast<const void *
>( dataCompressed.constData() );
181 m_inBuf.size = dataCompressed.size();
184 ZSTD_outBuffer outBuf {
reinterpret_cast<void *
>( dataUncompressed.data() ), MAXSIZE, 0 };
185 const size_t ret = ZSTD_decompressStream( strm, &outBuf, &m_inBuf );
186 Q_ASSERT( !ZSTD_isError( ret ) );
187 Q_ASSERT( outBuf.pos );
188 Q_ASSERT( outBuf.pos < outBuf.size );
190 ZSTD_freeDStream( strm );
191 dataUncompressed.resize( outBuf.pos );
192 return dataUncompressed;
197 if ( ! QFile::exists( filename ) )
201 const bool r = f.open( QIODevice::ReadOnly );
205 const QByteArray dataCompressed = f.readAll();
206 const QByteArray dataUncompressed = decompressZtdStream( dataCompressed );
207 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
212 const QByteArray dataUncompressed = decompressZtdStream( data );
213 return decompressBinary_( dataUncompressed, attributes, requestedAttributes, scale, offset, filterExpression, filterRect );
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.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
void setYMinimum(double y)
Set the minimum y value.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
void setXMinimum(double x)
Set the minimum x value.
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
void setYMaximum(double y)
Set the maximum y value.
void setXMaximum(double x)
Set the maximum x value.
bool isEmpty() const
Returns true if the rectangle has no area.
Class for storage of 3D vectors similar to QVector3D, with the difference that it uses double precisi...
double y() const
Returns Y coordinate.
double x() const
Returns X coordinate.