25#include <QJsonDocument>
29using namespace Qt::StringLiterals;
39 const double delta1 = newMean -
mean;
41 const double delta2 = newMean - stats.
mean;
42 const double variance2 = stats.
stDev * stats.
stDev * ( stats.
count - 1 ) + stats.
count * delta2 * delta2;
43 const double variance = ( variance1 + variance2 ) / (
count + stats.
count );
44 stDev = std::sqrt( variance );
75 mStatisticsMap.clear();
82 mStatisticsMap.remove( attribute.name() );
89 defaultVal.
minimum = std::numeric_limits<double>::max();
90 defaultVal.
maximum = std::numeric_limits<double>::lowest();
92 return mStatisticsMap.value( attribute, defaultVal );
97 if ( !mStatisticsMap.contains( attribute ) )
105 if ( !mStatisticsMap.contains( attribute ) )
106 return QMap<int, int>();
107 return mStatisticsMap[ attribute ].classCount;
112 if ( !mStatisticsMap.contains( attribute ) )
113 return std::numeric_limits<double>::quiet_NaN();
114 return mStatisticsMap[ attribute ].minimum;
119 if ( !mStatisticsMap.contains( attribute ) )
120 return std::numeric_limits<double>::quiet_NaN();
121 return mStatisticsMap[ attribute ].maximum;
126 if ( !mStatisticsMap.contains( attribute ) )
127 return std::numeric_limits<double>::quiet_NaN();
128 return mStatisticsMap[ attribute ].mean;
133 if ( !mStatisticsMap.contains( attribute ) )
134 return std::numeric_limits<double>::quiet_NaN();
135 return mStatisticsMap[ attribute ].stDev;
141 for (
auto it = stats.mStatisticsMap.constBegin(); it != stats.mStatisticsMap.constEnd(); it++ )
143 const QString attribute = it.key();
145 if ( mStatisticsMap.contains( attribute ) )
149 mStatisticsMap[ attribute ] = s;
151 mSampledPointsCount += stats.mSampledPointsCount;
159 for (
auto it = mStatisticsMap.constBegin(); it != mStatisticsMap.constEnd(); it++ )
162 stats.insert( it.key(), attributeStatisticsToJson( stat ) );
164 obj.insert( u
"stats"_s, stats );
166 QJsonDocument statsDoc( obj );
167 return statsDoc.toJson( QJsonDocument::Compact );
172 QJsonParseError error;
173 QJsonDocument document = QJsonDocument::fromJson( statsByteArray, &error );
174 if ( error.error != QJsonParseError::NoError )
176 QgsMessageLog::logMessage( QObject::tr(
"Failed to load statistics JSON from COPC file, reason: %1" ).arg( error.errorString() ) );
180 QJsonObject statsJson = document.object();
183 stats.mSampledPointsCount = statsJson.value( u
"sampled-points"_s ).toInt();
184 if ( statsJson.contains( u
"stats"_s ) )
186 QJsonObject statsObj = statsJson.value( u
"stats"_s ).toObject();
187 for (
const QString &attr : statsObj.keys() )
189 QJsonObject obj = statsObj.value( attr ).toObject();
191 attrStats.
count = stats.mSampledPointsCount;
192 stats.mStatisticsMap.insert( attr, attrStats );
201 obj.insert( u
"minimum"_s, stats.
minimum );
202 obj.insert( u
"maximum"_s, stats.
maximum );
203 obj.insert( u
"mean"_s, stats.
mean );
204 if ( !std::isnan( stats.
stDev ) )
206 obj.insert( u
"standard-deviation"_s, stats.
stDev );
208 QJsonObject classCount;
211 classCount.insert( QString::number( it.key() ), it.value() );
213 obj.insert( u
"class-count"_s, classCount );
219 QgsPointCloudAttributeStatistics statsObj;
220 QVariantMap m = statsJson.toVariantMap();
221 statsObj.
minimum = m.value( u
"minimum"_s, std::numeric_limits<double>::max() ).toDouble();
222 statsObj.
maximum = m.value( u
"maximum"_s, std::numeric_limits<double>::lowest() ).toDouble();
223 statsObj.
mean = m.value( u
"mean"_s, 0 ).toDouble();
224 statsObj.
stDev = m.value( u
"standard-deviation"_s, std::numeric_limits<double>::quiet_NaN() ).toDouble();
225 QJsonObject classCountJson = statsJson.value( u
"class-count"_s ).toObject();
226 for (
const QString &key : classCountJson.keys() )
228 statsObj.
classCount.insert( key.toInt(), classCountJson.value( key ).toInt() );
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Attribute for point cloud data pair of name and size in bytes.
double maximum(const QString &attribute) const
Returns the maximum value for the attribute attribute If no matching statistic is available then NaN ...
double stDev(const QString &attribute) const
Returns the standard deviation value for the attribute attribute If no matching statistic is availabl...
void clear()
Clears the statistics of all attributes.
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 ...
static QgsPointCloudStatistics fromStatisticsJson(const QByteArray &stats)
Creates a statistics object from the JSON object stats.
QgsPointCloudStatistics()
QList< int > classesOf(const QString &attribute) const
Returns a list of existing classes which are present for the specified attribute.
double mean(const QString &attribute) const
Returns the mean value for the attribute attribute If no matching statistic is available then NaN wil...
void combineWith(const QgsPointCloudStatistics &stats)
Merges the current statistics with the statistics from stats.
double minimum(const QString &attribute) const
Returns the minimum value for the attribute attribute If no matching statistic is available then NaN ...
int sampledPointsCount() const
Returns the number of points used to calculate the statistics.
QByteArray toStatisticsJson() const
Converts the current statistics object into JSON object.
QgsPointCloudAttributeStatistics statisticsOf(const QString &attribute) const
Returns the calculated statistics of attribute attribute.
Stores statistics of one attribute of a point cloud dataset.
void cumulateStatistics(const QgsPointCloudAttributeStatistics &stats)
Updates the current point cloud statistics to hold the cumulation of the current statistics and stats...
int singleClassCount(int cls) const
Returns the count of points in given class or -1 on error.
QMap< int, int > classCount