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