Interpolation on rectilinear grids

Grid-based interpolation on rectilinear grids provides efficient evaluation of functions sampled on structured Cartesian grids in 2D, 3D, and higher dimensions. The GridSurface class and associated factory methods in the Interpolation class enable fast, accurate interpolation from gridded data.

Rectilinear Grids

A rectilinear grid (also called a product grid) is defined by independent coordinate vectors along each dimension. Grid points are located at the Cartesian product of these coordinate vectors. For example, a 2D rectilinear grid with x-coordinates [0, 1, 3] and y-coordinates [0, 2, 4, 5] has 3 × 4 = 12 grid points.

Rectilinear grids are particularly well-suited for data that naturally aligns with coordinate axes but may have non-uniform spacing. Common applications include:

  • Physical simulations on adaptive grids

  • Image or voxel data resampling

  • Lookup tables and tabulated functions

  • Geospatial elevation and gridded sensor data

Regular vs. Rectilinear Grids: A regular grid is a special case of a rectilinear grid where all axes have uniform spacing. Rectilinear grids allow non-uniform spacing along each axis, providing greater flexibility for representing data with varying resolution.

Supported Interpolation Methods

The grid interpolation API supports multiple interpolation methods, each with different trade-offs in smoothness, accuracy, and computational cost:

Grid interpolation method comparison

Method

Continuity

Dimensions

Use Cases

Nearest

Discontinuous (piecewise constant)

Any

Categorical data, extremely fast lookups

Linear

C0 (continuous)

Any

General-purpose, balanced performance and quality

Cubic (specialized)

C2 (smooth)

2D, 3D only

High-quality visualization, natural boundary conditions

Tensor-product splines

C1 (smooth with cubic kernel)

Any

N-D interpolation, custom kernels, flexible boundaries

Nearest-neighbor interpolation returns the value at the closest grid point. It is piecewise constant, creating a blocky appearance but offering the fastest evaluation. Use for categorical data or when minimal computational cost is essential.

Linear (multilinear) interpolation performs bilinear (2D), trilinear (3D), or multilinear (N-D) interpolation within each grid cell. The result is continuous but has discontinuous first derivatives at cell boundaries. This is the most commonly used method, providing a good balance of accuracy and speed.

Cubic spline interpolation comes in two forms:

  • Specialized 2D/3D cubic surfaces (created via GridCubic2DInterpolator(IReadOnlyList<Double>, IReadOnlyList<Double>, IReadOnlyList<Double>, ExtrapolationMode) and GridCubic3DInterpolator) : These precompute partial derivatives using natural cubic splines along each axis, achieving C² continuity (smooth first and second derivatives). Available only for 2D and 3D grids. Ideal for high-quality visualization and when natural boundary conditions (zero second derivative at edges) are appropriate.

  • Tensor-product cubic splines (created via GridCubicTensorSplineInterpolator): These use recursive 1D cubic Hermite interpolation (Catmull-Rom style) along each axis, achieving C¹ continuity. Work for any dimension including 1D, 2D, 3D, and beyond. Support custom boundary conditions (periodic, reflect, clamp, fill). Slightly less smooth than specialized 2D/3D surfaces but more flexible.

Both cubic methods can introduce overshoots and oscillations near sharp features. They are best suited for smooth underlying functions.

Specialized 2D/3D Cubic vs. Tensor-Product Splines

The library provides two families of cubic interpolation for rectilinear grids, each with distinct characteristics:

Comparison: Specialized cubic vs. tensor-product splines

Feature

Specialized 2D/3D Cubic

Tensor-Product Splines

Factory methods

GridCubic2DInterpolator(IReadOnlyList<Double>, IReadOnlyList<Double>, IReadOnlyList<Double>, ExtrapolationMode), GridCubic3DInterpolator

GridCubicTensorSplineInterpolator

Dimensions supported

2D and 3D only

Any (1D, 2D, 3D, 4D, ...)

Smoothness

C² (continuous value, 1st and 2nd derivatives)

C¹ with cubic kernel (continuous value and 1st derivative)

Underlying method

Natural cubic splines (CubicSpline) with global tridiagonal solve

Local cubic Hermite (Catmull-Rom) or custom kernels (ISplineKernel1D)

Boundary conditions

Natural only (zero 2nd derivative at boundaries)

