QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgspointcloudindex.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgspointcloudindex.cpp
3 --------------------
4 begin : October 2020
5 copyright : (C) 2020 by Peter Petrik
6 email : zilolv at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgspointcloudindex.h"
19#include <QFile>
20#include <QFileInfo>
21#include <QDir>
22#include <QJsonArray>
23#include <QJsonDocument>
24#include <QJsonObject>
25#include <QTime>
26#include <QtDebug>
27
30
32 mD( -1 ),
33 mX( 0 ),
34 mY( 0 ),
35 mZ( 0 )
36{}
37
38IndexedPointCloudNode::IndexedPointCloudNode( int _d, int _x, int _y, int _z ):
39 mD( _d ),
40 mX( _x ),
41 mY( _y ),
42 mZ( _z )
43{}
44
46{
47 return IndexedPointCloudNode( mD - 1, mX / 2, mY / 2, mZ / 2 );
48}
49
51{
52 QStringList lst = str.split( '-' );
53 if ( lst.count() != 4 )
54 return IndexedPointCloudNode();
55 return IndexedPointCloudNode( lst[0].toInt(), lst[1].toInt(), lst[2].toInt(), lst[3].toInt() );
56}
57
59{
60 return QStringLiteral( "%1-%2-%3-%4" ).arg( mD ).arg( mX ).arg( mY ).arg( mZ );
61}
62
64{
65 return mD;
66}
67
69{
70 return mX;
71}
72
74{
75 return mY;
76}
77
79{
80 return mZ;
81}
82
84{
85 return id.d() + id.x() + id.y() + id.z();
86}
87
89
90//
91// QgsPointCloudDataBounds
92//
93
95
96QgsPointCloudDataBounds::QgsPointCloudDataBounds( qint32 xmin, qint32 ymin, qint32 zmin, qint32 xmax, qint32 ymax, qint32 zmax )
97 : mXMin( xmin )
98 , mYMin( ymin )
99 , mZMin( zmin )
100 , mXMax( xmax )
101 , mYMax( ymax )
102 , mZMax( zmax )
103{
104
105}
106
108{
109 return mXMin;
110}
111
113{
114 return mYMin;
115}
116
118{
119 return mXMax;
120}
121
123{
124 return mYMax;
125}
126
128{
129 return mZMin;
130}
131
133{
134 return mZMax;
135}
136
138{
139 return QgsRectangle(
140 mXMin * scale.x() + offset.x(), mYMin * scale.y() + offset.y(),
141 mXMax * scale.x() + offset.x(), mYMax * scale.y() + offset.y()
142 );
143}
144
146{
147 return QgsDoubleRange( mZMin * scale.z() + offset.z(), mZMax * scale.z() + offset.z() );
148}
149
151
152//
153// QgsPointCloudIndex
154//
155
157
159
161{
162 QMutexLocker locker( &mHierarchyMutex );
163 return mHierarchy.contains( n );
164}
165
167{
168 QMutexLocker locker( &mHierarchyMutex );
169 return mHierarchy.value( n, -1 );
170}
171
172QList<IndexedPointCloudNode> QgsPointCloudIndex::nodeChildren( const IndexedPointCloudNode &n ) const
173{
174 QMutexLocker locker( &mHierarchyMutex );
175 Q_ASSERT( mHierarchy.contains( n ) );
176 QList<IndexedPointCloudNode> lst;
177 const int d = n.d() + 1;
178 const int x = n.x() * 2;
179 const int y = n.y() * 2;
180 const int z = n.z() * 2;
181
182 for ( int i = 0; i < 8; ++i )
183 {
184 int dx = i & 1, dy = !!( i & 2 ), dz = !!( i & 4 );
185 const IndexedPointCloudNode n2( d, x + dx, y + dy, z + dz );
186 if ( mHierarchy.contains( n2 ) )
187 lst.append( n2 );
188 }
189 return lst;
190}
191
193{
194 return mAttributes;
195}
196
198{
199 qint32 xMin = -999999999, yMin = -999999999, zMin = -999999999;
200 qint32 xMax = 999999999, yMax = 999999999, zMax = 999999999;
201
202 const int d = mRootBounds.xMax() - mRootBounds.xMin();
203 const double dLevel = ( double )d / pow( 2, n.d() );
204
205 xMin = round( mRootBounds.xMin() + dLevel * n.x() );
206 xMax = round( mRootBounds.xMin() + dLevel * ( n.x() + 1 ) );
207 yMin = round( mRootBounds.yMin() + dLevel * n.y() );
208 yMax = round( mRootBounds.yMin() + dLevel * ( n.y() + 1 ) );
209 zMin = round( mRootBounds.zMin() + dLevel * n.z() );
210 zMax = round( mRootBounds.zMin() + dLevel * ( n.z() + 1 ) );
211
212 QgsPointCloudDataBounds db( xMin, yMin, zMin, xMax, yMax, zMax );
213 return db;
214}
215
217{
218 return nodeBounds( node ).mapExtent( mOffset, mScale );
219}
220
222{
223 return nodeBounds( node ).zRange( mOffset, mScale );
224}
225
227{
228 const double w = nodeMapExtent( n ).width();
229 return w / mSpan;
230}
231
233{
234 return mScale;
235}
236
238{
239 return mOffset;
240}
241
243{
245}
246
248{
249 return mSpan;
250}
251
253{
254 mHierarchyMutex.lock();
255 const int count = mHierarchy.value( n, -1 );
256 mHierarchyMutex.unlock();
257 return count;
258}
259
260bool QgsPointCloudIndex::setSubsetString( const QString &subset )
261{
262 const QString lastExpression = mFilterExpression;
263 mFilterExpression.setExpression( subset );
264 if ( mFilterExpression.hasParserError() && !subset.isEmpty() )
265 {
266 mFilterExpression.setExpression( lastExpression );
267 return false;
268 }
269
270 // fail if expression references unknown attributes
271 int offset;
272 const QSet<QString> attributes = mFilterExpression.referencedAttributes();
273 for ( const QString &attribute : attributes )
274 {
275 if ( !mAttributes.find( attribute, offset ) )
276 {
277 mFilterExpression.setExpression( lastExpression );
278 return false;
279 }
280 }
281 return true;
282}
283
285{
286 return mFilterExpression;
287}
288
289QVariant QgsPointCloudIndex::metadataStatistic( const QString &attribute, QgsStatisticalSummary::Statistic statistic ) const
290{
291 if ( attribute == QLatin1String( "X" ) && statistic == QgsStatisticalSummary::Min )
292 return mExtent.xMinimum();
293 if ( attribute == QLatin1String( "X" ) && statistic == QgsStatisticalSummary::Max )
294 return mExtent.xMaximum();
295
296 if ( attribute == QLatin1String( "Y" ) && statistic == QgsStatisticalSummary::Min )
297 return mExtent.yMinimum();
298 if ( attribute == QLatin1String( "Y" ) && statistic == QgsStatisticalSummary::Max )
299 return mExtent.yMaximum();
300
301 if ( attribute == QLatin1String( "Z" ) && statistic == QgsStatisticalSummary::Min )
302 return mZMin;
303 if ( attribute == QLatin1String( "Z" ) && statistic == QgsStatisticalSummary::Max )
304 return mZMax;
305
306 return QVariant();
307}
308
309QVariantList QgsPointCloudIndex::metadataClasses( const QString &attribute ) const
310{
311 Q_UNUSED( attribute );
312 return QVariantList();
313}
314
315QVariant QgsPointCloudIndex::metadataClassStatistic( const QString &attribute, const QVariant &value, QgsStatisticalSummary::Statistic statistic ) const
316{
317 Q_UNUSED( attribute );
318 Q_UNUSED( value );
319 Q_UNUSED( statistic );
320 return QVariant();
321}
322
324{
325 QMap<QString, QgsPointCloudAttributeStatistics> statsMap;
326 for ( QgsPointCloudAttribute attribute : attributes().attributes() )
327 {
328 QString name = attribute.name();
330 QVariant min = metadataStatistic( name, QgsStatisticalSummary::Min );
331 QVariant max = metadataStatistic( name, QgsStatisticalSummary::Max );
332 QVariant mean = metadataStatistic( name, QgsStatisticalSummary::Mean );
333 QVariant stDev = metadataStatistic( name, QgsStatisticalSummary::StDev );
334 if ( !min.isValid() )
335 continue;
336
337 s.minimum = min.toDouble();
338 s.maximum = max.toDouble();
339 s.mean = mean.toDouble();
340 s.stDev = stDev.toDouble();
342 QVariantList classes = metadataClasses( name );
343 for ( QVariant c : classes )
344 {
345 s.classCount[ c.toInt() ] = metadataClassStatistic( name, c, QgsStatisticalSummary::Count ).toInt();
346 }
347 statsMap[ name ] = s;
348 }
349 return QgsPointCloudStatistics( pointCount(), statsMap );
350}
351
353{
354 // Base QgsPointCloudIndex fields
355 destination->mExtent = mExtent;
356 destination->mZMin = mZMin;
357 destination->mZMax = mZMax;
358 destination->mHierarchy = mHierarchy;
359 destination->mScale = mScale;
360 destination->mOffset = mOffset;
361 destination->mRootBounds = mRootBounds;
362 destination->mAttributes = mAttributes;
363 destination->mSpan = mSpan;
365}
Represents a indexed point cloud node in octree.
int y() const
Returns y.
static IndexedPointCloudNode fromString(const QString &str)
Creates node from string.
int x() const
Returns x.
QString toString() const
Encode node to string.
int d() const
Returns d.
IndexedPointCloudNode parentNode() const
Returns the parent of the node.
int z() const
Returns z.
IndexedPointCloudNode()
Constructs invalid node.
QgsRange which stores a range of double values.
Definition: qgsrange.h:203
Collection of point cloud attributes.
const QgsPointCloudAttribute * find(const QString &attributeName, int &offset) const
Finds the attribute with the name.
Attribute for point cloud data pair of name and size in bytes.
Represents packaged data bounds.
qint32 xMax() const
Returns x max.
qint32 xMin() const
Returns x min.
qint32 yMax() const
Returns y max.
QgsDoubleRange zRange(const QgsVector3D &offset, const QgsVector3D &scale) const
Returns the z range, applying the specified offset and scale.
QgsPointCloudDataBounds()
Constructs invalid bounds.
qint32 zMax() const
Returns z max.
QgsRectangle mapExtent(const QgsVector3D &offset, const QgsVector3D &scale) const
Returns 2D rectangle in map coordinates.
qint32 yMin() const
Returns y min.
qint32 zMin() const
Returns z min.
Represents a indexed point clouds data in octree.
int span() const
Returns the number of points in one direction in a single node.
double zMax() const
Returns z max.
virtual qint64 nodePointCount(const IndexedPointCloudNode &n) const
Returns the number of points of a given node n.
QgsRectangle nodeMapExtent(const IndexedPointCloudNode &node) const
Returns the extent of a node in map coordinates.
virtual QVariant metadataClassStatistic(const QString &attribute, const QVariant &value, QgsStatisticalSummary::Statistic statistic) const
Returns the statistic statistic of the class value of the attribute attribute.
virtual QList< IndexedPointCloudNode > nodeChildren(const IndexedPointCloudNode &n) const
Returns all children of node.
QgsPointCloudIndex()
Constructs index.
QString subsetString() const
Returns the string used to define a subset of the point cloud.
double zMin() const
Returns z min.
QgsVector3D offset() const
Returns offset.
QgsVector3D scale() const
Returns scale.
virtual qint64 pointCount() const =0
Returns the number of points in the point cloud.
virtual QVariantList metadataClasses(const QString &attribute) const
Returns the classes of attribute.
void copyCommonProperties(QgsPointCloudIndex *destination) const
Copies common properties to the destination index.
virtual QVariant metadataStatistic(const QString &attribute, QgsStatisticalSummary::Statistic statistic) const
Returns the statistic statistic of attribute.
bool setSubsetString(const QString &subset)
Sets the string used to define a subset of the point cloud.
QHash< IndexedPointCloudNode, int > mHierarchy
Data hierarchy.
double mZMax
Vertical extent of data.
QgsPointCloudDataBounds mRootBounds
Bounds of the root node's cube (in int32 coordinates)
virtual QgsPointCloudStatistics metadataStatistics() const
Returns the object containings the statistics metadata extracted from the dataset.
QgsRectangle mExtent
2D extent of data
QgsPointCloudAttributeCollection mAttributes
QgsPointCloudDataBounds nodeBounds(const IndexedPointCloudNode &node) const
Returns bounds of particular node.
virtual bool hasNode(const IndexedPointCloudNode &n) const
Returns whether the octree contain given node.
QgsVector3D mOffset
Offset of our int32 coordinates compared to CRS coords.
QgsDoubleRange nodeZRange(const IndexedPointCloudNode &node) const
Returns the z range of a node.
float nodeError(const IndexedPointCloudNode &n) const
Returns node's error in map units (used to determine in whether the node has enough detail for the cu...
int mSpan
All native attributes stored in the file.
QgsVector3D mScale
Scale of our int32 coordinates compared to CRS coords.
QgsPointCloudExpression mFilterExpression
The filter expression to be evaluated when fetching node data.
void setAttributes(const QgsPointCloudAttributeCollection &attributes)
Sets native attributes of the data.
QgsPointCloudAttributeCollection attributes() const
Returns all attributes that are stored in the file.
Class used to store statistics of a point cloud dataset.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Definition: qgsrectangle.h:223
Statistic
Enumeration of flags that specify statistics to be calculated.
@ StDev
Standard deviation of values.
double y() const
Returns Y coordinate.
Definition: qgsvector3d.h:51
double z() const
Returns Z coordinate.
Definition: qgsvector3d.h:53
double x() const
Returns X coordinate.
Definition: qgsvector3d.h:49
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define str(x)
Definition: qgis.cpp:37
uint qHash(IndexedPointCloudNode id)
Hash function for indexed nodes.
Class used to store statistics of one attribute of a point cloud dataset.