使用c/awk/shell对二维数据进行双线性插值



有人知道使用以下任何一种语言c/awk/shell/c++对数据进行双线性插值吗

我的数据文件,这个文件没有排序不知道怎么做:(很大的文件

row col data 
20 14 91 
21 15 95
21 14 162 
20 15 210

我希望输出像这样,列间隔0.5,行间隔0.2

20 14 91 
20 14.5 150.5
20 15 210
20.2 14.5 146.1
.....
.....
.....
21 14 162
21 14.5 128.5
21 15 95 

请帮助

(已编辑以允许移动目标。)

以下内容适用于您的(非常有限!)示例数据集。它是这样工作的:

  1. 将数据集加载到内存中,并将其存储在一个简单的结构中
  2. 对于每一行/列数据项,查找所需的下一项:(行,列>=1)、(行>=1,列)和(行>=1,列>=1)。未测试(因为缺少数据),但使用最接近的值
  3. 如果所有四个数据点都已知,则从左到右、从上到下进行插值

因为样本数据集太小,所以很难提出优化建议。如果连续的行和列之间的距离未知(数据按随机顺序排列,如您的示例中所示),最好尝试将整个文件读取到内存中。

如果数据是按预先排序的,那么在开始时读取一行就足够了,然后对于每个循环,读取下一行。此外,如果数据也按排序,则可以跳过整个find_set例程,并立即调用连续项的interpolate

所有printf语句的错误之处在于,您的首选输出格式无法使用标准的printf格式说明符。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_ITEM    25
struct data_t {
int row;
int col;
int data;
} array[MAX_ITEM];
int n_item = 0;
// interpolate A > B
//             v   v
//             C > D
void interpolate (int A, int B, int C, int D)
{
int i,j, deltaCol,deltaRow;
float a,b, delta_AC, delta_BD, value;
a = array[A].data;
b = array[B].data;
deltaCol = 2*(array[B].col-array[A].col);
deltaRow = 5*(array[C].row-array[A].row);
delta_AC = (array[C].data-array[A].data)/(float)deltaRow;
delta_BD = (array[D].data-array[B].data)/(float)deltaRow;
// rows
for (j=0; j<=deltaRow; j++)
{
// columns
for (i=0; i<=deltaCol; i++)
{
if (j % 5)
printf ("%.1f ", array[A].row+(j/5.0f));
else
printf ("%d ", array[A].row+j/5);
if (i % 2)
printf ("%.1f ", array[A].col+(i/2.0f));
else
printf ("%d ", array[A].col+i/2);
value = a+(b-a)*((float)i/deltaCol);
if ((int)(100*value+0.5) % 100)
printf ("%.1fn", value);
else
printf ("%dn", (int)(value+0.5f));
}
a += delta_AC;
b += delta_BD;
}
}
// For a start row/col A find B,C,D
// where B = A(0,>=1), C=A(>=1,0), D=A(>=1,>=1)
void interpolate_from (int A)
{
int i, B=-1, C=-1, D=-1;
for (i=0; i<n_item; i++)
{
if (i == A) continue;
if (array[A].row == array[i].row)
{
if (array[A].col < array[i].col || (B != -1 && array[i].col < array[B].col))
{
B = i;
}
} else
if (array[A].row < array[i].row)
{
if (array[A].col == array[i].col)
{
C = i;
} else
{
if (array[A].col < array[i].col || (D != -1 && array[i].col < array[D].col))
{
D = i;
}
}
}
if (B+1 && C+1 && D+1)
{
interpolate (A,B,C,D);
return;
}
}
}
int main (void)
{
int i,j,k;
FILE *f;
f = fopen ("data.txt", "r");
while (n_item < MAX_ITEM && fscanf (f, "%d %d %d", &i,&j, &k) == 3)
{
array[n_item].row = i;
array[n_item].col = j;
array[n_item].data = k;
n_item++;
}
fclose (f);
for (i=0; i<n_item; i++)
interpolate_from (i);
printf ("n");
return 0;
}

使用修改后的数据集

20 14 91
21 14 162
21 18 95
20 18 210

输出为:

20 14 91
20 14.5 105.9
20 15 120.8
20 15.5 135.6
...

(等等--运行以查看结果)

听起来像是sort -k1 -k2 -g data.txt的工作。

最新更新