64 std::unique_ptr<QgsPointCloudBlock> block =
nullptr;
67 block = mIndex.nodeData( nodeId, mRequest );
72 if ( request ==
nullptr )
74 QgsDebugError( QStringLiteral(
"Unable to calculate statistics for node %1: Got nullptr async request" ).arg( nodeId.
toString() ) );
81 if ( !mFeedback->isCanceled() )
98 const QVector<QgsPointCloudAttribute> attributes = attributesCollection.
attributes();
99 const char *ptr = block->data();
100 int count = block->pointCount();
103 QMap<QString, QgsPointCloudAttributeStatistics> statsMap;
107 summary.
minimum = std::numeric_limits<double>::max();
108 summary.
maximum = std::numeric_limits<double>::lowest();
111 summary.
stDev = std::numeric_limits<double>::quiet_NaN();
113 statsMap[ attribute.name() ] = std::move( summary );
116 QVector<int> attributeOffsetVector;
117 QSet<int> classifiableAttributesOffsetSet;
120 int attributeOffset = 0;
121 attributesCollection.
find( attribute.name(), attributeOffset );
122 attributeOffsetVector.push_back( attributeOffset );
123 if ( attribute.name() == QLatin1String(
"ScannerChannel" ) ||
124 attribute.name() == QLatin1String(
"ReturnNumber" ) ||
125 attribute.name() == QLatin1String(
"NumberOfReturns" ) ||
126 attribute.name() == QLatin1String(
"ScanDirectionFlag" ) ||
127 attribute.name() == QLatin1String(
"Classification" ) ||
128 attribute.name() == QLatin1String(
"EdgeOfFlightLine" ) ||
129 attribute.name() == QLatin1String(
"PointSourceId" ) ||
130 attribute.name() == QLatin1String(
"Synthetic" ) ||
131 attribute.name() == QLatin1String(
"KeyPoint" ) ||
132 attribute.name() == QLatin1String(
"Withheld" ) ||
133 attribute.name() == QLatin1String(
"Overlap" ) )
135 classifiableAttributesOffsetSet.insert( attributeOffset );
139 QVector<double> sumOfSquares( attributes.size(), 0 );
140 QVector<double> partialMean( attributes.size(), 0 );
141 for (
int i = 0; i < count; ++i )
143 for (
int j = 0; j < attributes.size(); ++j )
145 if ( mFeedback->isCanceled() )
149 QString attributeName = attributes.at( j ).name();
152 double attributeValue = 0;
153 int attributeOffset = attributeOffsetVector[ j ];
159 stats.
mean += attributeValue / count;
163 const double delta = attributeValue - partialMean[j];
164 partialMean[j] += delta / stats.
count;
165 sumOfSquares[j] += delta * ( attributeValue - partialMean[j] );
167 if ( classifiableAttributesOffsetSet.contains( attributeOffset ) )
174 for (
int j = 0; j < attributes.size(); ++j )
176 const QString attributeName = attributes.at( j ).name();
178 stats.
stDev = std::sqrt( sumOfSquares[j] / ( stats.
count - 1.0 ) );