Flexible: clamp, periodic, reflect, fill

Custom kernels

Not supported

Yes, via ISplineKernel1D

Performance

Faster evaluation (O(1) after precomputation)

Good (recursive 1D evaluation, zero allocations)

When to use specialized 2D/3D cubic surfaces:

  • You have 2D or 3D data

  • You need the highest smoothness (C²)

  • Natural boundary conditions are acceptable

  • You prioritize evaluation performance

When to use tensor-product splines:

  • You have N-dimensional data (any dimension)

  • You need custom boundary conditions (periodic, reflect, etc.)

  • You want to use custom spline kernels (linear, cubic, PCHIP, etc.)

  • C¹ continuity is sufficient

Creating Grid-Based Interpolators

The Interpolation class provides factory methods to create grid interpolators for 2D, 3D, and N-dimensional data. The methods follow a consistent naming pattern:

  • GridLinearInterpolator – multilinear interpolation

  • GridNearestInterpolator – nearest-neighbor interpolation

  • GridCubic2DInterpolator(IReadOnlyList<Double>, IReadOnlyList<Double>, IReadOnlyList<Double>, ExtrapolationMode), GridCubic3DInterpolator, GridCubicTensorSplineInterpolator(IReadOnlyList<IReadOnlyList<Double>>, IReadOnlyList<Double>, ExtrapolationMode) – cubic spline interpolation

Array Dimension Order

Important: When passing grid values as 2D or 3D arrays, the dimension order must match the order of the axis arguments.

For a 2D grid created with GridXxxInterpolator(xAxis, yAxis, values):

  • values.GetLength(0) must equal xAxis.Length

  • values.GetLength(1) must equal yAxis.Length

  • values[i, j] corresponds to the function value at f(xAxis[i], yAxis[j])

For a 3D grid, the rule extends analogously:

  • values[i, j, k] = f(xAxis[i], yAxis[j], zAxis[k])

This convention ensures that the first array dimension corresponds to the first axis argument, the second array dimension to the second axis, and so on. When initializing arrays, structure your loops accordingly:

C#
double[] xAxis = { 0.0, 1.0, 2.0 };
double[] yAxis = { 0.0, 1.0 };
double[,] values = new double[xAxis.Length, yAxis.Length];

for (int i = 0; i < xAxis.Length; i++)
{
    for (int j = 0; j < yAxis.Length; j++)
    {
        values[i, j] = MyFunction(xAxis[i], yAxis[j]);
    }
}

2D and 3D Examples

2D Grid Interpolation:

To create a 2D grid interpolator, provide the x-axis, y-axis, and a 2D array or matrix of function values. The values array must have dimensions matching the axis lengths as described in the Array Dimension Order section above.

C#
// Define a 2D rectilinear grid
double[] xAxis = { 0.0, 1.0, 2.0, 3.0 };
double[] yAxis = { 0.0, 1.0, 2.0 };

// Define values on the grid
// Array dimension order: values[i, j] = f(xAxis[i], yAxis[j])
double[,] values = new double[xAxis.Length, yAxis.Length];
for (int i = 0; i < xAxis.Length; i++)
{
    for (int j = 0; j < yAxis.Length; j++)
    {
        values[i, j] = i + j * 4;  // Example function
    }
}

// Create a linear grid interpolator
var surface = Numerics.NET.Interpolation.GridLinearInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Throw);

// Evaluate at a single point
double z1 = surface.Evaluate(1.5, 1.0);
Console.WriteLine($"Linear interpolation at (1.5, 1.0): {z1}");

// Evaluate at multiple points
double z2 = surface.Evaluate(0.5, 0.5);
double z3 = surface.Evaluate(2.5, 1.5);
Console.WriteLine($"Values: ({z2:F2}, {z3:F2})");

For smoother interpolation, use cubic splines:

C#
// Create a cubic spline interpolator for smoother results
var cubicSurface = Numerics.NET.Interpolation.GridCubicInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Throw);

// Evaluate at the same points - cubic will be smoother
double zc1 = cubicSurface.Evaluate(1.5, 1.0);
double zc2 = cubicSurface.Evaluate(0.5, 0.5);
Console.WriteLine($"Cubic interpolation at (1.5, 1.0): {zc1}");
Console.WriteLine($"Cubic interpolation at (0.5, 0.5): {zc2}");

