QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgspointcloudstatistics.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspointcloudstatistics.h
3  --------------------
4  begin : May 2022
5  copyright : (C) 2022 by Belgacem Nedjima
6  email : belgacem dot nedjima 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 
19 
20 #include <limits>
21 #include <QJsonObject>
22 #include <QJsonDocument>
23 
24 #include "qgspointcloudattribute.h"
25 #include "qgsmessagelog.h"
26 
27 // QgsPointCloudAttributeStatistics
28 
30 {
31  minimum = std::min( minimum, stats.minimum );
32  maximum = std::max( maximum, stats.maximum );
33 
34  double newMean = ( mean * count + stats.mean * stats.count ) / ( count + stats.count );
35  double delta1 = newMean - mean;
36  double variance1 = stDev * stDev + delta1 * delta1 - 2 * count * delta1 * mean;
37  double delta2 = newMean - stats.mean;
38  double variance2 = stats.stDev * stats.stDev + delta2 * delta2 - 2 * stats.count * delta2 * stats.mean;
39  stDev = ( variance1 * count + variance2 * stats.count ) / ( count + stats.count );
40  stDev = std::sqrt( stDev );
41 
42  mean = newMean;
43  count += stats.count;
44 
45  for ( int key : stats.classCount.keys() )
46  {
47  int c = classCount.value( key, 0 );
48  c += stats.classCount[ key ];
49  classCount[ key ] = c;
50  }
51 }
52 
53 // QgsPointCloudStatistics
54 
56 {
57 
58 }
59 
60 QgsPointCloudStatistics::QgsPointCloudStatistics( int sampledPointsCount, const QMap<QString, QgsPointCloudAttributeStatistics> &stats )
61  : mSampledPointsCount( sampledPointsCount ), mStatisticsMap( stats )
62 {
63 
64 }
65 
67 {
68  mStatisticsMap.clear();
69 }
70 
71 void QgsPointCloudStatistics::clear( const QVector<QgsPointCloudAttribute> &attributes )
72 {
73  for ( QgsPointCloudAttribute attribute : attributes )
74  {
75  mStatisticsMap.remove( attribute.name() );
76  }
77 }
78 
80 {
82  defaultVal.minimum = std::numeric_limits<double>::max();
83  defaultVal.maximum = std::numeric_limits<double>::lowest();
84  defaultVal.count = 0;
85  return mStatisticsMap.value( attribute, defaultVal );
86 }
87 
88 QList<int> QgsPointCloudStatistics::classesOf( const QString &attribute ) const
89 {
90  if ( !mStatisticsMap.contains( attribute ) )
91  return QList<int>();
92  QgsPointCloudAttributeStatistics s = mStatisticsMap[ attribute ];
93  return s.classCount.keys();
94 }
95 
96 QMap<int, int> QgsPointCloudStatistics::availableClasses( const QString &attribute ) const
97 {
98  if ( !mStatisticsMap.contains( attribute ) )
99  return QMap<int, int>();
100  return mStatisticsMap[ attribute ].classCount;
101 }
102 
103 double QgsPointCloudStatistics::minimum( const QString &attribute ) const
104 {
105  if ( !mStatisticsMap.contains( attribute ) )
106  return std::numeric_limits<double>::quiet_NaN();
107  return mStatisticsMap[ attribute ].minimum;
108 }
109 
110 double QgsPointCloudStatistics::maximum( const QString &attribute ) const
111 {
112  if ( !mStatisticsMap.contains( attribute ) )
113  return std::numeric_limits<double>::quiet_NaN();
114  return mStatisticsMap[ attribute ].maximum;
115 }
116 
117 double QgsPointCloudStatistics::mean( const QString &attribute ) const
118 {
119  if ( !mStatisticsMap.contains( attribute ) )
120  return std::numeric_limits<double>::quiet_NaN();
121  return mStatisticsMap[ attribute ].mean;
122 }
123 
124 double QgsPointCloudStatistics::stDev( const QString &attribute ) const
125 {
126  if ( !mStatisticsMap.contains( attribute ) )
127  return std::numeric_limits<double>::quiet_NaN();
128  return mStatisticsMap[ attribute ].stDev;
129 }
130 
131 
133 {
134  for ( const QString &attribute : stats.mStatisticsMap.keys() )
135  {
136  QgsPointCloudAttributeStatistics s = stats.mStatisticsMap[ attribute ];
137  if ( mStatisticsMap.contains( attribute ) )
138  {
139  s.cumulateStatistics( mStatisticsMap[ attribute ] );
140  }
141  mStatisticsMap[ attribute ] = s;
142  }
143  mSampledPointsCount += stats.mSampledPointsCount;
144 }
145 
147 {
148  QJsonObject obj;
149  obj.insert( QStringLiteral( "sampled-points" ), QJsonValue::fromVariant( sampledPointsCount() ) );
150  QJsonObject stats;
151  for ( const QString &attr : mStatisticsMap.keys() )
152  {
153  QgsPointCloudAttributeStatistics stat = mStatisticsMap.value( attr );
154  stats.insert( attr, attributeStatisticsToJson( stat ) );
155  }
156  obj.insert( QStringLiteral( "stats" ), stats );
157 
158  QJsonDocument statsDoc( obj );
159  return statsDoc.toJson( QJsonDocument::Compact );
160 }
161 
163 {
164  QJsonParseError error;
165  QJsonDocument document = QJsonDocument::fromJson( statsByteArray, &error );
166  if ( error.error != QJsonParseError::NoError )
167  {
168  QgsMessageLog::logMessage( QObject::tr( "Failed to load statistics JSON from COPC file, reason: %1" ).arg( error.errorString() ) );
169  return QgsPointCloudStatistics();
170  }
171 
172  QJsonObject statsJson = document.object();
173 
175  stats.mSampledPointsCount = statsJson.value( QStringLiteral( "sampled-points" ) ).toInt();
176  if ( statsJson.contains( QStringLiteral( "stats" ) ) )
177  {
178  QJsonObject statsObj = statsJson.value( QStringLiteral( "stats" ) ).toObject();
179  for ( const QString &attr : statsObj.keys() )
180  {
181  QJsonObject obj = statsObj.value( attr ).toObject();
182  QgsPointCloudAttributeStatistics attrStats = fromAttributeStatisticsJson( obj );
183  attrStats.count = stats.mSampledPointsCount;
184  stats.mStatisticsMap.insert( attr, attrStats );
185  }
186  }
187  return stats;
188 }
189 
190 QJsonObject QgsPointCloudStatistics::attributeStatisticsToJson( const QgsPointCloudAttributeStatistics &stats )
191 {
192  QJsonObject obj;
193  obj.insert( QStringLiteral( "minimum" ), stats.minimum );
194  obj.insert( QStringLiteral( "maximum" ), stats.maximum );
195  obj.insert( QStringLiteral( "mean" ), stats.mean );
196  if ( !std::isnan( stats.stDev ) )
197  {
198  obj.insert( QStringLiteral( "standard-deviation" ), stats.stDev );
199  }
200  QJsonObject classCount;
201  for ( const int &c : stats.classCount.keys() )
202  {
203  classCount.insert( QString::number( c ), stats.classCount[c] );
204  }
205  obj.insert( QStringLiteral( "class-count" ), classCount );
206  return obj;
207 }
208 
209 QgsPointCloudAttributeStatistics QgsPointCloudStatistics::fromAttributeStatisticsJson( QJsonObject &statsJson )
210 {
212  QVariantMap m = statsJson.toVariantMap();
213  statsObj.minimum = m.value( QStringLiteral( "minimum" ), std::numeric_limits<double>::max() ).toDouble();
214  statsObj.maximum = m.value( QStringLiteral( "maximum" ), std::numeric_limits<double>::lowest() ).toDouble();
215  statsObj.mean = m.value( QStringLiteral( "mean" ), 0 ).toDouble();
216  statsObj.stDev = m.value( QStringLiteral( "standard-deviation" ), std::numeric_limits<double>::quiet_NaN() ).toDouble();
217  QJsonObject classCountJson = statsJson.value( QStringLiteral( "class-count" ) ).toObject();
218  for ( const QString &key : classCountJson.keys() )
219  {
220  statsObj.classCount.insert( key.toInt(), classCountJson.value( key ).toInt() );
221  }
222  return statsObj;
223 }
QgsPointCloudStatistics::stDev
double stDev(const QString &attribute) const
Returns the standard deviation value for the attribute attribute If no matching statistic is availabl...
Definition: qgspointcloudstatistics.cpp:124
QgsPointCloudAttributeStatistics::classCount
QMap< int, int > classCount
Definition: qgspointcloudstatistics.h:47
QgsPointCloudStatistics::combineWith
void combineWith(const QgsPointCloudStatistics &stats)
Merges the current statistics with the statistics from stats.
Definition: qgspointcloudstatistics.cpp:132
QgsPointCloudStatistics::clear
void clear()
Clears the statistics of all attributes.
Definition: qgspointcloudstatistics.cpp:66
QgsPointCloudAttributeStatistics::minimum
double minimum
Definition: qgspointcloudstatistics.h:41
qgspointcloudattribute.h
QgsPointCloudStatistics
Class used to store statistics of a point cloud dataset.
Definition: qgspointcloudstatistics.h:61
QgsPointCloudStatistics::maximum
double maximum(const QString &attribute) const
Returns the maximum value for the attribute attribute If no matching statistic is available then NaN ...
Definition: qgspointcloudstatistics.cpp:110
QgsPointCloudStatistics::sampledPointsCount
int sampledPointsCount() const
Returns the number of points used to calculate the statistics.
Definition: qgspointcloudstatistics.h:73
qgspointcloudstatistics.h
QgsPointCloudStatistics::fromStatisticsJson
static QgsPointCloudStatistics fromStatisticsJson(QByteArray stats)
Creates a statistics object from the JSON object stats.
Definition: qgspointcloudstatistics.cpp:162
QgsPointCloudStatistics::classesOf
QList< int > classesOf(const QString &attribute) const
Returns a list of existing classes which are present for the specified attribute.
Definition: qgspointcloudstatistics.cpp:88
QgsPointCloudAttributeStatistics
Class used to store statistics of one attribute of a point cloud dataset.
Definition: qgspointcloudstatistics.h:39
QgsPointCloudStatistics::mean
double mean(const QString &attribute) const
Returns the mean value for the attribute attribute If no matching statistic is available then NaN wil...
Definition: qgspointcloudstatistics.cpp:117
QgsPointCloudStatistics::QgsPointCloudStatistics
QgsPointCloudStatistics()
Constructor.
Definition: qgspointcloudstatistics.cpp:55
QgsPointCloudAttributeStatistics::count
int count
Definition: qgspointcloudstatistics.h:45
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsPointCloudStatistics::toStatisticsJson
QByteArray toStatisticsJson() const
Converts the current statistics object into JSON object.
Definition: qgspointcloudstatistics.cpp:146
QgsPointCloudAttribute
Attribute for point cloud data pair of name and size in bytes.
Definition: qgspointcloudattribute.h:40
QgsPointCloudAttributeStatistics::cumulateStatistics
void cumulateStatistics(const QgsPointCloudAttributeStatistics &stats)
Updates the current point cloud statistics to hold the cumulation of the current statistics and stats...
Definition: qgspointcloudstatistics.cpp:29
QgsPointCloudStatistics::minimum
double minimum(const QString &attribute) const
Returns the minimum value for the attribute attribute If no matching statistic is available then NaN ...
Definition: qgspointcloudstatistics.cpp:103
QgsPointCloudStatistics::availableClasses
QMap< int, int > availableClasses(const QString &attribute) const
Returns a map containing the count of each class of the attribute attribute If no matching statistic ...
Definition: qgspointcloudstatistics.cpp:96
c
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
Definition: porting_processing.dox:1
QgsPointCloudAttributeStatistics::maximum
double maximum
Definition: qgspointcloudstatistics.h:42
QgsPointCloudAttributeStatistics::stDev
double stDev
Definition: qgspointcloudstatistics.h:44
QgsPointCloudStatistics::statisticsOf
QgsPointCloudAttributeStatistics statisticsOf(const QString &attribute) const
Returns the calculated statistics of attribute attribute.
Definition: qgspointcloudstatistics.cpp:79
QgsPointCloudAttributeStatistics::mean
double mean
Definition: qgspointcloudstatistics.h:43
qgsmessagelog.h