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