N-Dimensional Grid Interpolation:

For 3D and higher-dimensional grids, pass an array of axis coordinate vectors and a flat array of values. The values must be stored in row-major order, where the last dimension varies fastest. For a 3D grid with axes [z, y, x], the value at grid point (i, j, k) is stored at index i*ny*nx + j*nx + k.

C#
// Create a 3D grid interpolator
Vector<double> xAxis = Vector.Create(0.0, 1.0, 2.0);
Vector<double> yAxis = Vector.Create(0.0, 1.0);
Vector<double> zAxis = Vector.Create(0.0, 1.0, 2.0);

// Axes are ordered as [z, y, x] for row-major storage
Vector<double>[] axes = new Vector<double>[] { zAxis, yAxis, xAxis };

// Flat values array in row-major order (z varies slowest, x varies fastest)
Vector<double> values = Vector.Create(
    // z=0, y=0: x values
    1.0, 2.0, 3.0,
    // z=0, y=1: x values
    4.0, 5.0, 6.0,
    // z=1, y=0: x values
    7.0, 8.0, 9.0,
    // z=1, y=1: x values
    10.0, 11.0, 12.0,
    // z=2, y=0: x values
    13.0, 14.0, 15.0,
    // z=2, y=1: x values
    16.0, 17.0, 18.0
);

// Create the ND linear interpolator
var field = Numerics.NET.Interpolation.GridLinearInterpolator(
    axes, values, ExtrapolationMode.Throw);

// Evaluate at a 3D point
Vector<double> point = Vector.Create(1.0, 0.5, 1.5);
double value = field.Evaluate(point);
Console.WriteLine($"3D interpolation at (1.0, 0.5, 1.5): {value}");

Evaluating Grid Surfaces

Once a GridSurface is created, evaluation is straightforward using the Evaluate(IReadOnlyList<Double>) method.

For 2D surfaces, call surface.Evaluate(x, y). For N-dimensional surfaces, pass a coordinate array or span: surface.Evaluate(new double[] { x, y, z }).

Evaluation is efficient: linear interpolation requires a small number of arithmetic operations per query, while cubic interpolation involves evaluating spline basis functions. Grid-based interpolation scales well to large grids because it uses binary search to locate the relevant cell.

Derivatives and Gradients

Grid surfaces support gradient and (for some methods) Hessian evaluation via the Gradient(ReadOnlySpan<Double>, Span<Double>) and Hessian(ReadOnlySpan<Double>, Span2D<Double>) methods.

Derivative behavior depends on the interpolation method:

  • Nearest-neighbor: Gradient and Hessian are effectively zero (piecewise constant).

  • Linear: Gradient is constant within each cell, discontinuous at boundaries. Hessian is zero within cells.

  • Cubic: Gradient and Hessian are continuous and computed analytically from the spline basis functions.

  • Shape-preserving: Gradient is available; Hessian is not supported for monotone cubic splines.

C#
// Define a 2D grid
double[] xAxis = { 0.0, 1.0, 2.0 };
double[] yAxis = { 0.0, 1.0, 2.0 };

// Array dimension order: values[i, j] = f(xAxis[i], yAxis[j])
double[,] values = new double[xAxis.Length, yAxis.Length];
for (int i = 0; i < xAxis.Length; i++)
{
    for (int j = 0; j < yAxis.Length; j++)
    {
        values[i, j] = i + j;  // Example: f(x,y) = x + y
    }
}

// Create cubic interpolator which supports gradients
var surface = Numerics.NET.Interpolation.GridCubicInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Throw);

// Compute gradient at a point
Vector<double> gradient = Vector.Create(0.0, 0.0);
surface.Gradient(1.0, 1.0, gradient);
Console.WriteLine($"Gradient at (1.0, 1.0): [{gradient[0]:F3}, {gradient[1]:F3}]");

Boundary Conditions vs. Extrapolation Modes

The grid interpolation system distinguishes between two related but distinct concepts: boundary conditions and extrapolation modes. Understanding this distinction is crucial for correct usage of tensor-product splines.

