SpringBoot注解笔记

216 阅读1分钟
import { spline } from 'cubic-hermite-spline';
import { zeros, NdArray } from 'ndarray';

/**
 * 双三次样条插值类
 */
class BicubicSpline {
    private x: number[];
    private y: number[];
    private z: NdArray<number>;

    constructor(x: number[], y: number[], z: number[][]) {
        this.x = x;
        this.y = y;
        const nx = x.length;
        const ny = y.length;

        if (nx < 2 || ny < 2) {
            throw new Error("x and y must have at least two points.");
        }
        if (z.length !== ny || z.some(row => row.length !== nx)) {
            throw new Error("z must be a matrix of size [ny][nx].");
        }

        // 将 z 转换为 NdArray 格式
        this.z = zeros([ny, nx]);
        for (let i = 0; i < ny; i++) {
            for (let j = 0; j < nx; j++) {
                this.z.set(i, j, z[i][j]);
            }
        }
    }

    /**
     * 插值函数
     */
    public interpolate(xVal: number, yVal: number): number {
        const { x, y, z } = this;

        // 找到 xVal 和 yVal 所在的区间索引
        const xi = this.findInterval(x, xVal);
        const yi = this.findInterval(y, yVal);

        // 提取局部网格点
        const xLocal = [x[xi], x[xi + 1]];
        const yLocal = [y[yi], y[yi + 1]];
        const zLocal: number[][] = [
            [z.get(yi, xi), z.get(yi, xi + 1)],
            [z.get(yi + 1, xi), z.get(yi + 1, xi + 1)]
        ];

        // 使用 cubic-hermite-spline 进行插值
        return spline(
            [xVal, yVal],
            [xLocal, yLocal],
            zLocal
        );
    }

    /**
     * 找到值所在的区间索引
     */
    private findInterval(arr: number[], val: number): number {
        let i = 0;
        while (i < arr.length - 1 && val > arr[i + 1]) {
            i++;
        }
        return i;
    }
}

// 示例用法
const x = [0, 1, 2]; // x 坐标
const y = [0, 1, 2]; // y 坐标
const z = [
    [0, 1, 4],
    [1, 2, 5],
    [4, 5, 8]
]; // z 值矩阵

const bicubicSpline = new BicubicSpline(x, y, z);

console.log(bicubicSpline.interpolate(0.5, 0.5)); // 输出插值结果
console.log(bicubicSpline.interpolate(1.5, 1.5));
console.log(bicubicSpline.interpolate(1.2, 0.8));
import CubicSpline from 'cubic-spline';

/**
 * 双三次样条插值类
 */
class BicubicSpline {
    private x: number[];
    private y: number[];
    private z: number[][];
    private rowSplines: CubicSpline[];

    constructor(x: number[], y: number[], z: number[][]) {
        this.x = x;
        this.y = y;
        this.z = z;

        const nx = x.length;
        const ny = y.length;

        if (nx < 2 || ny < 2) {
            throw new Error("x and y must have at least two points.");
        }
        if (z.length !== ny || z.some(row => row.length !== nx)) {
            throw new Error("z must be a matrix of size [ny][nx].");
        }

        // 对每一行 y 进行 x 方向的一维插值
        this.rowSplines = z.map((row) => new CubicSpline(x, row));
    }

    /**
     * 插值函数
     */
    public interpolate(xVal: number, yVal: number): number {
        // 在 x 方向上插值
        const rowValues = this.rowSplines.map(spline => spline.at(xVal));

        // 在 y 方向上插值
        const columnSpline = new CubicSpline(this.y, rowValues);
        return columnSpline.at(yVal);
    }
}

// 示例用法
const x = [0, 1, 2]; // x 坐标
const y = [0, 1, 2]; // y 坐标
const z = [
    [0, 1, 4],
    [1, 2, 5],
    [4, 5, 8]
]; // z 值矩阵

const bicubicSpline = new BicubicSpline(x, y, z);

console.log(bicubicSpline.interpolate(0.5, 0.5)); // 输出插值结果
console.log(bicubicSpline.interpolate(1.5, 1.5));
console.log(bicubicSpline.interpolate(1.2, 0.8));