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 accross 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 scaned 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 : */
57 46254 : 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 46254 : if (scan & GRIB2BIT_3) {
64 0 : x = row / Ny;
65 0 : if ((scan & GRIB2BIT_4) && ((x % 2) == 1)) {
66 0 : y = (Ny - 1) - (row % Ny);
67 : } else {
68 0 : y = row % Ny;
69 : }
70 : } else {
71 46254 : y = row / Nx;
72 68910 : if ((scan & GRIB2BIT_4) && ((y % 2) == 1)) {
73 22656 : x = (Nx - 1) - (row % Nx);
74 : } else {
75 23598 : x = row % Nx;
76 : }
77 : }
78 46254 : if (scan & GRIB2BIT_1) {
79 0 : x = (Nx - 1 - x);
80 : }
81 46254 : if (!(scan & GRIB2BIT_2)) {
82 588 : y = (Ny - 1 - y);
83 : }
84 : /* Changed following two lines (with the + 1) on 7/22/2003 */
85 46254 : *X = x + 1;
86 46254 : *Y = y + 1;
87 46254 : }
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 scaned 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 0 : void XY2ScanIndex (sInt4 * Row, sInt4 x, sInt4 y, uChar scan, sInt4 Nx,
126 : sInt4 Ny)
127 : {
128 : sInt4 row; /* local copy of row */
129 :
130 : /* Added following two lines on 7/22/2003 */
131 0 : x = x - 1;
132 0 : y = y - 1;
133 0 : if (scan & GRIB2BIT_1) {
134 0 : x = (Nx - 1 - x);
135 : }
136 0 : if (!(scan & GRIB2BIT_2)) {
137 0 : y = (Ny - 1 - y);
138 : }
139 0 : if (scan & GRIB2BIT_3) {
140 0 : if ((scan & GRIB2BIT_4) && ((x % 2) == 1)) {
141 0 : row = Ny - 1 - y + x * Ny;
142 : } else {
143 0 : row = y + x * Ny;
144 : }
145 : } else {
146 0 : if ((scan & GRIB2BIT_4) && ((y % 2) == 1)) {
147 0 : row = Nx - 1 - x + y * Nx;
148 : } else {
149 0 : row = x + y * Nx;
150 : }
151 : }
152 0 : *Row = row;
153 0 : }
154 :
155 : /*****************************************************************************
156 : * main() --
157 : *
158 : * Arthur Taylor / MDL
159 : *
160 : * PURPOSE
161 : * To test the ScanIndex2XY, and XY2ScanIndex routines, to make sure that
162 : * they are inverses of each other, for all possible scan values. Also to
163 : * see what a sample array looks like in the various scans, and to make sure
164 : * that we are generating (scan = 0100) data.
165 : *
166 : * ARGUMENTS
167 : * argc = The number of arguments on the command line. (Input)
168 : * argv = The arguments on the command line. (Input)
169 : *
170 : * FILES/DATABASES: None
171 : *
172 : * RETURNS: void
173 : *
174 : * HISTORY
175 : * 10/2002 Arthur Taylor (MDL/RSIS): Created.
176 : *
177 : * NOTES
178 : *****************************************************************************
179 : */
180 : #ifdef TEST_SCAN
181 : #include <stdio.h>
182 : int main (int argc, char **argv)
183 : {
184 : int data[3][4];
185 : int ray1[6];
186 : int ray2[6];
187 : sInt4 Nx = 2, Ny = 3;
188 : sInt4 NxNy = 6;
189 : sInt4 row, x, y;
190 : sInt4 x1, y1;
191 : int i;
192 : int scan;
193 :
194 : /* Set up sample data. */
195 : for (x = 1; x <= Nx; x++) {
196 : for (y = 1; y <= Ny; y++) {
197 : data[x][y] = 1 + x + (y * 2);
198 : }
199 : }
200 : for (i = 0; i < 16; i++) {
201 : scan = i << 4;
202 : /* Print scan info. */
203 : printf ("Checking xy2row -> row2xy for scan %d ", i);
204 : if (scan & GRIB2BIT_1)
205 : printf ("-1");
206 : else
207 : printf ("-0");
208 : if (scan & GRIB2BIT_2)
209 : printf ("-1");
210 : else
211 : printf ("-0");
212 : if (scan & GRIB2BIT_3)
213 : printf ("-1");
214 : else
215 : printf ("-0");
216 : if (scan & GRIB2BIT_4)
217 : printf ("-1");
218 : else
219 : printf ("-0");
220 : printf ("\n");
221 :
222 : /* Test invertiblity of functions. */
223 : for (x = 1; x <= Nx; x++) {
224 : for (y = 1; y <= Ny; y++) {
225 : XY2ScanIndex (&row, x, y, scan, Nx, Ny);
226 : ScanIndex2XY (row, &x1, &y1, scan, Nx, Ny);
227 : if ((x1 != x) || (y1 != y)) {
228 : printf (" %ld %ld .. %ld .. %ld %ld \n", x, y, row, x1, y1);
229 : }
230 : }
231 : }
232 :
233 : /* Set up sample scan data. */
234 : for (x = 1; x <= Nx; x++) {
235 : for (y = 1; y <= Ny; y++) {
236 : XY2ScanIndex (&row, x, y, scan, Nx, Ny);
237 : ray1[row] = data[x][y];
238 : }
239 : }
240 :
241 : /* Convert from ray1[] to ray2[] where ray2[] is scan value 0100. */
242 : for (x = 0; x < NxNy; x++) {
243 : printf ("%d ", ray1[x]);
244 : ScanIndex2XY (x, &x1, &y1, scan, Nx, Ny);
245 : /*
246 : * To get scan 0000 do the following:
247 : * row = x1 + ((Ny-1) - y1) * Nx;
248 : */
249 : row = (x1 - 1) + (y1 - 1) * Nx;
250 : ray2[row] = ray1[x];
251 : }
252 : printf ("\n");
253 : for (x = 0; x < NxNy; x++) {
254 : printf ("%d ", ray2[x]);
255 : }
256 : printf ("\n");
257 : }
258 : return 0;
259 : }
260 : #endif
|