1 /*****************************************************************************
2  * scan.c
3  *
4  * DESCRIPTION
5  *    This file contains the code that is used to assist with handling the
6  * possible scan values of the grid.
7  *
8  * HISTORY
9  *   10/2002 Arthur Taylor (MDL / RSIS): Created.
10  *
11  * NOTES
12  *****************************************************************************
13  */
14 #include "scan.h"
15 
16 /*****************************************************************************
17  * ScanIndex2XY() --
18  *
19  * Arthur Taylor / MDL
20  *
21  * PURPOSE
22  *   To convert from the index of the GRIB2 message which is defined by the
23  * scan parameter, to one that seemed reasonable.  The choice for internal
24  * array orientation boiled down to either (scan = 0000) (start from upper
25  * left and across similar to a CRT screen) or (scan = 0100) (start at lower
26  * left and go up ).
27  *   It was decided that (scan 0100) was what people expected.  The only catch
28  * is that Spatial Analyst requires (scan = 0000), so when writing to that
29  * format we have to switch.
30  *   For more info on scan flags: see Grib2 "Flag" Table 3.4
31  *
32  * ARGUMENTS
33  *    row = The index in the scanned in data. (Input)
34  *   X, Y = The x,y position in a scan == 0100 world. (Output)
35  *   scan = The orientation of the GRIB2 grid. (Input)
36  * Nx, Ny = The Dimensions of the grid (Input).
37  *
38  * FILES/DATABASES: None
39  *
40  * RETURNS: void
41  *   Returns x, y, in bounds of [1..Nx], [1..Ny]
42  *      Assuming row is in [0..Nx*Ny)
43  *
44  * HISTORY
45  *   10/2002 Arthur Taylor (MDL/RSIS): Created.
46  *    7/2003 AAT: Switched to x, y [1..Nx] because that is what the map
47  *           routines give.
48  *
49  * NOTES
50  * scan based on Grib2 "Flag" Table 3.4
51  *  scan & GRIB2BIT_1 => decrease x
52  *  scan & GRIB2BIT_2 => increase y
53  *  scan & GRIB2BIT_3 => adjacent points in y direction consecutive.
54  *  scan & GRIB2BIT_4 => adjacent rows scan in opposite directions.
55  *****************************************************************************
56  */
ScanIndex2XY(sInt4 row,sInt4 * X,sInt4 * Y,uChar scan,sInt4 Nx,sInt4 Ny)57 void ScanIndex2XY (sInt4 row, sInt4 *X, sInt4 *Y, uChar scan, sInt4 Nx,
58                    sInt4 Ny)
59 {
60    sInt4 x;             /* local copy of x */
61    sInt4 y;             /* local copy of y */
62 
63    if (scan & GRIB2BIT_3) {
64       x = row / Ny;
65       if ((scan & GRIB2BIT_4) && ((x % 2) == 1)) {
66          y = (Ny - 1) - (row % Ny);
67       } else {
68          y = row % Ny;
69       }
70    } else {
71       y = row / Nx;
72       if ((scan & GRIB2BIT_4) && ((y % 2) == 1)) {
73          x = (Nx - 1) - (row % Nx);
74       } else {
75          x = row % Nx;
76       }
77    }
78    if (scan & GRIB2BIT_1) {
79       x = (Nx - 1 - x);
80    }
81    if (!(scan & GRIB2BIT_2)) {
82       y = (Ny - 1 - y);
83    }
84    /* Changed following two lines (with the + 1) on 7/22/2003 */
85    *X = x + 1;
86    *Y = y + 1;
87 }
88 
89 /*****************************************************************************
90  * XY2ScanIndex() --
91  *
92  * Arthur Taylor / MDL
93  *
94  * PURPOSE
95  *   To convert from an x,y coordinate system that matches scan = 0100 to the
96  * scan index of the GRIB2 message as defined by the scan parameter.
97  *   This tends to be less important than ScanIndex2XY, but is provided for
98  * testing purposes, and in case it is useful.
99  *
100  * ARGUMENTS
101  *    Row = The index in the scanned in data. (Output)
102  *   x, y = The x,y position in a (scan = 0100) world. (Input)
103  *   scan = The orientation of the GRIB2 grid. (Input)
104  * Nx, Ny = The Dimensions of the grid (Input).
105  *
106  * FILES/DATABASES: None
107  *
108  * RETURNS: void
109  *   Returns row in [0..Nx*Ny)
110  *      Assuming x, y, is in bounds of [1..Nx], [1..Ny]
111  *
112  * HISTORY
113  *   10/2002 Arthur Taylor (MDL/RSIS): Created.
114  *    7/2003 AAT: Switched to x, y [1..Nx] because that is what the map
115  *           routines give.
116  *
117  * NOTES
118  * scan based on Grib2 "Flag" Table 3.4
119  *  scan & GRIB2BIT_1 => decrease x
120  *  scan & GRIB2BIT_2 => increase y
121  *  scan & GRIB2BIT_3 => adjacent points in y direction consecutive.
122  *  scan & GRIB2BIT_4 => adjacent rows scan in opposite directions.
123  *****************************************************************************
124  */
125 #ifdef unused_by_GDAL
XY2ScanIndex(sInt4 * Row,sInt4 x,sInt4 y,uChar scan,sInt4 Nx,sInt4 Ny)126 void XY2ScanIndex (sInt4 *Row, sInt4 x, sInt4 y, uChar scan, sInt4 Nx,
127                    sInt4 Ny)
128 {
129    sInt4 row;           /* local copy of row */
130 
131    /* Added following two lines on 7/22/2003 */
132    x = x - 1;
133    y = y - 1;
134    if (scan & GRIB2BIT_1) {
135       x = (Nx - 1 - x);
136    }
137    if (!(scan & GRIB2BIT_2)) {
138       y = (Ny - 1 - y);
139    }
140    if (scan & GRIB2BIT_3) {
141       if ((scan & GRIB2BIT_4) && ((x % 2) == 1)) {
142          row = Ny - 1 - y + x * Ny;
143       } else {
144          row = y + x * Ny;
145       }
146    } else {
147       if ((scan & GRIB2BIT_4) && ((y % 2) == 1)) {
148          row = Nx - 1 - x + y * Nx;
149       } else {
150          row = x + y * Nx;
151       }
152    }
153    *Row = row;
154 }
155 #endif // unused_by_GDAL
156 
157 /*****************************************************************************
158  * main() --
159  *
160  * Arthur Taylor / MDL
161  *
162  * PURPOSE
163  *   To test the ScanIndex2XY, and XY2ScanIndex routines, to make sure that
164  * they are inverses of each other, for all possible scan values.  Also to
165  * see what a sample array looks like in the various scans, and to make sure
166  * that we are generating (scan = 0100) data.
167  *
168  * ARGUMENTS
169  * argc = The number of arguments on the command line. (Input)
170  * argv = The arguments on the command line. (Input)
171  *
172  * FILES/DATABASES: None
173  *
174  * RETURNS: void
175  *
176  * HISTORY
177  *   10/2002 Arthur Taylor (MDL/RSIS): Created.
178  *
179  * NOTES
180  *****************************************************************************
181  */
182 #ifdef TEST_SCAN
183 #include <stdio.h>
main(int argc,char ** argv)184 int main (int argc, char **argv)
185 {
186    int data[3][4];
187    int ray1[6];
188    int ray2[6];
189    sInt4 Nx = 2, Ny = 3;
190    sInt4 NxNy = 6;
191    sInt4 row, x, y;
192    sInt4 x1, y1;
193    int i;
194    int scan;
195 
196    /* Set up sample data. */
197    for (x = 1; x <= Nx; x++) {
198       for (y = 1; y <= Ny; y++) {
199          data[x][y] = 1 + x + (y * 2);
200       }
201    }
202    for (i = 0; i < 16; i++) {
203       scan = i << 4;
204       /* Print scan info. */
205       printf ("Checking xy2row -> row2xy for scan %d ", i);
206       if (scan & GRIB2BIT_1)
207          printf ("-1");
208       else
209          printf ("-0");
210       if (scan & GRIB2BIT_2)
211          printf ("-1");
212       else
213          printf ("-0");
214       if (scan & GRIB2BIT_3)
215          printf ("-1");
216       else
217          printf ("-0");
218       if (scan & GRIB2BIT_4)
219          printf ("-1");
220       else
221          printf ("-0");
222       printf ("\n");
223 
224       /* Test invertiblity of functions. */
225       for (x = 1; x <= Nx; x++) {
226          for (y = 1; y <= Ny; y++) {
227             XY2ScanIndex (&row, x, y, scan, Nx, Ny);
228             ScanIndex2XY (row, &x1, &y1, scan, Nx, Ny);
229             if ((x1 != x) || (y1 != y)) {
230                printf ("   %ld %ld .. %ld .. %ld %ld \n", x, y, row, x1, y1);
231             }
232          }
233       }
234 
235       /* Set up sample scan data. */
236       for (x = 1; x <= Nx; x++) {
237          for (y = 1; y <= Ny; y++) {
238             XY2ScanIndex (&row, x, y, scan, Nx, Ny);
239             ray1[row] = data[x][y];
240          }
241       }
242 
243       /* Convert from ray1[] to ray2[] where ray2[] is scan value 0100. */
244       for (x = 0; x < NxNy; x++) {
245          printf ("%d ", ray1[x]);
246          ScanIndex2XY (x, &x1, &y1, scan, Nx, Ny);
247          /*
248           * To get scan 0000 do the following:
249           * row = x1 + ((Ny-1) - y1) * Nx;
250           */
251          row = (x1 - 1) + (y1 - 1) * Nx;
252          ray2[row] = ray1[x];
253       }
254       printf ("\n");
255       for (x = 0; x < NxNy; x++) {
256          printf ("%d ", ray2[x]);
257       }
258       printf ("\n");
259    }
260    return 0;
261 }
262 #endif
263