Back

Interpolation Functions

Overview

The interpolation module provides several methods for spatial interpolation of scalar and vector fields from scattered data points to target locations. Methods include Inverse Distance Weighting (IDW), Radial Basis Functions (RBF), Nearest Neighbor, Natural Neighbor (Sibson), and a general-purpose field interpolation function.

Inverse Distance Weighting (IDW)

IDW Interpolation

// Interpolate values from source points to target points using IDW
template <typename T, size_t DIM>
Serie<T> idw(
    const Serie<Vector<DIM>> &points,      // Source point positions
    const Serie<T>           &values,      // Values at source points
    const Serie<Vector<DIM>> &targets,     // Target point positions
    double power     = 2.0,                // Distance weighting power
    double smoothing = 1e-10               // Smoothing parameter
);
IDW Example

// Known data points with temperature values
df::Serie<Vector<2>> stations{
    {0.0, 0.0}, {10.0, 0.0}, {5.0, 8.0}
};
df::Serie<double> temperatures{20.0, 25.0, 22.0};

// Points where we want to estimate temperature
df::Serie<Vector<2>> grid_points{
    {3.0, 3.0}, {7.0, 3.0}, {5.0, 5.0}
};

// Interpolate using IDW with power=2
auto estimated = df::geo::idw<double, 2>(
    stations, temperatures, grid_points, 2.0
);

// Also works with vector-valued data
df::Serie<Vector<3>> displacements{
    {0.1, 0.0, 0.0}, {0.0, 0.2, 0.0}, {0.05, 0.05, 0.1}
};
auto interp_disp = df::geo::idw<Vector<3>, 2>(
    stations, displacements, grid_points
);

Radial Basis Functions (RBF)

RBF Interpolation

// Available RBF kernels
enum class RBFKernel {
    Gaussian,             // exp(-r^2 / epsilon^2)
    Multiquadric,         // sqrt(1 + (r/epsilon)^2)
    InverseMultiquadric,  // 1 / sqrt(1 + (r/epsilon)^2)
    ThinPlate,            // r^2 * log(r)
    Linear                // r
};

// 2D RBF interpolation
Serie<double> rbf_2d(
    const Serie<Vector<2>> &points,
    const Serie<double>     &values,
    const Serie<Vector<2>> &targets,
    RBFKernel kernel = RBFKernel::ThinPlate,
    double epsilon   = 1.0
);

// 3D RBF interpolation
Serie<double> rbf_3d(
    const Serie<Vector<3>> &points,
    const Serie<double>     &values,
    const Serie<Vector<3>> &targets,
    RBFKernel kernel = RBFKernel::ThinPlate,
    double epsilon   = 1.0
);
RBF Example

df::Serie<Vector<2>> pts{{0,0}, {1,0}, {0,1}, {1,1}};
df::Serie<double> vals{1.0, 2.0, 3.0, 4.0};

df::Serie<Vector<2>> targets{{0.5, 0.5}, {0.25, 0.75}};

// Thin-plate spline interpolation
auto result_tp = df::geo::rbf_2d(pts, vals, targets,
    df::geo::RBFKernel::ThinPlate);

// Gaussian kernel with custom epsilon
auto result_g = df::geo::rbf_2d(pts, vals, targets,
    df::geo::RBFKernel::Gaussian, 0.5);

Nearest Neighbor

Nearest Neighbor Interpolation

// 2D nearest neighbor interpolation
template <typename T>
Serie<T> nearest_2d(
    const Serie<Vector<2>> &points,
    const Serie<T>          &values,
    const Serie<Vector<2>> &targets
);

// 3D nearest neighbor interpolation
template <typename T>
Serie<T> nearest_3d(
    const Serie<Vector<3>> &points,
    const Serie<T>          &values,
    const Serie<Vector<3>> &targets
);
Nearest Neighbor Example

df::Serie<Vector<3>> pts{{0,0,0}, {10,0,0}, {0,10,0}};
df::Serie<double> vals{1.0, 2.0, 3.0};

df::Serie<Vector<3>> targets{{1,1,0}, {9,1,0}};

auto result = df::geo::nearest_3d(pts, vals, targets);
// result = {1.0, 2.0}  (value of nearest source point)

Natural Neighbor (Sibson)

Natural Neighbor Interpolation

// 2D Natural Neighbor interpolation using Sibson's method
// NOTE: Requires CGAL library
Serie<double> natural_neighbor_2d(
    const Serie<Vector<2>> &points,
    const Serie<double>     &values,
    const Serie<Vector<2>> &targets
);

Natural Neighbor interpolation uses the concept of Voronoi diagrams and Delaunay triangulations to compute smooth, C1-continuous interpolants. It produces very natural-looking results for scattered data and respects the convex hull of the input points. Requires the CGAL library to be linked.

Natural Neighbor Example

df::Serie<Vector<2>> pts{{0,0}, {1,0}, {0,1}, {1,1}, {0.5, 0.5}};
df::Serie<double> vals{0.0, 1.0, 1.0, 2.0, 1.5};

df::Serie<Vector<2>> targets{{0.25, 0.25}, {0.75, 0.75}};

auto result = df::geo::natural_neighbor_2d(pts, vals, targets);
// Smooth C1 interpolation based on Voronoi cell overlap

Field Interpolation

General Field Interpolation

// Interpolation parameters
struct InterpolationParams {
    size_t num_neighbors = 8;      // Number of neighbors to use
    double power         = 2.0;    // IDW power parameter
    double smoothing     = 1e-10;  // Smoothing factor
    std::string method   = "idw";  // "idw", "rbf", "nearest"
    double radius        = 0.0;    // Search radius (0 = unlimited)
    size_t iterations    = 1;      // Number of smoothing iterations
};

// Interpolate a field from source to target positions
template <typename T, size_t DIM>
Serie<T> interpolate_field(
    const Serie<Vector<DIM>> &source_positions,
    const Serie<T>           &source_values,
    const Serie<Vector<DIM>> &target_positions,
    const InterpolationParams &params = {}
);
Field Interpolation Example

// Interpolate a displacement field from a coarse mesh to a fine mesh
df::Serie<Vector<3>> coarse_pts = /* coarse mesh vertices */;
df::Serie<Vector<3>> fine_pts   = /* fine mesh vertices */;
df::Serie<Vector<3>> coarse_disp = /* displacement at coarse nodes */;

df::InterpolationParams params;
params.method        = "idw";
params.num_neighbors = 12;
params.power         = 2.0;

auto fine_disp = df::geo::interpolate_field<Vector<3>, 3>(
    coarse_pts, coarse_disp, fine_pts, params
);