67 std::unique_ptr<QgsPointCloudBlock> block =
nullptr;
70 block = mIndex.nodeData( nodeId, mRequest );
75 if ( request ==
nullptr )
77 QgsDebugError( u
"Unable to calculate statistics for node %1: Got nullptr async request"_s.arg( nodeId.
toString() ) );
84 if ( !mFeedback->isCanceled() )
101 const QVector<QgsPointCloudAttribute> attributes = attributesCollection.
attributes();
102 const char *ptr = block->data();
103 int count = block->pointCount();
106 QMap<QString, QgsPointCloudAttributeStatistics> statsMap;
110 summary.
minimum = std::numeric_limits<double>::max();
111 summary.
maximum = std::numeric_limits<double>::lowest();
114 summary.
stDev = std::numeric_limits<double>::quiet_NaN();
116 statsMap[ attribute.name() ] = std::move( summary );
119 QVector<int> attributeOffsetVector;
120 QSet<int> classifiableAttributesOffsetSet;
123 int attributeOffset = 0;
124 attributesCollection.
find( attribute.name(), attributeOffset );
125 attributeOffsetVector.push_back( attributeOffset );
126 if ( attribute.name() ==
"ScannerChannel"_L1 ||
127 attribute.name() ==
"ReturnNumber"_L1 ||
128 attribute.name() ==
"NumberOfReturns"_L1 ||
129 attribute.name() ==
"ScanDirectionFlag"_L1 ||
130 attribute.name() ==
"Classification"_L1 ||
131 attribute.name() ==
"EdgeOfFlightLine"_L1 ||
132 attribute.name() ==
"PointSourceId"_L1 ||
133 attribute.name() ==
"Synthetic"_L1 ||
134 attribute.name() ==
"KeyPoint"_L1 ||
135 attribute.name() ==
"Withheld"_L1 ||
136 attribute.name() ==
"Overlap"_L1 )
138 classifiableAttributesOffsetSet.insert( attributeOffset );
142 QVector<double> sumOfSquares( attributes.size(), 0 );
143 QVector<double> partialMean( attributes.size(), 0 );
144 for (
int i = 0; i < count; ++i )
146 for (
int j = 0; j < attributes.size(); ++j )
148 if ( mFeedback->isCanceled() )
152 QString attributeName = attributes.at( j ).name();
155 double attributeValue = 0;
156 int attributeOffset = attributeOffsetVector[ j ];
162 stats.
mean += attributeValue / count;
166 const double delta = attributeValue - partialMean[j];
167 partialMean[j] += delta / stats.
count;
168 sumOfSquares[j] += delta * ( attributeValue - partialMean[j] );
170 if ( classifiableAttributesOffsetSet.contains( attributeOffset ) )
177 for (
int j = 0; j < attributes.size(); ++j )
179 const QString attributeName = attributes.at( j ).name();
181 stats.
stDev = std::sqrt( sumOfSquares[j] / ( stats.
count - 1.0 ) );