71 std::unique_ptr<QgsPointCloudBlock> block =
nullptr;
74 block = mIndex.nodeData( nodeId, mRequest );
79 if ( request ==
nullptr )
81 QgsDebugError( u
"Unable to calculate statistics for node %1: Got nullptr async request"_s.arg( nodeId.
toString() ) );
88 if ( !mFeedback->isCanceled() )
105 const QVector<QgsPointCloudAttribute> attributes = attributesCollection.
attributes();
106 const char *ptr = block->data();
107 int count = block->pointCount();
110 QMap<QString, QgsPointCloudAttributeStatistics> statsMap;
114 summary.
minimum = std::numeric_limits<double>::max();
115 summary.
maximum = std::numeric_limits<double>::lowest();
118 summary.
stDev = std::numeric_limits<double>::quiet_NaN();
120 statsMap[attribute.name()] = std::move( summary );
123 QVector<int> attributeOffsetVector;
124 QSet<int> classifiableAttributesOffsetSet;
127 int attributeOffset = 0;
128 attributesCollection.
find( attribute.name(), attributeOffset );
129 attributeOffsetVector.push_back( attributeOffset );
130 if ( attribute.name() ==
"ScannerChannel"_L1
131 || attribute.name() ==
"ReturnNumber"_L1
132 || attribute.name() ==
"NumberOfReturns"_L1
133 || attribute.name() ==
"ScanDirectionFlag"_L1
134 || attribute.name() ==
"Classification"_L1
135 || attribute.name() ==
"EdgeOfFlightLine"_L1
136 || attribute.name() ==
"PointSourceId"_L1
137 || attribute.name() ==
"Synthetic"_L1
138 || attribute.name() ==
"KeyPoint"_L1
139 || attribute.name() ==
"Withheld"_L1
140 || attribute.name() ==
"Overlap"_L1 )
142 classifiableAttributesOffsetSet.insert( attributeOffset );
146 QVector<double> sumOfSquares( attributes.size(), 0 );
147 QVector<double> partialMean( attributes.size(), 0 );
148 for (
int i = 0; i < count; ++i )
150 for (
int j = 0; j < attributes.size(); ++j )
152 if ( mFeedback->isCanceled() )
156 QString attributeName = attributes.at( j ).name();
159 double attributeValue = 0;
160 int attributeOffset = attributeOffsetVector[j];
166 stats.
mean += attributeValue / count;
170 const double delta = attributeValue - partialMean[j];
171 partialMean[j] += delta / stats.
count;
172 sumOfSquares[j] += delta * ( attributeValue - partialMean[j] );
174 if ( classifiableAttributesOffsetSet.contains( attributeOffset ) )
181 for (
int j = 0; j < attributes.size(); ++j )
183 const QString attributeName = attributes.at( j ).name();
185 stats.
stDev = std::sqrt( sumOfSquares[j] / ( stats.
count - 1.0 ) );