双线性插值的 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<D; i++)
        num = num*N[i] + index[i];
    return num;
}
void number2index_C(int *index, int num, int *N, int D)
{
    for (int i = D - 1; i >= 0; i--)
    {
        index[i] = num % N[i];
        num = (num - index[i]) / N[i];
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容