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