GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
n_arrays_io.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * MODULE: Grass PDE Numerical Library
4  * AUTHOR(S): Soeren Gebbert, Berlin (GER) Dec 2006
5  * soerengebbert <at> gmx <dot> de
6  *
7  * PURPOSE: IO array management functions
8  * part of the gpde library
9  *
10  * COPYRIGHT: (C) 2000 by the GRASS Development Team
11  *
12  * This program is free software under the GNU General Public
13  * License (>=v2). Read the file COPYING that comes with GRASS
14  * for details.
15  *
16  *****************************************************************************/
17 
18 #include <math.h>
19 
20 #include <grass/N_pde.h>
21 #include <grass/raster.h>
22 #include <grass/glocale.h>
23 
24 /* ******************** 2D ARRAY FUNCTIONS *********************** */
25 
26 /*!
27  * \brief Read a raster map into a N_array_2d structure
28  *
29  * The raster map will be opened in the current region settings.
30  * If no N_array_2d structure is provided (NULL pointer), a new structure will
31  * be allocated with the same data type as the raster map and the size of the
32  * current region. The array offset will be set to 0. <br><br> If a N_array_2d
33  * structure is provided, the values from the raster map are casted to the
34  * N_array_2d type. The array must have the same size as the current region.
35  * <br><br>
36  * The new created or the provided array are returned.
37  * If the reading of the raster map fails, G_fatal_error() will
38  * be invoked.
39  *
40  * \param name * char - the name of an existing raster map
41  * \param array * N_array_2d - an existing array or NULL
42  * \return N_array_2d * - the existing or new allocated array
43  * */
45 {
46  int map; /*The rastermap */
47  int x, y, cols, rows, type;
48  void *rast;
49  void *ptr;
50  struct Cell_head region;
51  N_array_2d *data = array;
52 
53  /* Get the active region */
54  G_get_set_window(&region);
55 
56  /*set the rows and cols */
57  rows = region.rows;
58  cols = region.cols;
59 
60  /*open the raster map */
61  map = Rast_open_old(name, "");
62 
63  type = Rast_get_map_type(map);
64 
65  /*if the array is NULL create a new one with the data type of the raster map
66  */
67  /*the offset is 0 by default */
68  if (data == NULL) {
69  if (type == DCELL_TYPE) {
70  data = N_alloc_array_2d(cols, rows, 0, DCELL_TYPE);
71  }
72  if (type == FCELL_TYPE) {
73  data = N_alloc_array_2d(cols, rows, 0, FCELL_TYPE);
74  }
75  if (type == CELL_TYPE) {
76  data = N_alloc_array_2d(cols, rows, 0, CELL_TYPE);
77  }
78  }
79  else {
80  /*Check the array sizes */
81  if (data->cols != cols)
82  G_fatal_error("N_read_rast_to_array_2d: the data array size is "
83  "different from the current region settings");
84  if (data->rows != rows)
85  G_fatal_error("N_read_rast_to_array_2d: the data array size is "
86  "different from the current region settings");
87  }
88 
89  rast = Rast_allocate_buf(type);
90 
91  G_message(_("Reading raster map <%s> into memory"), name);
92 
93  for (y = 0; y < rows; y++) {
94  G_percent(y, rows - 1, 10);
95 
96  Rast_get_row(map, rast, y, type);
97 
98  for (x = 0, ptr = rast; x < cols;
99  x++, ptr = G_incr_void_ptr(ptr, Rast_cell_size(type))) {
100  if (type == CELL_TYPE) {
101  if (Rast_is_c_null_value(ptr)) {
102  N_put_array_2d_value_null(data, x, y);
103  }
104  else {
105  if (data->type == CELL_TYPE)
106  N_put_array_2d_c_value(data, x, y,
107  (CELL) * (CELL *)ptr);
108  if (data->type == FCELL_TYPE)
109  N_put_array_2d_f_value(data, x, y,
110  (FCELL) * (CELL *)ptr);
111  if (data->type == DCELL_TYPE)
112  N_put_array_2d_d_value(data, x, y,
113  (DCELL) * (CELL *)ptr);
114  }
115  }
116  if (type == FCELL_TYPE) {
117  if (Rast_is_f_null_value(ptr)) {
118  N_put_array_2d_value_null(data, x, y);
119  }
120  else {
121  if (data->type == CELL_TYPE)
122  N_put_array_2d_c_value(data, x, y,
123  (CELL) * (FCELL *)ptr);
124  if (data->type == FCELL_TYPE)
125  N_put_array_2d_f_value(data, x, y,
126  (FCELL) * (FCELL *)ptr);
127  if (data->type == DCELL_TYPE)
128  N_put_array_2d_d_value(data, x, y,
129  (DCELL) * (FCELL *)ptr);
130  }
131  }
132  if (type == DCELL_TYPE) {
133  if (Rast_is_d_null_value(ptr)) {
134  N_put_array_2d_value_null(data, x, y);
135  }
136  else {
137  if (data->type == CELL_TYPE)
138  N_put_array_2d_c_value(data, x, y,
139  (CELL) * (DCELL *)ptr);
140  if (data->type == FCELL_TYPE)
141  N_put_array_2d_f_value(data, x, y,
142  (FCELL) * (DCELL *)ptr);
143  if (data->type == DCELL_TYPE)
144  N_put_array_2d_d_value(data, x, y,
145  (DCELL) * (DCELL *)ptr);
146  }
147  }
148  }
149  }
150 
151  /* Close file */
152  Rast_close(map);
153  G_free(rast);
154 
155  return data;
156 }
157 
158 /*!
159  * \brief Write a N_array_2d struct to a raster map
160  *
161  * A new raster map is created with the same type as the N_array_2d.
162  * The current region is used to open the raster map.
163  * The N_array_2d must have the same size as the current region.
164  If the writing of the raster map fails, G_fatal_error() will
165  * be invoked.
166 
167  * \param array N_array_2d *
168  * \param name char * - the name of the raster map
169  * \return void
170  *
171  * */
173 {
174  int map; /*The rastermap */
175  int x, y, cols, rows, type;
176  CELL *rast = NULL;
177  FCELL *frast = NULL;
178  DCELL *drast = NULL;
179  struct Cell_head region;
180 
181  if (!array)
182  G_fatal_error(_("N_array_2d * array is empty"));
183 
184  /* Get the current region */
185  G_get_set_window(&region);
186 
187  rows = region.rows;
188  cols = region.cols;
189  type = array->type;
190 
191  /*Open the new map */
192  map = Rast_open_new(name, type);
193 
194  if (type == CELL_TYPE)
195  rast = Rast_allocate_buf(type);
196  if (type == FCELL_TYPE)
197  frast = Rast_allocate_buf(type);
198  if (type == DCELL_TYPE)
199  drast = Rast_allocate_buf(type);
200 
201  G_message(_("Write 2d array to raster map <%s>"), name);
202 
203  for (y = 0; y < rows; y++) {
204  G_percent(y, rows - 1, 10);
205  for (x = 0; x < cols; x++) {
206  if (type == CELL_TYPE)
207  rast[x] = N_get_array_2d_c_value(array, x, y);
208  if (type == FCELL_TYPE)
209  frast[x] = N_get_array_2d_f_value(array, x, y);
210  if (type == DCELL_TYPE)
211  drast[x] = N_get_array_2d_d_value(array, x, y);
212  }
213  if (type == CELL_TYPE)
214  Rast_put_c_row(map, rast);
215  if (type == FCELL_TYPE)
216  Rast_put_f_row(map, frast);
217  if (type == DCELL_TYPE)
218  Rast_put_d_row(map, drast);
219  }
220 
221  /* Close file */
222  Rast_close(map);
223  G_free(rast);
224  G_free(frast);
225  G_free(drast);
226 }
227 
228 /* ******************** 3D ARRAY FUNCTIONS *********************** */
229 
230 /*!
231  * \brief Read a volume map into a N_array_3d structure
232  *
233  * The volume map is opened in the current region settings.
234  * If no N_array_3d structure is provided (NULL pointer), a new structure will
235  * be allocated with the same data type as the volume map and the size of the
236  * current region. The array offset will be set to 0. <br><br>
237  *
238  * If a N_array_3d structure is provided, the values from the volume map are
239  * casted to the N_array_3d type. The array must have the same size
240  * as the current region.
241  * <br><br>
242  *
243  * The new created or the provided array is returned.
244  * If the reading of the volume map fails, Rast3d_fatal_error() will
245  * be invoked.
246  *
247  * \param name * char - the name of an existing volume map
248  * \param array * N_array_3d - an existing array or NULL
249  * \param mask int - 0 = false, 1 = true : if a mask is presenent, use it with
250  * the input volume map \return N_array_3d * - the existing or new allocated
251  * array
252  * */
254 {
255  void *map = NULL; /*The 3D Rastermap */
256  int changemask = 0;
257  int x, y, z, cols, rows, depths, type;
258  double d1 = 0, f1 = 0;
259  N_array_3d *data = array;
260  RASTER3D_Region region;
261 
262  /*get the current region */
263  Rast3d_get_window(&region);
264 
265  cols = region.cols;
266  rows = region.rows;
267  depths = region.depths;
268 
269  if (NULL == G_find_raster3d(name, ""))
270  Rast3d_fatal_error(_("3D raster map <%s> not found"), name);
271 
272  /*Open all maps with default region */
273  map = Rast3d_open_cell_old(
276 
277  if (map == NULL)
278  Rast3d_fatal_error(_("Unable to open 3D raster map <%s>"), name);
279 
280  type = Rast3d_tile_type_map(map);
281 
282  /*if the array is NULL create a new one with the data type of the volume map
283  */
284  /*the offset is 0 by default */
285  if (data == NULL) {
286  if (type == FCELL_TYPE) {
288  }
289  if (type == DCELL_TYPE) {
291  }
292  }
293  else {
294  /*Check the array sizes */
295  if (data->cols != cols)
296  G_fatal_error("N_read_rast_to_array_3d: the data array size is "
297  "different from the current region settings");
298  if (data->rows != rows)
299  G_fatal_error("N_read_rast_to_array_3d: the data array size is "
300  "different from the current region settings");
301  if (data->depths != depths)
302  G_fatal_error("N_read_rast_to_array_3d: the data array size is "
303  "different from the current region settings");
304  }
305 
306  G_message(_("Read g3d map <%s> into the memory"), name);
307 
308  /*if requested set the Mask on */
309  if (mask) {
310  if (Rast3d_mask_file_exists()) {
311  changemask = 0;
312  if (Rast3d_mask_is_off(map)) {
313  Rast3d_mask_on(map);
314  changemask = 1;
315  }
316  }
317  }
318 
319  for (z = 0; z < depths; z++) { /*From the bottom to the top */
320  G_percent(z, depths - 1, 10);
321  for (y = 0; y < rows; y++) {
322  for (x = 0; x < cols; x++) {
323  if (type == FCELL_TYPE) {
324  Rast3d_get_value(map, x, y, z, &f1, type);
325  if (Rast_is_f_null_value((void *)&f1)) {
326  N_put_array_3d_value_null(data, x, y, z);
327  }
328  else {
329  if (data->type == FCELL_TYPE)
330  N_put_array_3d_f_value(data, x, y, z, f1);
331  if (data->type == DCELL_TYPE)
332  N_put_array_3d_d_value(data, x, y, z, (double)f1);
333  }
334  }
335  else {
336  Rast3d_get_value(map, x, y, z, &d1, type);
337  if (Rast_is_d_null_value((void *)&d1)) {
338  N_put_array_3d_value_null(data, x, y, z);
339  }
340  else {
341  if (data->type == FCELL_TYPE)
342  N_put_array_3d_f_value(data, x, y, z, (float)d1);
343  if (data->type == DCELL_TYPE)
344  N_put_array_3d_d_value(data, x, y, z, d1);
345  }
346  }
347  }
348  }
349  }
350 
351  /*We set the Mask off, if it was off before */
352  if (mask) {
354  if (Rast3d_mask_is_on(map) && changemask)
355  Rast3d_mask_off(map);
356  }
357 
358  /* Close files and exit */
359  if (!Rast3d_close(map))
360  Rast3d_fatal_error(_("Error closing g3d file <%s>"), name);
361 
362  return data;
363 }
364 
365 /*!
366  * \brief Write a N_array_3d struct to a volume map
367  *
368  * A new volume map is created with the same type as the N_array_3d.
369  * The current region is used to open the volume map.
370  * The N_array_3d must have the same size as the current region.
371  * If the writing of the volume map fails, Rast3d_fatal_error() will
372  * be invoked.
373  *
374  *
375  * \param array N_array_3d *
376  * \param name char * - the name of the volume map
377  * \param mask int - 1 = use a 3d mask, 0 do not use a 3d mask
378  * \return void
379  *
380  * */
381 void N_write_array_3d_to_rast3d(N_array_3d *array, char *name, int mask)
382 {
383  void *map = NULL; /*The 3D Rastermap */
384  int changemask = 0;
385  int x, y, z, cols, rows, depths, type;
386  double d1 = 0.0, f1 = 0.0;
387  N_array_3d *data = array;
388  RASTER3D_Region region;
389 
390  /*get the current region */
391  Rast3d_get_window(&region);
392 
393  cols = region.cols;
394  rows = region.rows;
395  depths = region.depths;
396  type = data->type;
397 
398  /*Check the array sizes */
399  if (data->cols != cols)
400  G_fatal_error("N_write_array_3d_to_rast3d: the data array size is "
401  "different from the current region settings");
402  if (data->rows != rows)
403  G_fatal_error("N_write_array_3d_to_rast3d: the data array size is "
404  "different from the current region settings");
405  if (data->depths != depths)
406  G_fatal_error("N_write_array_3d_to_rast3d: the data array size is "
407  "different from the current region settings");
408 
409  /*Open the new map */
410  if (type == DCELL_TYPE)
412  &region, DCELL_TYPE, 32);
413  else if (type == FCELL_TYPE)
415  &region, FCELL_TYPE, 32);
416 
417  if (map == NULL)
418  Rast3d_fatal_error(_("Error opening g3d map <%s>"), name);
419 
420  G_message(_("Write 3d array to g3d map <%s>"), name);
421 
422  /*if requested set the Mask on */
423  if (mask) {
424  if (Rast3d_mask_file_exists()) {
425  changemask = 0;
426  if (Rast3d_mask_is_off(map)) {
427  Rast3d_mask_on(map);
428  changemask = 1;
429  }
430  }
431  }
432 
433  for (z = 0; z < depths; z++) { /*From the bottom to the top */
434  G_percent(z, depths - 1, 10);
435  for (y = 0; y < rows; y++) {
436  for (x = 0; x < cols; x++) {
437  if (type == FCELL_TYPE) {
438  f1 = N_get_array_3d_f_value(data, x, y, z);
439  Rast3d_put_float(map, x, y, z, f1);
440  }
441  else if (type == DCELL_TYPE) {
442  d1 = N_get_array_3d_d_value(data, x, y, z);
443  Rast3d_put_double(map, x, y, z, d1);
444  }
445  }
446  }
447  }
448 
449  /*We set the Mask off, if it was off before */
450  if (mask) {
452  if (Rast3d_mask_is_on(map) && changemask)
453  Rast3d_mask_off(map);
454  }
455 
456  /* Flush all tile */
457  if (!Rast3d_flush_all_tiles(map))
458  Rast3d_fatal_error("Error flushing tiles with Rast3d_flush_all_tiles");
459  /* Close files and exit */
460  if (!Rast3d_close(map))
461  Rast3d_fatal_error(_("Error closing g3d file <%s>"), name);
462 
463  return;
464 }
#define NULL
Definition: ccmath.h:32
void G_percent(long, long, int)
Print percent complete messages.
Definition: percent.c:61
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_get_set_window(struct Cell_head *)
Get the current working window (region)
const char * G_find_raster3d(const char *, const char *)
Search for a 3D raster map in current search path or in a specified mapset.
Definition: find_rast3d.c:28
#define G_incr_void_ptr(ptr, size)
Definition: defs/gis.h:81
void G_message(const char *,...) __attribute__((format(printf
void Rast3d_get_value(RASTER3D_Map *, int, int, int, void *, int)
Returns in *value the resampled cell-value of the cell with window-coordinate (x, y,...
Definition: getvalue.c:22
int Rast3d_flush_all_tiles(RASTER3D_Map *)
Definition: cache.c:283
int Rast3d_mask_is_off(RASTER3D_Map *)
Returns 1 if the mask for map is turned off. Returns 0 otherwise.
Definition: mask.c:374
int Rast3d_put_float(RASTER3D_Map *, int, int, int, float)
Is equivalent to Rast3d_put_value (map, x, y, z, &value, FCELL_TYPE).
Definition: putvalue.c:18
int Rast3d_tile_type_map(RASTER3D_Map *)
Returns the type in which tiles of map are stored in memory.
Definition: headerinfo.c:156
void * Rast3d_open_cell_old(const char *, const char *, RASTER3D_Region *, int, int)
Opens existing g3d-file name in mapset. Tiles are stored in memory with type which must be any of FCE...
Definition: raster3d/open.c:80
void Rast3d_mask_off(RASTER3D_Map *)
Turns off the mask for map. This is the default. Do not invoke this function after the first tile has...
Definition: mask.c:345
int Rast3d_mask_file_exists(void)
Returns 1 if the 3d mask file exists.
Definition: mask.c:64
void Rast3d_mask_on(RASTER3D_Map *)
Turns on the mask for map. Do not invoke this function after the first tile has been read since the r...
Definition: mask.c:329
void * Rast3d_open_new_opt_tile_size(const char *, int, RASTER3D_Region *, int, int)
Opens new g3d-file with name in the current mapset. This method tries to compute optimal tile size ba...
Definition: open2.c:94
int Rast3d_put_double(RASTER3D_Map *, int, int, int, double)
Is equivalent to Rast3d_put_value (map, x, y, z, &value, DCELL_TYPE).
Definition: putvalue.c:53
void Rast3d_get_window(RASTER3D_Region *)
Stores the current default window in window.
void Rast3d_fatal_error(const char *,...) __attribute__((format(printf
int Rast3d_close(RASTER3D_Map *)
Close 3D raster map files.
int Rast3d_mask_is_on(RASTER3D_Map *)
Returns 1 if the mask for map is turned on. Returns 0 otherwise.
Definition: mask.c:360
void * Rast_allocate_buf(RASTER_MAP_TYPE)
Allocate memory for a raster map of given type.
Definition: alloc_cell.c:54
#define Rast_is_f_null_value(fcellVal)
Definition: defs/raster.h:406
void Rast_close(int)
Close a raster map.
Definition: raster/close.c:99
int Rast_open_old(const char *, const char *)
Open an existing integer raster map (cell)
Definition: raster/open.c:112
void Rast_put_f_row(int, const FCELL *)
Writes the next row for fcell file (FCELL version)
int Rast_open_new(const char *, RASTER_MAP_TYPE)
Opens a new raster map.
Definition: raster/open.c:1013
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition: alloc_cell.c:38
void Rast_put_d_row(int, const DCELL *)
Writes the next row for dcell file (DCELL version)
void Rast_put_c_row(int, const CELL *)
Writes the next row for cell file (CELL version)
#define Rast_is_d_null_value(dcellVal)
Definition: defs/raster.h:408
#define Rast_is_c_null_value(cellVal)
Definition: defs/raster.h:404
RASTER_MAP_TYPE Rast_get_map_type(int)
Determine raster type from descriptor.
Definition: raster/open.c:932
void Rast_get_row(int, void *, int, RASTER_MAP_TYPE)
Get raster row.
float FCELL
Definition: gis.h:630
double DCELL
Definition: gis.h:629
int CELL
Definition: gis.h:628
#define _(str)
Definition: glocale.h:10
FCELL N_get_array_2d_f_value(N_array_2d *data, int col, int row)
Returns the value of type FCELL at position col, row.
Definition: n_arrays.c:347
void N_put_array_3d_value_null(N_array_3d *data, int col, int row, int depth)
This function writes a null value to the N_array_3d data at position col, row, depth.
Definition: n_arrays.c:1060
CELL N_get_array_2d_c_value(N_array_2d *data, int col, int row)
Returns the value of type CELL at position col, row.
Definition: n_arrays.c:314
void N_put_array_2d_f_value(N_array_2d *data, int col, int row, FCELL value)
Writes a FCELL value to the N_array_2d struct at position col, row.
Definition: n_arrays.c:546
float N_get_array_3d_f_value(N_array_3d *data, int col, int row, int depth)
This function returns the value of type float at position col, row, depth.
Definition: n_arrays.c:948
void N_put_array_3d_f_value(N_array_3d *data, int col, int row, int depth, float value)
This function writes a float value to the N_array_3d data at position col, row, depth.
Definition: n_arrays.c:1121
DCELL N_get_array_2d_d_value(N_array_2d *data, int col, int row)
Returns the value of type DCELL at position col, row.
Definition: n_arrays.c:380
N_array_3d * N_alloc_array_3d(int cols, int rows, int depths, int offset, int type)
Allocate memory for a N_array_3d data structure.
Definition: n_arrays.c:719
N_array_2d * N_alloc_array_2d(int cols, int rows, int offset, int type)
Allocate memory for a N_array_2d data structure.
Definition: n_arrays.c:75
void N_put_array_3d_d_value(N_array_3d *data, int col, int row, int depth, double value)
Writes a double value to the N_array_3d struct at position col, row, depth.
Definition: n_arrays.c:1148
double N_get_array_3d_d_value(N_array_3d *data, int col, int row, int depth)
This function returns the value of type float at position col, row, depth.
Definition: n_arrays.c:979
void N_put_array_2d_value_null(N_array_2d *data, int col, int row)
Writes the null value to the N_array_2d struct at position col, row.
Definition: n_arrays.c:459
void N_put_array_2d_c_value(N_array_2d *data, int col, int row, CELL value)
Writes a CELL value to the N_array_2d struct at position col, row.
Definition: n_arrays.c:516
void N_put_array_2d_d_value(N_array_2d *data, int col, int row, DCELL value)
Writes a DCELL value to the N_array_2d struct at position col, row.
Definition: n_arrays.c:576
void N_write_array_3d_to_rast3d(N_array_3d *array, char *name, int mask)
Write a N_array_3d struct to a volume map.
Definition: n_arrays_io.c:381
N_array_3d * N_read_rast3d_to_array_3d(char *name, N_array_3d *array, int mask)
Read a volume map into a N_array_3d structure.
Definition: n_arrays_io.c:253
N_array_2d * N_read_rast_to_array_2d(char *name, N_array_2d *array)
Read a raster map into a N_array_2d structure.
Definition: n_arrays_io.c:44
void N_write_array_2d_to_rast(N_array_2d *array, char *name)
Write a N_array_2d struct to a raster map.
Definition: n_arrays_io.c:172
const char * name
Definition: named_colr.c:6
#define RASTER3D_DEFAULT_WINDOW
Definition: raster3d.h:29
#define RASTER3D_USE_CACHE_DEFAULT
Definition: raster3d.h:19
#define RASTER3D_TILE_SAME_AS_FILE
Definition: raster3d.h:11
#define RASTER3D_USE_CACHE_XY
Definition: raster3d.h:23
#define FCELL_TYPE
Definition: raster.h:12
#define DCELL_TYPE
Definition: raster.h:13
#define CELL_TYPE
Definition: raster.h:11
2D/3D raster map header (used also for region)
Definition: gis.h:440
int depths
number of depths for 3D data
Definition: gis.h:463
int rows
Number of rows for 2D data.
Definition: gis.h:455
int cols
Number of columns for 2D data.
Definition: gis.h:459
int type
Definition: N_pde.h:133
int type
Definition: N_pde.h:176
int rows
Definition: N_pde.h:177
int depths
Definition: N_pde.h:177
int cols
Definition: N_pde.h:177
#define x