| 202 | } |
| 203 | |
| 204 | void CovarianceFeaturesFilter::setDimensionality(PointView &view, const PointId &id, const KD3Index &kdi) |
| 205 | { |
| 206 | using namespace Eigen; |
| 207 | |
| 208 | PointRef p = view.point(id); |
| 209 | |
| 210 | // find neighbors, either by radius or k nearest neighbors |
| 211 | PointIdList ids; |
| 212 | if (m_optimal) |
| 213 | { |
| 214 | ids = kdi.neighbors(p, p.getFieldAs<uint64_t>(Id::OptimalKNN), 1); |
| 215 | } |
| 216 | else if (m_radiusArg->set()) |
| 217 | { |
| 218 | ids = kdi.radius(p, m_radius); |
| 219 | if (ids.size() < (size_t)m_minK) { |
| 220 | log()->get(LogLevel::Info) |
| 221 | << "Skipping point " << id << ". Found " << ids.size() |
| 222 | << " neighbors but required " << m_minK << ".\n"; |
| 223 | return; |
| 224 | } |
| 225 | } |
| 226 | else |
| 227 | { |
| 228 | ids = kdi.neighbors(p, m_knn + 1, m_stride); |
| 229 | } |
| 230 | |
| 231 | // compute covariance of the neighborhood |
| 232 | auto B = math::computeCovariance(view, ids); |
| 233 | |
| 234 | // Check if the covariance matrix is all zeros |
| 235 | if (B.isZero()) |
| 236 | { |
| 237 | log()->get(LogLevel::Info) |
| 238 | << "Skipping point " << id |
| 239 | << ". Covariance matrix is all zeros. This suggests a large number " |
| 240 | "of redundant points. Consider using filters.sample with a " |
| 241 | "small radius to remove redundant points.\n"; |
| 242 | return; |
| 243 | } |
| 244 | |
| 245 | // perform the eigen decomposition |
| 246 | SelfAdjointEigenSolver<Matrix3d> solver(B); |
| 247 | if (solver.info() != Success) |
| 248 | throwError("Cannot perform eigen decomposition."); |
| 249 | |
| 250 | // Extract eigenvalues and eigenvectors in decreasing order (largest eigenvalue first) |
| 251 | auto ev = solver.eigenvalues(); |
| 252 | std::vector<double> lambda = {((std::max)(ev[2],0.0)), |
| 253 | ((std::max)(ev[1],0.0)), |
| 254 | ((std::max)(ev[0],0.0))}; |
| 255 | double sum = std::accumulate(lambda.begin(), lambda.end(), 0.0); |
| 256 | |
| 257 | if (lambda[0] == 0) |
| 258 | throwError("Eigenvalues are all 0. Can't compute local features."); |
| 259 | |
| 260 | if (m_mode == Mode::SQRT) |
| 261 | { |
nothing calls this directly
no test coverage detected