Boundary conditions (represented by GridBoundaryCondition):

  • When: Applied during interpolation stencil assembly (construction/evaluation time)

  • What: Control how to access grid values when the interpolation kernel needs samples at indices outside [0, N-1]. For example, a 4-point cubic kernel near the edge may require i=-1 or i=N.

  • Where: Only used by tensor-product splines (GridSurface.CreateCubicTensorSpline and GridSurface.CreateTensorSpline). Not applicable to specialized 2D/3D cubic surfaces or linear interpolation.

  • Options: Clamp (default), Periodic, Reflect, Fill

Extrapolation modes (represented by ExtrapolationMode):

  • When: Applied during query evaluation

  • What: Control what happens when a query coordinate falls outside the grid domain [x₀, xₙ₋₁]. Should we throw an exception, clamp to boundaries, wrap periodically, etc.?

  • Where: Apply to all grid surface types

  • Options: Throw (default), Clamp, Constant, Periodic, Reflect, Default

Example scenario:

Consider a 1D grid with 10 points and a cubic kernel (width 4). At the left edge (i=0), the cubic stencil needs values at indices {-1, 0, 1, 2}. The boundary condition determines how to map index -1:

  • Clamp: Use value at index 0

  • Periodic: Use value at index 9 (wrap around)

  • Reflect: Use value at index 1 (mirror)

  • Fill: Use a constant (e.g., 0.0)

Now suppose you query the surface at coordinate x = -5 (outside the grid domain). The extrapolation mode determines the response:

  • Throw: Throw ArgumentOutOfRangeException

  • Clamp: Evaluate at x = x₀ (the left boundary)

  • Periodic: Wrap x into the grid domain and evaluate

  • Constant: Return NaN (or user-specified fill value)

Key insight: Boundary conditions affect how the interpolant is constructed and evaluated near edges. Extrapolation modes affect whether and how to evaluate queries outside the domain.

Extrapolation Modes in Detail

The ExtrapolationMode parameter controls how the interpolator handles query points outside the grid domain.

Extrapolation modes

Mode

Behavior

Category

Throw

Throws an ArgumentOutOfRangeException if any coordinate is outside the grid bounds. This is the default.

Global control

Clamp

Clamps each coordinate to the nearest boundary value, effectively extending the grid with constant extrapolation. Creates a plateau effect beyond boundaries.

Global control

Constant

Returns a fill value (typically NaN or a user-specified constant) for out-of-bounds queries without evaluating the interpolant. Useful for masking invalid regions.

Global control

Periodic

Wraps coordinates modulo the grid extent, treating the grid as periodic. Ideal for angular data, periodic signals, or toroidal domains.

Functional extension

Reflect

Reflects coordinates at the grid boundaries, creating a symmetric extension. Useful for symmetric functions or mirror boundary conditions.

Functional extension

Default

Uses the surface's default extrapolation mode, derived from the boundary condition. Periodic boundary → Periodic extrapolation, Reflect boundary → Reflect extrapolation, otherwise Throw.

Defers to surface default

Implementation categories:

  • Global control modes (Throw, Constant, Clamp): Handled by the grid infrastructure before interpolation. The interpolation method never sees out-of-bounds coordinates.

  • Functional extension modes (Periodic, Reflect): Handled by the interpolation strategy. They transform query coordinates and allow the interpolation method to extend the function mathematically beyond the domain.

The following example demonstrates the different extrapolation modes:

C#
double[] xAxis = { 0.0, 1.0, 2.0 };
double[] yAxis = { 0.0, 1.0 };

// Array dimension order: values[i, j] = f(xAxis[i], yAxis[j])
double[,] values = new double[xAxis.Length, yAxis.Length];
for (int i = 0; i < xAxis.Length; i++)
{
    for (int j = 0; j < yAxis.Length; j++)
    {
        values[i, j] = i + j * 3;
    }
}

// ExtrapolationMode.Throw: Out-of-range queries throw an exception
var throwSurface = Numerics.NET.Interpolation.GridLinearInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Throw);

try
{
    double z = throwSurface.Evaluate(3.0, 0.5); // Outside grid
}
catch (ArgumentOutOfRangeException)
{
    Console.WriteLine("Out-of-range query with Throw mode raised exception");
}

// ExtrapolationMode.Clamp: Clamp to boundary
var clampSurface = Numerics.NET.Interpolation.GridLinearInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Clamp);
double z1 = clampSurface.Evaluate(3.0, 0.5);
Console.WriteLine($"Clamped value at (3.0, 0.5): {z1}");

