LINEAR_ND_INTERP

This function performs piecewise linear interpolation for scattered data in dimensions greater than one. It triangulates the input point set and evaluates a linear interpolant within each simplex.

For data points \mathbf{x}_i \in \mathbb{R}^N with values v_i, the estimate at a query point \mathbf{x} is computed by barycentric linear combination on the simplex containing \mathbf{x}.

Excel Usage

=LINEAR_ND_INTERP(points, values, xi, fill_value)
  • points (list[list], required): The coordinates of the data points (n_points x n_dims)
  • values (list[list], required): The values at the data points (n_points x 1)
  • xi (list[list], required): The points at which to interpolate (n_new_points x n_dims)
  • fill_value (float, optional, default: 0): Value used for points outside the convex hull

Returns (list[list]): Interpolated values as a 2D list, or error message string.

Example 1: Linear interpolation on 2D unit square

Inputs:

points values xi
0 0 0 0.5 0.5
1 0 1
0 1 1
1 1 2

Excel formula:

=LINEAR_ND_INTERP({0,0;1,0;0,1;1,1}, {0;1;1;2}, {0.5,0.5})

Expected output:

1

Example 2: 2D interpolation with out-of-hull fill value

Inputs:

points values xi fill_value
0 0 1 0.5 0 -999
1 0 2 10 10
0 1 3
1 1 4

Excel formula:

=LINEAR_ND_INTERP({0,0;1,0;0,1;1,1}, {1;2;3;4}, {0.5,0;10,10}, -999)

Expected output:

Result
1.5
-999
Example 3: Linear interpolation in 3D tetrahedron

Inputs:

points values xi
0 0 0 0 0.25 0.25 0.25
1 0 0 1
0 1 0 2
0 0 1 3

Excel formula:

=LINEAR_ND_INTERP({0,0,0;1,0,0;0,1,0;0,0,1}, {0;1;2;3}, {0.25,0.25,0.25})

Expected output:

1.5

Example 4: Multiple query points on 2D square

Inputs:

points values xi fill_value
0 0 0 1 0 0
2 0 4 0 1
0 2 4 1 1
2 2 8

Excel formula:

=LINEAR_ND_INTERP({0,0;2,0;0,2;2,2}, {0;4;4;8}, {1,0;0,1;1,1}, 0)

Expected output:

Result
2
2
4

Python Code

import math
import numpy as np
from scipy.interpolate import LinearNDInterpolator as scipy_LinearNDInterpolator

def linear_nd_interp(points, values, xi, fill_value=0):
    """
    Piecewise linear interpolator in N > 1 dimensions.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.LinearNDInterpolator.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        points (list[list]): The coordinates of the data points (n_points x n_dims)
        values (list[list]): The values at the data points (n_points x 1)
        xi (list[list]): The points at which to interpolate (n_new_points x n_dims)
        fill_value (float, optional): Value used for points outside the convex hull Default is 0.

    Returns:
        list[list]: Interpolated values as a 2D list, or error message string.
    """
    try:
        def to2d(x):
            return [[x]] if not isinstance(x, list) else x

        # Normalize inputs to 2D lists
        points = to2d(points)
        values = to2d(values)
        xi = to2d(xi)

        # Validate that inputs are 2D lists
        if not isinstance(points, list) or not all(isinstance(row, list) for row in points):
            return "Error: Invalid input: points must be a 2D list."
        if not isinstance(values, list) or not all(isinstance(row, list) for row in values):
            return "Error: Invalid input: values must be a 2D list."
        if not isinstance(xi, list) or not all(isinstance(row, list) for row in xi):
            return "Error: Invalid input: xi must be a 2D list."

        # Validate fill_value
        if not isinstance(fill_value, (int, float)):
            return "Error: Invalid input: fill_value must be a number."
        fill_value = float(fill_value)

        # Check dimensions
        if len(points) == 0:
            return "Error: Invalid input: points must not be empty."
        if len(values) == 0:
            return "Error: Invalid input: values must not be empty."
        if len(xi) == 0:
            return "Error: Invalid input: xi must not be empty."

        if len(points) != len(values):
            return "Error: Invalid input: points and values must have the same number of rows."

        # Validate that all rows have consistent dimensions
        n_dims = len(points[0])
        if n_dims < 2:
            return "Error: Invalid input: points must have at least 2 dimensions (N > 1)."

        for i, row in enumerate(points):
            if len(row) != n_dims:
                return f"Error: Invalid input: all rows in points must have the same length (row {i} mismatch)."

        for i, row in enumerate(values):
            if len(row) != 1:
                return f"Error: Invalid input: values must be a column vector (row {i} has {len(row)} columns)."

        xi_dims = len(xi[0])
        if xi_dims != n_dims:
            return f"Error: Invalid input: xi must have same dimensions as points ({n_dims})."

        for i, row in enumerate(xi):
            if len(row) != xi_dims:
                return f"Error: Invalid input: all rows in xi must have the same length (row {i} mismatch)."

        # Validate that all values are numeric and finite
        try:
            for i, row in enumerate(points):
                for j, val in enumerate(row):
                    if not isinstance(val, (int, float)):
                        return f"Error: Invalid input: points[{i}][{j}] must be numeric."
                    if math.isinf(val) or math.isnan(val):
                        return f"Error: Invalid input: points[{i}][{j}] must be finite."

            for i, row in enumerate(values):
                val = row[0]
                if not isinstance(val, (int, float)):
                    return f"Error: Invalid input: values[{i}][0] must be numeric."
                if math.isinf(val) or math.isnan(val):
                    return f"Error: Invalid input: values[{i}][0] must be finite."

            for i, row in enumerate(xi):
                for j, val in enumerate(row):
                    if not isinstance(val, (int, float)):
                        return f"Error: Invalid input: xi[{i}][{j}] must be numeric."
                    if math.isinf(val) or math.isnan(val):
                        return f"Error: Invalid input: xi[{i}][{j}] must be finite."
        except Exception as e:
            return f"Error: Invalid input: error validating numeric values: {e}"

        # Convert to numpy arrays
        try:
            points_arr = np.array(points, dtype=float)
            values_arr = np.array(values, dtype=float).flatten()
            xi_arr = np.array(xi, dtype=float)
        except Exception as e:
            return f"Error: Invalid input: error converting to arrays: {e}"

        # Perform interpolation
        try:
            interp = scipy_LinearNDInterpolator(points_arr, values_arr, fill_value=fill_value)
            result = interp(xi_arr)
        except Exception as e:
            return f"Error: scipy.interpolate.LinearNDInterpolator error: {e}"

        # Convert result to 2D list
        try:
            result_2d = [[float(val)] for val in result]
        except Exception as e:
            return f"Error: Error converting result to 2D list: {e}"

        return result_2d
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

The coordinates of the data points (n_points x n_dims)
The values at the data points (n_points x 1)
The points at which to interpolate (n_new_points x n_dims)
Value used for points outside the convex hull