双线性插值的 C 代码

2022.08.08 Monday @BJ

Project 中要对二维数据做个插值,用 C 写了个双线性插值的代码,备忘一下。

// bdr 是旧网格的边界, bdrq 是新网格的边界
// NR 是旧网格的节点数,NRq 是新网格的节点数
// v 是旧数据,vq 是再新网格上的插值结果
void Interp2(double bdr[][2], double *v, int *NR, double bdrq[][2], double *vq, int *NRq)
{
    int DIM = 2;
    int NRD = prod(NR, DIM), NRDq = prod(NRq, DIM);
    double dx = (bdr[0][1] - bdr[0][0]) / NR[0], dy = (bdr[1][1] - bdr[1][0]) / NR[1];
    double dxq = (bdrq[0][1] - bdrq[0][0]) / NRq[0], dyq = (bdrq[1][1] - bdrq[1][0]) / NRq[1];

    double xq, yq;
    int num, index[2], indexq[2];
    double index_x, index_y;
    bool out_of_domain;
    double a, b;
    for (int i = 0; i < NRDq; i++)
    {
        // 计算第 i 个点的坐标
        number2index_C(indexq, i, NRq, DIM);
        xq = bdrq[0][0] + indexq[0] * dxq;
        yq = bdrq[1][0] + indexq[1] * dyq;
        // 计算该点在旧网格中左下角的坐标点
        index_x = (xq - bdr[0][0]) / dx;
        index_y = (yq - bdr[1][0]) / dy;
        index[0] = (int)index_x;
        index[1] = (int)index_y;
        a = index_x - index[0];
        b = index_y - index[1];

        out_of_domain = false;
        if (index_x < 0)
        {
            index[0] = 0;
            out_of_domain = true;
        }
        if (index_y < 0)
        {
            index[1] = 0;
            out_of_domain = true;
        }
        if (index_x >= NR[0] - 1)
        {
            index[0] = NR[0] - 1;
            out_of_domain = true;
        }
        if (index_y >= NR[1] - 1)
        {
            index[1] = NR[1] - 1;
            out_of_domain = true;
        }

        // 超出边界的部分, 用最简单的最近邻插值
        if (out_of_domain)
        {
            num = index2number_C(index, NR, DIM);
            vq[i] = v[num];
            continue;
        }

        // 其余用双线性插值
        vq[i] = (1 - a) * (1 - b) * v[index2number_C(index, NR, DIM)]; // index 为左下角点
        index[0] += 1;
        vq[i] += a * (1 - b) * v[index2number_C(index, NR, DIM)]; // index 为右下角点
        index[1] += 1;
        vq[i] += a * b * v[index2number_C(index, NR, DIM)]; // index 为右上角点
        index[0] -= 1;
        vq[i] += (1 - a) * b * v[index2number_C(index, NR, DIM)]; // index 为左上角点
    }
}

其中用到的指标转化函数为

int index2number_C(int *index, int *N, int D)
{
    int num = index[0];
    for (int i = 1; i= 0; i--)
    {
        index[i] = num % N[i];
        num = (num - index[i]) / N[i];
    }
}

你可能感兴趣的:(双线性插值的 C 代码)