#include "gtest/gtest.h"
TEST(Interpolants, SheppardInterpolant1D) {
int N = 4;
int num_closest = 2;
Range<Vec1d> pos(N);
Range<double> values(N);
for (int i = 0; i < N; i++) {
pos[i] = i;
values[i] = i;
}
SheppardInterpolant<Vec1d, double> interpolant(pos, values);
point.setConstant(1.5);
double value = interpolant(point, num_closest);
EXPECT_NEAR(1.5, value, 1e-15);
}
TEST(Interpolants, SheppardInterpolant2D) {
int N = 4;
Range<Vec2d> pos(N);
Range<double> values(N);
for (int i = 0; i < N; i++) {
values[i] = i;
}
SheppardInterpolant<Vec2d, double> interpolant(pos, values);
int N_points = 30;
auto x = Eigen::ArrayXf::LinSpaced(N_points, 0, 1);
auto y = x;
for (int i = 1; i < N_points - 1; i++) {
for (int j = 1; j < N_points - 1; j++) {
auto point =
Vec2d{x(i), y(j)};
double value = interpolant(point, N);
Range<double> w(N);
double w_sum = 0;
for (int k = 0; k < N; k++) {
w[k] = 1 / (point - pos[k]).squaredNorm();
w_sum += w[k];
}
double expected_value = 0;
for (int k = 0; k < N; k++) {
expected_value += w[k] * values[k];
}
expected_value /= w_sum;
EXPECT_NEAR(expected_value, value, 1e-15);
}
}
for (int i = 0; i < N; i++) {
double value = interpolant(pos[i], N);
EXPECT_NEAR(values[i], value, 1e-15);
}
}
TEST(Interpolants, SheppardInterpolant3D) {
int N = 3;
Range<Vec3d> pos(N);
Range<double> values(N);
for (int i = 0; i < N; i++) {
values[i] = i;
}
SheppardInterpolant<Vec3d, double> interpolant(pos, values);
double value = interpolant(point, 3);
EXPECT_NEAR(1, value, 1e-15);
point = 0.2 * (pos[1] + pos[2]);
value = interpolant(point, 2);
EXPECT_NEAR(1.5, value, 1e-15);
}
TEST(Interpolants, SheppardInterpolantPower) {
int N = 2;
int num_closest = 2;
Range<Vec1d> pos(N);
Range<double> values(N);
for (int i = 0; i < N; i++) {
pos[i] = i;
values[i] = i + 2;
}
SheppardInterpolant<Vec1d, double> interpolant(pos, values);
for (int power = 1; power < 10; power++) {
double value = interpolant(point, num_closest, power);
Range<double> w(N);
double w_sum = 0;
for (int k = 0; k < N; k++) {
w[k] = 1.0 / std::pow((point - pos[k]).norm(), power);
w_sum += w[k];
}
double expected_value = 0;
for (int k = 0; k < N; k++) {
expected_value += w[k] * values[k];
}
expected_value /= w_sum;
EXPECT_NEAR(expected_value, value, 1e-15);
}
}
TEST(Interpolants, SheppardInterpolantSingleNeighbor) {
int N = 2;
int num_closest = 1;
Range<Vec1d> pos(N);
Range<double> values(N);
for (int i = 0; i < N; i++) {
pos[i] = 5 * i;
values[i] = i + 2;
}
SheppardInterpolant<Vec1d, double> interpolant(pos, values);
double value = interpolant(point, num_closest);
EXPECT_NEAR(values[0], value, 1e-15);
point.setConstant(2.6);
value = interpolant(point, num_closest);
EXPECT_NEAR(values[1], value, 1e-15);
}
TEST(Interpolants, SheppardInterpolantRegularization) {
int N = 2;
int num_closest = 2;
Range<Vec1d> pos(N);
Range<double> values(N);
for (int i = 0; i < N; i++) {
pos[i] = i;
values[i] = i + 2;
}
SheppardInterpolant<Vec1d, double> interpolant(pos, values);
for (double reg = 0.0; reg < 20.0; reg += 3.0) {
double value = interpolant(point, num_closest, 2, reg);
Range<double> w(N);
double w_sum = 0;
for (int k = 0; k < N; k++) {
w[k] = 1.0 / ((point - pos[k]).squaredNorm() + reg);
w_sum += w[k];
}
double expected_value = 0;
for (int k = 0; k < N; k++) {
expected_value += w[k] * values[k];
}
expected_value /= w_sum;
EXPECT_NEAR(expected_value, value, 1e-15);
}
}
TEST(Interpolants, SheppardInterpolantConfusionDistance) {
int N = 2;
int num_closest = 2;
Range<Vec1d> pos(N);
Range<double> values(N);
for (int i = 0; i < N; i++) {
pos[i] = i;
values[i] = i + 2;
}
SheppardInterpolant<Vec1d, double> interpolant(pos, values);
for (double conf_dist = 0.1; conf_dist > 1e-14; conf_dist /= 10) {
double value = interpolant(point, num_closest, 2, 0, conf_dist);
EXPECT_NEAR(values[0], value, 1e-15);
}
}
}