Interpolation Demo — Smooth Curves from Sample Points
The sangi interpolation module handles, in a unified way, the methods that reconstruct a continuous curve from a discrete set of sample points. This page presents three demos covering the representative interpolation methods (Lagrange interpolation, cubic spline, and PCHIP).
Demo 1: Lagrange Interpolation Exactly Recovers a Polynomial
We sample $p(x)=x^2+1$ at the 3 points $x=0,1,2$ (giving the values $1,2,5$) and then evaluate it at other points using Lagrange interpolation. Since the polynomial of degree at most $n-1$ that passes through $n$ points is unique, when the original is quadratic the interpolant matches exactly, for both interpolation and extrapolation.
Demo 2: The Cubic Spline Passes Through Every Data Point ($C^2$ Continuous)
We construct the natural cubic spline through the 5 points $(0,1),(1,3),(2,2),(3,5),(4,4)$. The spline passes through each data point exactly (the interpolation property) and is a smooth curve that is continuous up to its second derivative ($C^2$).
Demo 3: PCHIP Preserves Monotonicity (No Overshoot)
We interpolate the monotonically non-decreasing data $(0,0),(1,0),(2,0),(3,1),(4,1)$ with PCHIP (Piecewise Cubic Hermite Interpolation, shape-preserving). A cubic spline can overshoot after a flat segment, but PCHIP limits the slope on each interval to preserve monotonicity.
Source Code and How to Run
example_interpolation.cpp (full source code)
// example_interpolation.cpp — Interpolation demo
#include <math/interpolation/Interpolation.hpp>
#include <math/interpolation/BSpline.hpp>
#include <iostream>
#include <iomanip>
#include <vector>
using namespace sangi;
int main() {
std::cout << std::setprecision(12);
// --- Demo 1: Lagrange interpolation exactly recovers a polynomial ---
// p(x) = x^2 + 1 sampled at x = 0, 1, 2 -> y = 1, 2, 5
std::cout << "=== Demo 1: Lagrange recovers a polynomial ===\n";
std::vector<double> x1 = {0.0, 1.0, 2.0};
std::vector<double> y1 = {1.0, 2.0, 5.0}; // p(x) = x^2 + 1
for (double xi : {0.5, 1.5, 3.0}) {
double approx = lagrange_interpolation(x1, y1, xi);
double exact = xi * xi + 1.0;
std::cout << " L(" << xi << ") = " << approx
<< " exact = " << exact << "\n";
}
// --- Demo 2: Natural cubic spline interpolates through every knot ---
std::cout << "\n=== Demo 2: Cubic spline (C^2, passes through every knot) ===\n";
std::vector<double> xs = {0.0, 1.0, 2.0, 3.0, 4.0};
std::vector<double> ys = {1.0, 3.0, 2.0, 5.0, 4.0};
auto spline = cubicSpline(xs, ys);
for (std::size_t i = 0; i < xs.size(); ++i)
std::cout << " S(" << xs[i] << ") = " << spline.eval(xs[i])
<< " data = " << ys[i] << "\n";
// --- Demo 3: PCHIP preserves monotonicity (no overshoot) ---
std::cout << "\n=== Demo 3: PCHIP shape-preserving interpolation ===\n";
std::vector<double> xm = {0.0, 1.0, 2.0, 3.0, 4.0};
std::vector<double> ym = {0.0, 0.0, 0.0, 1.0, 1.0}; // monotone, non-decreasing
auto pchip = pchipCoefficients(xm, ym);
for (std::size_t i = 0; i < xm.size(); ++i)
std::cout << " P(" << xm[i] << ") = "
<< cubic_spline_evaluate(xm, pchip, xm[i])
<< " data = " << ym[i] << "\n";
return 0;
}
For API details, see the Interpolation API Reference.
Build and Run
cd sangi
mkdir build && cd build
cmake .. -G "Visual Studio 17 2022" -A x64
cmake --build . --config Release --target example-interpolation
examples\Release\example-interpolation.exe