// ExtrapolationMode.Fill: Return NaN
var fillSurface = Numerics.NET.Interpolation.GridLinearInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Fill);
double z2 = fillSurface.Evaluate(3.0, 0.5);
Console.WriteLine($"Fill value at (3.0, 0.5): {z2}");

  Note

Extrapolation applies only to the coordinate space. The interpolator does not perform polynomial or spline extrapolation beyond the grid boundaries; it modifies the query coordinates and then interpolates.

Examples

Example 1: Basic 2D interpolation (linear and cubic)

Suppose you have a function f(x, y) = x² + y² sampled on a coarse 2D grid, and you want to evaluate it at arbitrary points. Create a grid interpolator and compare linear and cubic results:

C#
// Define a 2D rectilinear grid
double[] xAxis = { 0.0, 1.0, 2.0, 3.0 };
double[] yAxis = { 0.0, 1.0, 2.0 };

// Define values on the grid
// Array dimension order: values[i, j] = f(xAxis[i], yAxis[j])
double[,] values = new double[xAxis.Length, yAxis.Length];
for (int i = 0; i < xAxis.Length; i++)
{
    for (int j = 0; j < yAxis.Length; j++)
    {
        values[i, j] = i + j * 4;  // Example function
    }
}

// Create a linear grid interpolator
var surface = Numerics.NET.Interpolation.GridLinearInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Throw);

// Evaluate at a single point
double z1 = surface.Evaluate(1.5, 1.0);
Console.WriteLine($"Linear interpolation at (1.5, 1.0): {z1}");

// Evaluate at multiple points
double z2 = surface.Evaluate(0.5, 0.5);
double z3 = surface.Evaluate(2.5, 1.5);
Console.WriteLine($"Values: ({z2:F2}, {z3:F2})");

Linear interpolation provides a good approximation with minimal computation. For smoother interpolation with continuous derivatives, use the specialized 2D cubic surface:

C#
// Create a cubic spline interpolator for smoother results
var cubicSurface = Numerics.NET.Interpolation.GridCubicInterpolator(
    xAxis, yAxis, values, ExtrapolationMode.Throw);

// Evaluate at the same points - cubic will be smoother
double zc1 = cubicSurface.Evaluate(1.5, 1.0);
double zc2 = cubicSurface.Evaluate(0.5, 0.5);
Console.WriteLine($"Cubic interpolation at (1.5, 1.0): {zc1}");
Console.WriteLine($"Cubic interpolation at (0.5, 0.5): {zc2}");

Example 2: Tensor-product cubic splines with custom boundary conditions

For N-dimensional grids with custom boundary conditions, use CreateCubicTensorSpline or CreateTensorSpline. This example shows periodic interpolation for angular data:

C#
// Create a 2D grid for latitude-longitude data
var latitudes = Vector.LinSpace(-90, 90, 37);   // -90 to +90 degrees
var longitudes = Vector.LinSpace(0, 360, 73);   // 0 to 360 degrees (periodic)

// Sample function values (e.g., temperature field)
var values = new double[latitudes.Count * longitudes.Count];
for (int i = 0; i < values.Length; i++)
    values[i] = Math.Sin(i * 0.1);  // Example data

// Create tensor-product cubic spline with periodic boundary in longitude direction
var surface = Numerics.NET.Interpolation.GridCubicTensorSplineInterpolator(
    new[] { latitudes, longitudes },
    values,
    boundaryCondition: GridBoundaryCondition.Periodic,
    extrapolation: ExtrapolationMode.Default  // Will use Periodic extrapolation
);

// Query at longitude = 370 degrees (wraps to 10 degrees)
double result = surface.Evaluate(new[] { 45.0, 370.0 });
Console.WriteLine($"Temperature at (45°N, 370°E): {result:F2}");

Example 3: Using different spline kernels

The CreateTensorSpline method accepts custom spline kernels. You can choose between linear and cubic kernels, or implement your own:

C#
// Create a 3D grid
var xAxis = Vector.LinSpace(0, 10, 11);
var yAxis = Vector.LinSpace(0, 10, 11);
var zAxis = Vector.LinSpace(0, 10, 11);
var values = new double[11 * 11 * 11];
for (int i = 0; i < values.Length; i++)
    values[i] = i * 0.01;  // Example data

