Skip to content

File test_process.cpp

File List > src > tests > test_process.cpp

Go to the documentation of this file

#include <gtest/gtest.h>

#include <cmath>
#include <limits>
#include <numbers>
#include <vector>

#include "las/las_point.hpp"
#include "lib/grid/grid.hpp"
#include "methods/hill_shade/hill_shade.hpp"
#include "process.hpp"
#include "utilities/progress_tracker.hpp"

// Test num_cells_by_distance function
TEST(Process, NumCellsByDistance) {
  // Test with unit cell size (dx = 1.0)
  EXPECT_EQ(num_cells_by_distance(0.0, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(0.1, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(0.5, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(0.9, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(1.0, 1.0), 2);
  EXPECT_EQ(num_cells_by_distance(1.1, 1.0), 2);
  EXPECT_EQ(num_cells_by_distance(1.5, 1.0), 2);
  EXPECT_EQ(num_cells_by_distance(2.0, 1.0), 3);

  // Test with different cell sizes
  EXPECT_EQ(num_cells_by_distance(10.0, 5.0), 3);
  EXPECT_EQ(num_cells_by_distance(10.1, 5.0), 3);
  EXPECT_EQ(num_cells_by_distance(20.0, 20.0), 2);
  EXPECT_EQ(num_cells_by_distance(20.1, 20.0), 2);

  // Test negative values (should use absolute value)
  EXPECT_EQ(num_cells_by_distance(-0.0, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(-0.1, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(-0.5, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(-1.0, 1.0), 2);
  EXPECT_EQ(num_cells_by_distance(-1.1, 1.0), 2);
  EXPECT_EQ(num_cells_by_distance(-10.0, 5.0), 3);
  EXPECT_EQ(num_cells_by_distance(-10.1, 5.0), 3);

  // Test negative dx values (should use absolute value)
  EXPECT_EQ(num_cells_by_distance(10.0, -5.0), 3);
  EXPECT_EQ(num_cells_by_distance(10.1, -5.0), 3);
  EXPECT_EQ(num_cells_by_distance(20.0, -20.0), 2);
  EXPECT_EQ(num_cells_by_distance(0.0, -1.0), 1);

  // Test error cases
  EXPECT_THROW(num_cells_by_distance(1.0, 0.0), std::invalid_argument);

  // Test edge cases
  EXPECT_EQ(num_cells_by_distance(1e-7, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(1e-6, 1.0), 1);
  EXPECT_EQ(num_cells_by_distance(100.0, 1.0), 101);
  EXPECT_EQ(num_cells_by_distance(100.1, 1.0), 101);
}

// ---- slope() tests -------------------------------------------------------

// A flat surface has zero gradient everywhere, so slope should be 0.
TEST(Slope, FlatSurface) {
  std::vector<std::vector<double>> data = {{10, 10, 10, 10, 10},
                                           {10, 10, 10, 10, 10},
                                           {10, 10, 10, 10, 10},
                                           {10, 10, 10, 10, 10},
                                           {10, 10, 10, 10, 10}};
  GeoGrid<double> flat(data);
  auto result = slope(flat, ProgressTracker());
  for (size_t i = 1; i < 4; i++) {
    for (size_t j = 1; j < 4; j++) {
      double val = result[{j, i}];
      EXPECT_NEAR(val, 0.0, 1e-9) << "at (" << j << "," << i << ")";
    }
  }
}

// A uniform 45-degree slope (rise = run = 1 cell) produces atan(1) = pi/4.
TEST(Slope, FortyFiveDegreeSlope) {
  std::vector<std::vector<double>> data = {
      {0, 0, 0, 0, 0}, {1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}, {3, 3, 3, 3, 3}, {4, 4, 4, 4, 4}};
  GeoGrid<double> sloped(data);
  auto result = slope(sloped, ProgressTracker());
  for (size_t i = 1; i < 4; i++) {
    for (size_t j = 1; j < 4; j++) {
      double val = result[{j, i}];
      EXPECT_NEAR(val, std::numbers::pi / 4, 1e-9) << "at (" << j << "," << i << ")";
    }
  }
}

// Slope values are always non-negative (range [0, pi/2]).
TEST(Slope, AlwaysNonNegative) {
  std::vector<std::vector<double>> data = {
      {5, 3, 7, 1, 9}, {2, 8, 4, 6, 0}, {9, 1, 5, 3, 7}, {4, 6, 2, 8, 4}, {7, 0, 9, 5, 2}};
  GeoGrid<double> mixed(data);
  auto result = slope(mixed, ProgressTracker());
  for (size_t i = 1; i < 4; i++) {
    for (size_t j = 1; j < 4; j++) {
      double val = result[{j, i}];
      EXPECT_GE(val, 0.0) << "at (" << j << "," << i << ")";
    }
  }
}

// Slope values never exceed pi/2 (vertical).
TEST(Slope, NeverExceedsVertical) {
  std::vector<std::vector<double>> data = {{0, 0, 1e6, 0, 0},
                                           {0, 0, 1e6, 0, 0},
                                           {0, 0, 1e6, 0, 0},
                                           {0, 0, 1e6, 0, 0},
                                           {0, 0, 1e6, 0, 0}};
  GeoGrid<double> steep(data);
  auto result = slope(steep, ProgressTracker());
  for (size_t i = 1; i < 4; i++) {
    for (size_t j = 1; j < 4; j++) {
      double val = result[{j, i}];
      EXPECT_LE(val, std::numbers::pi / 2) << "at (" << j << "," << i << ")";
    }
  }
}