1 /*
2 * Name
3 * bilinear.c -- use bilinear interpolation for given row, col
4 *
5 * Description
6 * bilinear interpolation for the given row, column indices.
7 * If the given row or column is outside the bounds of the input map,
8 * the point in the output map is set to NULL.
9 * If any of the 4 surrounding points to be used in the interpolation
10 * is NULL it is filled with is neighbor value
11 */
12
13 #include <math.h>
14 #include "global.h"
15
p_bilinear(struct cache * ibuffer,void * obufptr,int cell_type,double * row_idx,double * col_idx,struct Cell_head * cellhd)16 void p_bilinear(struct cache *ibuffer, /* input buffer */
17 void *obufptr, /* ptr in output buffer */
18 int cell_type, /* raster map type of obufptr */
19 double *row_idx, /* row index */
20 double *col_idx, /* column index */
21 struct Cell_head *cellhd /* information of output map */
22 )
23 {
24 int row; /* row indices for interp */
25 int col; /* column indices for interp */
26 int i, j;
27 double t, u; /* intermediate slope */
28 DCELL result; /* result of interpolation */
29 DCELL c[2][2];
30
31 /* cut indices to integer */
32 row = (int)floor(*row_idx - 0.5);
33 col = (int)floor(*col_idx - 0.5);
34
35 /* check for out of bounds - if out of bounds set NULL value and return */
36 if (row < 0 || row + 1 >= cellhd->rows || col < 0 || col + 1 >= cellhd->cols) {
37 Rast_set_null_value(obufptr, 1, cell_type);
38 return;
39 }
40
41 for (i = 0; i < 2; i++)
42 for (j = 0; j < 2; j++) {
43 const DCELL *cellp = CPTR(ibuffer, row + i, col + j);
44 if (Rast_is_d_null_value(cellp)) {
45 Rast_set_null_value(obufptr, 1, cell_type);
46 return;
47 }
48 c[i][j] = *cellp;
49 }
50
51 /* do the interpolation */
52 t = *col_idx - 0.5 - col;
53 u = *row_idx - 0.5 - row;
54
55 result = Rast_interp_bilinear(t, u, c[0][0], c[0][1], c[1][0], c[1][1]);
56
57 Rast_set_d_value(obufptr, result, cell_type);
58 }
59