// Option 1: Linear tensor-product interpolation (equivalent to trilinear)
var linearSurface = GridSurface.CreateTensorSpline(
    new[] { xAxis, yAxis, zAxis },
    values,
    kernel: SplineKernels.Linear
);

// Option 2: Cubic Hermite tensor-product interpolation
var cubicSurface = GridSurface.CreateTensorSpline(
    new[] { xAxis, yAxis, zAxis },
    values,
    kernel: SplineKernels.CubicHermite
);

// Both support gradient evaluation
var grad = cubicSurface.Gradient(new[] { 5.0, 5.0, 5.0 });
Console.WriteLine($"Gradient at (5, 5, 5): [{grad[0]:F4}, {grad[1]:F4}, {grad[2]:F4}]");

Example 4: Specialized 2D/3D cubic vs. tensor-product cubic

For 2D and 3D grids, you can choose between specialized cubic surfaces (higher smoothness) and tensor-product cubic splines (more flexibility):

C#
var xAxis = Vector.LinSpace(0, 10, 21);
var yAxis = Vector.LinSpace(0, 10, 21);
var values = new double[21, 21];
for (int i = 0; i < 21; i++)
    for (int j = 0; j < 21; j++)
        values[i, j] = Math.Sin(i * 0.3) * Math.Cos(j * 0.3);

// Flatten for GridSurface factory methods
var flatValues = new double[21 * 21];
for (int i = 0; i < 21; i++)
    for (int j = 0; j < 21; j++)
        flatValues[i * 21 + j] = values[i, j];

// Option A: Specialized 2D cubic surface (C² smoothness, natural boundaries)
var specializedCubic = GridSurface.CreateCubic(
    new[] { xAxis, yAxis },
    flatValues,
    extrapolation: ExtrapolationMode.Throw
);

// Option B: Tensor-product cubic (C¹ smoothness, custom boundaries)
var tensorCubic = GridSurface.CreateCubicTensorSpline(
    new[] { xAxis, yAxis },
    flatValues,
    boundaryCondition: GridBoundaryCondition.Reflect,  // Mirror at boundaries
    extrapolation: ExtrapolationMode.Reflect
);

// specializedCubic has smoother derivatives, tensorCubic is more flexible
double z1 = specializedCubic.Evaluate(new[] { 5.0, 5.0 });
double z2 = tensorCubic.Evaluate(new[] { 5.0, 5.0 });
Console.WriteLine($"Specialized: {z1:F4}, Tensor-product: {z2:F4}");

Example 5: High-dimensional lookup table

Tensor-product interpolation scales to arbitrary dimensions, making it ideal for multi-parameter lookup tables:

C#
// Create a 3D grid interpolator
Vector<double> xAxis = Vector.Create(0.0, 1.0, 2.0);
Vector<double> yAxis = Vector.Create(0.0, 1.0);
Vector<double> zAxis = Vector.Create(0.0, 1.0, 2.0);

// Axes are ordered as [z, y, x] for row-major storage
Vector<double>[] axes = new Vector<double>[] { zAxis, yAxis, xAxis };

// Flat values array in row-major order (z varies slowest, x varies fastest)
Vector<double> values = Vector.Create(
    // z=0, y=0: x values
    1.0, 2.0, 3.0,
    // z=0, y=1: x values
    4.0, 5.0, 6.0,
    // z=1, y=0: x values
    7.0, 8.0, 9.0,
    // z=1, y=1: x values
    10.0, 11.0, 12.0,
    // z=2, y=0: x values
    13.0, 14.0, 15.0,
    // z=2, y=1: x values
    16.0, 17.0, 18.0
);

// Create the ND linear interpolator
var field = Numerics.NET.Interpolation.GridLinearInterpolator(
    axes, values, ExtrapolationMode.Throw);

// Evaluate at a 3D point
Vector<double> point = Vector.Create(1.0, 0.5, 1.5);
double value = field.Evaluate(point);
Console.WriteLine($"3D interpolation at (1.0, 0.5, 1.5): {value}");

This approach works efficiently for moderate dimensions (typically up to 4-6 dimensions in practice, depending on grid resolution and performance requirements).

See Also