GRASS GIS 8 Programmer's Manual  8.2.2dev(2023)-3d2c704037
rd_cellhd.c
Go to the documentation of this file.
1 /*!
2  \file lib/gis/rd_cellhd.c
3 
4  \brief GIS Library - Read cell header or window
5 
6  (C) 1999-2011 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author USACERL and others
12 */
13 
14 #include <string.h>
15 
16 #include <grass/gis.h>
17 #include <grass/glocale.h>
18 
19 #include "gis_local_proto.h"
20 
21 static int scan_item(const char *, char *, char *);
22 static int scan_int(const char *, int *);
23 static double scan_double(const char *, double *);
24 
25 #define F_PROJ 1
26 #define F_ZONE 2
27 #define F_NORTH 3
28 #define F_SOUTH 4
29 #define F_EAST 5
30 #define F_WEST 6
31 #define F_EWRES 7
32 #define F_NSRES 8
33 #define F_FORMAT 9
34 #define F_COMP 10
35 #define F_COLS 11
36 #define F_ROWS 12
37 
38 #define F_EWRES3 13
39 #define F_NSRES3 14
40 #define F_COLS3 15
41 #define F_ROWS3 16
42 #define F_TOP 17
43 #define F_BOTTOM 18
44 #define F_TBRES 19
45 #define F_DEPTHS 20
46 
47 #define SET(x) flags|=(1<<x)
48 #define TEST(x) (flags&(1<<x))
49 
50 /*!
51  \brief Read cell header (for internal use only)
52 
53  \param fp file descriptor
54  \param[out] cellhd pointer to Cell_head structure
55  \param is_cellhd ? (unused)
56 */
57 void G__read_Cell_head(FILE * fd, struct Cell_head *cellhd, int is_cellhd)
58 {
59  int count;
60  char **array;
61  char buf[1024];
62 
63  G_debug(2, "G__read_Cell_head");
64 
65  /* Count lines */
66  count = 0;
67  G_fseek(fd, 0L, 0);
68  while (G_getl(buf, sizeof(buf), fd))
69  count++;
70 
71  array = (char **)G_calloc(count + 1, sizeof(char *));
72 
73  count = 0;
74  G_fseek(fd, 0L, 0);
75  while (G_getl(buf, sizeof(buf), fd)) {
76  array[count] = G_store(buf);
77  count++;
78  }
79 
80  G__read_Cell_head_array(array, cellhd, is_cellhd);
81 
82  count = 0;
83  while (array[count]) {
84  G_free(array[count]);
85  count++;
86  }
87  G_free(array);
88 }
89 
90 /*!
91  \brief Read window from NULL terminated array of strings (for internal use only)
92 
93  \param array array of strings
94  \param[out] cellhd pointer to Cell_head structure
95  \param is_cellhd ? (unused)
96 */
97 void G__read_Cell_head_array(char **array,
98  struct Cell_head *cellhd, int is_cellhd)
99 {
100  char *buf;
101  char label[200];
102  char value[200];
103  int i, line;
104  int flags;
105 
106  G_debug(2, "G__read_Cell_head_array");
107 
108  flags = 0;
109 
110  /* initialize the cell header */
111  cellhd->format = 0;
112  cellhd->rows = 0;
113  cellhd->rows3 = 0;
114  cellhd->cols = 0;
115  cellhd->cols3 = 0;
116  cellhd->depths = 1;
117  cellhd->proj = -1;
118  cellhd->zone = -1;
119  cellhd->compressed = -1;
120  cellhd->ew_res = 0.0;
121  cellhd->ew_res3 = 1.0;
122  cellhd->ns_res = 0.0;
123  cellhd->ns_res3 = 1.0;
124  cellhd->tb_res = 1.0;
125  cellhd->north = 0.0;
126  cellhd->south = 0.0;
127  cellhd->east = 0.0;
128  cellhd->west = 0.0;
129  cellhd->top = 1.0;
130  cellhd->bottom = 0.0;
131 
132  /* determine projection, zone first */
133 
134  i = 0;
135  for (line = 1; (buf = array[i++]); line++) {
136  if (TEST(F_PROJ) && TEST(F_ZONE))
137  break;
138 
139  switch (scan_item(buf, label, value)) {
140  case -1:
141  G_fatal_error(_("Syntax error in cell header, line %d: %s"),
142  line, buf);
143  case 0:
144  continue;
145  case 1:
146  break;
147  }
148  if (strncmp(label, "proj", 4) == 0) {
149  if (TEST(F_PROJ))
150  G_fatal_error(_("Duplicate projection field"));
151 
152  if (!scan_int(value, &cellhd->proj))
153  G_fatal_error(_("Invalid projection field: %s"), value);
154 
155  SET(F_PROJ);
156  continue;
157  }
158  if (strncmp(label, "zone", 4) == 0) {
159  if (TEST(F_ZONE))
160  G_fatal_error(_("Duplicate zone field"));
161 
162  if (!scan_int(value, &cellhd->zone))
163  G_fatal_error(_("Invalid zone field: %s"), value);
164 
165  SET(F_ZONE);
166  continue;
167  }
168  }
169  if (!TEST(F_PROJ))
170  G_fatal_error(_("Field <%s> missing"), "projection");
171  if (!TEST(F_ZONE))
172  G_fatal_error(_("Field <%s> missing"), "zone");
173 
174  /* read the other info */
175  i = 0;
176  for (line = 1; (buf = array[i++]); line++) {
177  G_debug(3, "region item: %s", buf);
178  switch (scan_item(buf, label, value)) {
179  case -1:
180  G_fatal_error(_("Syntax error in cell header, line %d: %s"),
181  line, buf);
182  case 0:
183  continue;
184  case 1:
185  break;
186  }
187 
188  if (strncmp(label, "proj", 4) == 0)
189  continue;
190  if (strncmp(label, "zone", 4) == 0)
191  continue;
192 
193  if (strncmp(label, "nort", 4) == 0) {
194  if (TEST(F_NORTH))
195  G_fatal_error(_("Duplicate north field"));
196  if (!G_scan_northing(value, &cellhd->north, cellhd->proj))
197  G_fatal_error(_("Invalid north field: %s"), value);
198  SET(F_NORTH);
199  continue;
200  }
201  if (strncmp(label, "sout", 4) == 0) {
202  if (TEST(F_SOUTH))
203  G_fatal_error(_("Duplicate south field"));
204  if (!G_scan_northing(value, &cellhd->south, cellhd->proj))
205  G_fatal_error(_("Invalid south field: %s"), value);
206  SET(F_SOUTH);
207  continue;
208  }
209  if (strncmp(label, "east", 4) == 0) {
210  if (TEST(F_EAST))
211  G_fatal_error(_("Duplicate east field"));
212  if (!G_scan_easting(value, &cellhd->east, cellhd->proj))
213  G_fatal_error(_("Invalid east field: %s"), value);
214  SET(F_EAST);
215  continue;
216  }
217  if (strncmp(label, "west", 4) == 0) {
218  if (TEST(F_WEST))
219  G_fatal_error(_("Duplicate west field"));
220  if (!G_scan_easting(value, &cellhd->west, cellhd->proj))
221  G_fatal_error(_("Invalid west field: %s"), value);
222  SET(F_WEST);
223  continue;
224  }
225  if (strncmp(label, "top", 3) == 0) {
226  if (TEST(F_TOP))
227  G_fatal_error(_("Duplicate top field"));
228  if (!scan_double(value, &cellhd->top))
229  G_fatal_error(_("Invalid top field: %s"), value);
230  SET(F_TOP);
231  continue;
232  }
233  if (strncmp(label, "bottom", 6) == 0) {
234  if (TEST(F_BOTTOM))
235  G_fatal_error(_("Duplicate bottom field"));
236  if (!scan_double(value, &cellhd->bottom))
237  G_fatal_error(_("Invalid bottom field: %s"), value);
238  SET(F_BOTTOM);
239  continue;
240  }
241  if (strncmp(label, "e-w ", 4) == 0 && strlen(label) == 9) {
242  if (TEST(F_EWRES))
243  G_fatal_error(_("Duplicate e-w resolution field"));
244  if (!G_scan_resolution(value, &cellhd->ew_res, cellhd->proj))
245  G_fatal_error(_("Invalid e-w resolution field: %s"), value);
246  if (cellhd->ew_res <= 0.0)
247  G_fatal_error(_("Invalid e-w resolution field: %s"), value);
248  SET(F_EWRES);
249  continue;
250  }
251  if (strncmp(label, "e-w resol3", 10) == 0) {
252  if (TEST(F_EWRES3))
253  G_fatal_error(_("Duplicate 3D e-w resolution field"));
254  if (!G_scan_resolution(value, &cellhd->ew_res3, cellhd->proj))
255  G_fatal_error(_("Invalid 3D e-w resolution field: %s"), value);
256  if (cellhd->ew_res3 <= 0.0)
257  G_fatal_error(_("Invalid 3D e-w resolution field: %s"), value);
258  SET(F_EWRES3);
259  continue;
260  }
261  if (strncmp(label, "n-s ", 4) == 0 && strlen(label) == 9) {
262  if (TEST(F_NSRES))
263  G_fatal_error(_("Duplicate n-s resolution field"));
264  if (!G_scan_resolution(value, &cellhd->ns_res, cellhd->proj))
265  G_fatal_error(_("Invalid n-s resolution field: %s"), value);
266  if (cellhd->ns_res <= 0.0)
267  G_fatal_error(_("Invalid n-s resolution field: %s"), value);
268  SET(F_NSRES);
269  continue;
270  }
271  if (strncmp(label, "n-s resol3", 10) == 0) {
272  if (TEST(F_NSRES3))
273  G_fatal_error(_("Duplicate 3D n-s resolution field"));
274  if (!G_scan_resolution(value, &cellhd->ns_res3, cellhd->proj))
275  G_fatal_error(_("Invalid 3D n-s resolution field: %s"), value);
276  if (cellhd->ns_res3 <= 0.0)
277  G_fatal_error(_("Invalid 3D n-s resolution field: %s"), value);
278  SET(F_NSRES3);
279  continue;
280  }
281  if (strncmp(label, "t-b ", 4) == 0) {
282  if (TEST(F_TBRES))
283  G_fatal_error(_("Duplicate t-b resolution field"));
284  if (!scan_double(value, &cellhd->tb_res))
285  G_fatal_error(_("Invalid t-b resolution field: %s"), value);
286  if (cellhd->tb_res <= 0.0)
287  G_fatal_error(_("Invalid t-b resolution field: %s"), value);
288  SET(F_TBRES);
289  continue;
290  }
291  if (strncmp(label, "rows", 4) == 0 && strlen(label) == 4) {
292  if (TEST(F_ROWS))
293  G_fatal_error(_("Duplicate rows field"));
294  if (!scan_int(value, &cellhd->rows))
295  G_fatal_error(_("Invalid rows field: %s"), value);
296  if (cellhd->rows <= 0)
297  G_fatal_error(_("Invalid rows field: %s"), value);
298  SET(F_ROWS);
299  continue;
300  }
301  if (strncmp(label, "rows3", 5) == 0) {
302  if (TEST(F_ROWS3))
303  G_fatal_error(_("Duplicate 3D rows field"));
304  if (!scan_int(value, &cellhd->rows3))
305  G_fatal_error(_("Invalid 3D rows field: %s"), value);
306  if (cellhd->rows3 <= 0)
307  G_fatal_error(_("Invalid 3D rows field: %s"), value);
308  SET(F_ROWS3);
309  continue;
310  }
311  if (strncmp(label, "cols", 4) == 0 && strlen(label) == 4) {
312  if (TEST(F_COLS))
313  G_fatal_error(_("Duplicate cols field"));
314  if (!scan_int(value, &cellhd->cols))
315  G_fatal_error(_("Invalid cols field: %s"), value);
316  if (cellhd->cols <= 0)
317  G_fatal_error(_("Invalid cols field: %s"), value);
318  SET(F_COLS);
319  continue;
320  }
321  if (strncmp(label, "cols3", 5) == 0) {
322  if (TEST(F_COLS3))
323  G_fatal_error(_("Duplicate 3D cols field"));
324  if (!scan_int(value, &cellhd->cols3))
325  G_fatal_error(_("Invalid 3D cols field: %s"), value);
326  if (cellhd->cols3 <= 0)
327  G_fatal_error(_("Invalid 3D cols field: %s"), value);
328  SET(F_COLS3);
329  continue;
330  }
331  if (strncmp(label, "depths", 6) == 0) {
332  if (TEST(F_DEPTHS))
333  G_fatal_error(_("Duplicate depths field"));
334  if (!scan_int(value, &cellhd->depths))
335  G_fatal_error(_("Invalid depths field: %s"), value);
336  if (cellhd->depths <= 0)
337  G_fatal_error(_("Invalid depths field: %s"), value);
338  SET(F_DEPTHS);
339  continue;
340  }
341  if (strncmp(label, "form", 4) == 0) {
342  if (TEST(F_FORMAT))
343  G_fatal_error(_("Duplicate format field"));
344  if (!scan_int(value, &cellhd->format))
345  G_fatal_error(_("Invalid format field: %s"), value);
346  SET(F_FORMAT);
347  continue;
348  }
349  if (strncmp(label, "comp", 4) == 0) {
350  if (TEST(F_COMP))
351  G_fatal_error(_("Duplicate compressed field"));
352  if (!scan_int(value, &cellhd->compressed))
353  G_fatal_error(_("Invalid compressed field: %s"), value);
354  SET(F_COMP);
355  continue;
356  }
357  G_fatal_error(_("Syntax error in cell header, line %d: %s"),
358  line, buf);
359  }
360 
361  /* check some of the fields */
362  if (!TEST(F_NORTH))
363  G_fatal_error(_("Field <%s> missing"), "north");
364  if (!TEST(F_SOUTH))
365  G_fatal_error(_("Field <%s> missing"), "south");
366  if (!TEST(F_WEST))
367  G_fatal_error(_("Field <%s> missing"), "west");
368  if (!TEST(F_EAST))
369  G_fatal_error(_("Field <%s> missing"), "east");
370  if (!TEST(F_EWRES) && !TEST(F_COLS))
371  G_fatal_error(_("Field <%s> missing"), "cols");
372  if (!TEST(F_NSRES) && !TEST(F_ROWS))
373  G_fatal_error(_("Field <%s> missing"), "rows");
374  /* This next stmt is commented out to allow wr_cellhd.c to write
375  * headers that will be readable by GRASS 3.1
376  if ((TEST(F_ROWS) && TEST(F_NSRES))
377  || (TEST(F_COLS) && TEST(F_EWRES)))
378  ERROR ("row/col and resolution information can not both appear ",0);
379  */
380 
381  /* 3D defined? */
382  if (TEST(F_EWRES3) || TEST(F_NSRES3) || TEST(F_COLS3) || TEST(F_ROWS3)) {
383  if (!TEST(F_EWRES3))
384  G_fatal_error(_("Field <%s> missing"), "ewres3");
385  if (!TEST(F_NSRES3))
386  G_fatal_error(_("Field <%s> missing"), "nsres3");
387  if (!TEST(F_COLS3))
388  G_fatal_error(_("Field <%s> missing"), "cols3");
389  if (!TEST(F_ROWS3))
390  G_fatal_error(_("Field <%s> missing"), "rows3");
391  }
392  else { /* use 2D */
393  cellhd->ew_res3 = cellhd->ew_res;
394  cellhd->ns_res3 = cellhd->ns_res;
395  cellhd->cols3 = cellhd->cols;
396  cellhd->rows3 = cellhd->rows;
397  }
398 
399  /* Adjust and complete the cell header */
401 }
402 
403 static int scan_item(const char *buf, char *label, char *value)
404 {
405  /* skip blank lines */
406  if (sscanf(buf, "%1s", label) != 1)
407  return 0;
408 
409  /* skip comment lines */
410  if (*label == '#')
411  return 0;
412 
413  /* must be label: value */
414  if (sscanf(buf, "%[^:]:%[^\n]", label, value) != 2)
415  return -1;
416 
417  G_strip(label);
418  G_strip(value);
419  return 1;
420 }
421 
422 static int scan_int(const char *buf, int *n)
423 {
424  char dummy[3];
425 
426  *dummy = 0;
427  return (sscanf(buf, "%d%1s", n, dummy) == 1 && *dummy == 0);
428 }
429 
430 static double scan_double(const char *buf, double *n)
431 {
432  char dummy[3];
433 
434  *dummy = 0;
435  return (sscanf(buf, "%lf%1s", n, dummy) == 1 && *dummy == 0);
436 }
437 
int G_getl(char *, int, FILE *)
Gets a line of text from a file.
Definition: getl.c:31
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
#define F_SOUTH
Definition: rd_cellhd.c:28
#define F_ROWS
Definition: rd_cellhd.c:36
2D/3D raster map header (used also for region)
Definition: gis.h:423
#define F_COLS3
Definition: rd_cellhd.c:40
#define F_EWRES3
Definition: rd_cellhd.c:38
double west
Extent coordinates (west)
Definition: gis.h:475
#define F_PROJ
Definition: rd_cellhd.c:25
#define F_ROWS3
Definition: rd_cellhd.c:41
#define F_COMP
Definition: rd_cellhd.c:34
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
int count
void G__read_Cell_head(FILE *fd, struct Cell_head *cellhd, int is_cellhd)
Read cell header (for internal use only)
Definition: rd_cellhd.c:57
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition: strings.c:300
int format
Max number of bytes per raster data value minus 1 (raster header only)
Definition: gis.h:429
#define F_NORTH
Definition: rd_cellhd.c:27
#define G_calloc(m, n)
Definition: defs/gis.h:113
int cols3
Number of columns for 3D data.
Definition: gis.h:444
double top
Extent coordinates (top) - 3D data.
Definition: gis.h:477
#define F_BOTTOM
Definition: rd_cellhd.c:43
int compressed
Compression mode (raster header only)
Definition: gis.h:436
double north
Extent coordinates (north)
Definition: gis.h:469
double ns_res3
Resolution - north to south cell size for 3D data.
Definition: gis.h:465
#define F_EAST
Definition: rd_cellhd.c:29
int rows3
Number of rows for 3D data.
Definition: gis.h:440
int G_scan_easting(const char *, double *, int)
ASCII easting to double.
Definition: wind_scan.c:69
int G_scan_resolution(const char *, double *, int)
ASCII resolution to double.
Definition: wind_scan.c:100
#define F_FORMAT
Definition: rd_cellhd.c:33
void G__read_Cell_head_array(char **array, struct Cell_head *cellhd, int is_cellhd)
Read window from NULL terminated array of strings (for internal use only)
Definition: rd_cellhd.c:97
double south
Extent coordinates (south)
Definition: gis.h:471
int zone
Projection zone (UTM)
Definition: gis.h:457
void G_fseek(FILE *, off_t, int)
Change the file position of the stream.
Definition: gis/seek.c:50
double bottom
Extent coordinates (bottom) - 3D data.
Definition: gis.h:479
int depths
number of depths for 3D data
Definition: gis.h:446
int proj
Projection code.
Definition: gis.h:455
void G_adjust_Cell_head(struct Cell_head *, int, int)
Adjust cell header.
Definition: adj_cellhd.c:51
#define F_NSRES
Definition: rd_cellhd.c:32
#define F_WEST
Definition: rd_cellhd.c:30
#define F_ZONE
Definition: rd_cellhd.c:26
#define F_TOP
Definition: rd_cellhd.c:42
int cols
Number of columns for 2D data.
Definition: gis.h:442
double ns_res
Resolution - north to south cell size for 2D data.
Definition: gis.h:463
#define TEST(x)
Definition: rd_cellhd.c:48
double east
Extent coordinates (east)
Definition: gis.h:473
#define _(str)
Definition: glocale.h:10
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
#define F_NSRES3
Definition: rd_cellhd.c:39
#define SET(x)
Definition: rd_cellhd.c:47
#define F_COLS
Definition: rd_cellhd.c:35
double ew_res
Resolution - east to west cell size for 2D data.
Definition: gis.h:459
double tb_res
Resolution - top to bottom cell size for 3D data.
Definition: gis.h:467
int rows
Number of rows for 2D data.
Definition: gis.h:438
int G_debug(int, const char *,...) __attribute__((format(printf
double ew_res3
Resolution - east to west cell size for 3D data.
Definition: gis.h:461
#define F_TBRES
Definition: rd_cellhd.c:44
int G_scan_northing(const char *, double *, int)
ASCII northing to double.
Definition: wind_scan.c:38
#define F_EWRES
Definition: rd_cellhd.c:31
#define F_DEPTHS
Definition: rd_cellhd.c:45