C语言实现matlab的interp2()函数

   项目要用到matlab中的Vq = interp2(X,Y,V,Xq,Yq)函数,即把一个已知经纬度和对应值的矩阵,插值变换到一个给定经纬度网格中,也就是对给定网格填值,需要用到插值,这里使用双线性内插法。

*(这只是一个初步完成代码,仅供参考)

以下是对应C代码和测试程序:

  1 //************************************
  2 // 函数名称: inter_linear()
  3 // 函数说明:计算两点之间某一给定点的值,(x0,y0)->(x1,y1),已知x(x0<x<x1),求y
  4 // 返 回 值: double
  5 // 参    数: double x0,y0,x1,y1/*in*/    两个点的坐标(x0,y0)(x1,y1)
  6 
  7 // 作    者:WSS
  8 // 作成日期:2019/09/05
  9 
 10 //************************************
 11 double inter_linear(double x0, double y0, double x1, double y1, double x)
 12 {
 13     double a0, a1, y;
 14     a0 = (x - x1) / (x0 - x1);
 15     a1 = (x - x0) / (x1 - x0);
 16     y = a0*y0 + a1*y1;
 17     return y;
 18 }
 19 //************************************
 20 // 函数名称: interp2d()
 21 // 函数说明:二维插值,同matlab的interp2()功能
 22 // 返 回 值: double
 23 // 参    数: x,y分别为长度为m和n的向量(一维数组),z为矩阵(对应的二维数组(m,n))
 24 //           a,b分别为长度为asize和bsize的向量(一维数组),out_result为矩阵(对应的二维数组(asize,bsize))
 25 
 26 // 作    者:WSS
 27 // 作成日期:2019/09/05
 28 
 29 //************************************
 30 int interp2d(double *x, double *y, double *z, int m, int n, double *a, double *b, int asize,int bsize,double *out_result)
 31 {
 32     //a,b是待插值的矩阵行和列,遍历a,取出行,遍历b取出列,将插值计算后的值存储在out_result中
 33     double pointa = 0;
 34     double pointb = 0;
 35     double w1, w2,w;
 36     const int nu_val = -9999;
 37     int tempi = 0;
 38     int tempj =0;
 39     for (int i = 0; i < asize; ++i)
 40     {
 41         for (int j = 0; j < bsize; ++j)
 42         {
 43             // 找到网格点位置
 44             pointa = a[i];
 45             pointb = b[j];
 46             //确定pointa pointb所在的位置
 47             for (int p = 0; p < m-1; ++p)
 48             {
 49                 if (pointa < x[0]||pointa>x[m-1])//范围外的值不进行插值处理
 50                 {
 51                     tempi = nu_val;
 52                     break;
 53                 }
 54                 else if (pointa == x[m - 1])
 55                 {
 56                     tempi = m - 1;
 57                     break;
 58                 }
 59                 else if(pointa >= x[p] && pointa < x[p+1])//x升序
 60                 {
 61                     tempi = p;
 62                     break;
 63                 }
 64             }
 65             for (int q = 0; q < n - 1; ++q)
 66             {
 67                 if (pointb< y[0] || pointb>y[n- 1])//范围外的值不进行插值处理
 68                 {
 69                     tempj = nu_val;
 70                     break;
 71                 }
 72                 else if (pointb == y[n - 1])
 73                 {
 74                     tempj = n - 1;
 75                     break;
 76                 }
 77                 else if (pointb >= y[q] && pointb < y[q + 1])//y升序
 78                 {
 79                     tempj = q;
 80                     break;
 81                 }
 82             }
 83             if (tempj == nu_val || tempi == nu_val)
 84             {
 85                 out_result[i*bsize + j] = -9999;
 86             }
 87             else
 88             {
 89                 cout << tempi << " " << tempj << endl;
 90                 /**************x方向进行插值*************/
 91                 if (x[tempi] == pointa)
 92                 {
 93                     //取网格节点值
 94                     w1 = z[tempi*n + tempj];
 95                     w2 = z[tempi*n + tempj + 1];
 96                     //y方向进行插值
 97                     if (y[tempj] == pointb)
 98                     {
 99                         w = w1;
100                     }
101                     else
102                     {
103                         w = inter_linear(y[tempj], w1, y[tempj + 1], w2, pointb);
104                     }
105                 }
106                 else
107                 {
108                     //x方向进行插值
109                     w1 = inter_linear(x[tempi], z[tempi*n + tempj], x[tempi + 1], z[(tempi + 1)*n + tempj], pointa);
110                     w2 = inter_linear(x[tempi], z[tempi*n + tempj + 1], x[tempi + 1], z[(tempi + 1)*n + tempj + 1], pointa);
111                     /*******y方向进行插值********/
112 
113                     if (y[tempj] == pointb)
114 
115                     {
116 
117                         //取网格节点值
118 
119                         w = w1;
120 
121                     }
122                     else
123                     {
124                         //进行插值(y)
125 
126                         w = inter_linear(y[tempj], w1, y[tempj + 1], w2, pointb);
127                     }
128                 }
129                 out_result[i*bsize + j] = w;
130             }
131             
132             
133         }
134     }
135     return 0;
136 }

测试函数:

 1 int main()
 2 {
 3     //插值函数测试
 4     int ret = 0;
 5     double a1[5] = { 10, 20, 30, 40, 50 };
 6     double a2[6] = {1,2,4,6,8,9};
 7     double z[30] ;
 8     for (int i = 0; i < 5; ++i)
 9     {
10         for (int j = 0; j < 6; ++j)
11         {
12             z[i*6+j] = a1[i]+a2[j];
13         }
14     }
15 
16     double b1[10] = { 10, 20, 30, 40, 50, 10, 20, 30, 40, 50 };
17     double b2[18] = { 0, 2, 4, 6, 8, 10, 0, 2, 4, 6, 8, 10, 0, 2, 4, 6, 8, 10 };
18     double zout[180];
19     ret = interp2d(a1, a2, z, 5, 6, b1, b2, 10, 18, zout);
20     for (int i = 0; i < 5; ++i)
21     {
22         for (int j = 0; j < 6; j++)
23         {
24             cout << z[i * 6 + j] << " ";
25         }
26         cout << endl;
27     }
28     cout << endl;
29     for (int i = 0; i < 10; ++i)
30     {
31         for (int j = 0; j <18; j++)
32         {
33             cout << zout[i *18 + j] << " ";
34         }
35         cout << endl;
36     }
37  return 0;
38 }

猜你喜欢

转载自www.cnblogs.com/rswss/p/11468265.html
今日推荐