Coverage Report

Created: 2025-07-23 09:13

/src/gdal/frmts/grib/degrib/degrib/scan.c
Line
Count
Source
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
 */
57
void ScanIndex2XY (sInt4 row, sInt4 *X, sInt4 *Y, uChar scan, sInt4 Nx,
58
                   sInt4 Ny)
59
28.3M
{
60
28.3M
   sInt4 x;             /* local copy of x */
61
28.3M
   sInt4 y;             /* local copy of y */
62
63
28.3M
   if (scan & GRIB2BIT_3) {
64
36.3k
      x = row / Ny;
65
36.3k
      if ((scan & GRIB2BIT_4) && ((x % 2) == 1)) {
66
2.32k
         y = (Ny - 1) - (row % Ny);
67
34.0k
      } else {
68
34.0k
         y = row % Ny;
69
34.0k
      }
70
28.3M
   } else {
71
28.3M
      y = row / Nx;
72
28.3M
      if ((scan & GRIB2BIT_4) && ((y % 2) == 1)) {
73
272k
         x = (Nx - 1) - (row % Nx);
74
28.0M
      } else {
75
28.0M
         x = row % Nx;
76
28.0M
      }
77
28.3M
   }
78
28.3M
   if (scan & GRIB2BIT_1) {
79
4.19M
      x = (Nx - 1 - x);
80
4.19M
   }
81
28.3M
   if (!(scan & GRIB2BIT_2)) {
82
23.4M
      y = (Ny - 1 - y);
83
23.4M
   }
84
   /* Changed following two lines (with the + 1) on 7/22/2003 */
85
28.3M
   *X = x + 1;
86
28.3M
   *Y = y + 1;
87
28.3M
}
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
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>
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