| 294 | } |
| 295 | |
| 296 | void SMRFilter::classifyGround(PointViewPtr view, std::vector<double>& ZIpro) |
| 297 | { |
| 298 | // "While many authors use a single value for the elevation threshold, we |
| 299 | // suggest that a second parameter be used to increase the threshold on |
| 300 | // steep slopes, transforming the threshold to a slope-dependent value. The |
| 301 | // total permissible distance is then equal to a fixed elevation threshold |
| 302 | // plus the scaling value multiplied by the slope of the DEM at each LIDAR |
| 303 | // point. The rationale behind this approach is that small horizontal and |
| 304 | // vertical displacements yield larger errors on steep slopes, and as a |
| 305 | // result the BE/OBJ threshold distance should be more permissive at these |
| 306 | // points." |
| 307 | MatrixXd gsurfs(m_rows, m_cols); |
| 308 | MatrixXd thresh(m_rows, m_cols); |
| 309 | { |
| 310 | MatrixXd ZIproM = Map<MatrixXd>(ZIpro.data(), m_rows, m_cols); |
| 311 | MatrixXd scaled = ZIproM / m_args->m_cell; |
| 312 | |
| 313 | MatrixXd gx = math::gradX(scaled); |
| 314 | MatrixXd gy = math::gradY(scaled); |
| 315 | gsurfs = (gx.cwiseProduct(gx) + gy.cwiseProduct(gy)).cwiseSqrt(); |
| 316 | std::vector<double> gsurfsV(gsurfs.data(), |
| 317 | gsurfs.data() + gsurfs.size()); |
| 318 | |
| 319 | //ABELL - We can eliminate this copy if we're OK with not writing |
| 320 | // both the filled and non-filled array to output. |
| 321 | std::vector<double> gsurfs_fillV = gsurfsV; |
| 322 | knnfill(view, gsurfs_fillV); |
| 323 | gsurfs = Map<MatrixXd>(gsurfs_fillV.data(), m_rows, m_cols); |
| 324 | thresh = |
| 325 | (m_args->m_threshold + m_args->m_scalar * gsurfs.array()).matrix(); |
| 326 | |
| 327 | if (!m_args->m_dir.empty()) |
| 328 | { |
| 329 | std::string fname = |
| 330 | FileUtils::toAbsolutePath("gx.tif", m_args->m_dir); |
| 331 | math::writeMatrix(gx, fname, "GTiff", m_args->m_cell, m_bounds, m_srs); |
| 332 | |
| 333 | fname = FileUtils::toAbsolutePath("gy.tif", m_args->m_dir); |
| 334 | math::writeMatrix(gy, fname, "GTiff", m_args->m_cell, m_bounds, m_srs); |
| 335 | |
| 336 | fname = FileUtils::toAbsolutePath("gsurfs.tif", m_args->m_dir); |
| 337 | math::writeMatrix(gsurfs, fname, "GTiff", m_args->m_cell, m_bounds, m_srs); |
| 338 | |
| 339 | fname = FileUtils::toAbsolutePath("gsurfs_fill.tif", m_args->m_dir); |
| 340 | MatrixXd gsurfs_fill = |
| 341 | Map<MatrixXd>(gsurfs_fillV.data(), m_rows, m_cols); |
| 342 | math::writeMatrix(gsurfs_fill, fname, "GTiff", m_args->m_cell, m_bounds, m_srs); |
| 343 | |
| 344 | fname = FileUtils::toAbsolutePath("thresh.tif", m_args->m_dir); |
| 345 | math::writeMatrix(thresh, fname, "GTiff", m_args->m_cell, m_bounds, m_srs); |
| 346 | } |
| 347 | } |
| 348 | |
| 349 | point_count_t ng(0); |
| 350 | point_count_t g(0); |
| 351 | for (PointRef p : *view) |
| 352 | { |
| 353 | double x = p.getFieldAs<double>(Id::X); |
nothing calls this directly
no test coverage detected