GRASS 8 Programmer's Manual 8.6.0dev(2026)-55de52a352
Loading...
Searching...
No Matches
vrt.c
Go to the documentation of this file.
1/*!
2 \file lib/raster/vrt.c
3
4 \brief Raster Library - virtual GRASS raster maps.
5
6 SPDX-FileCopyrightText: 2010 GRASS Development Team
7 SPDX-License-Identifier: GPL-2.0-or-later
8
9 \author Markus Metz
10 */
11
12#include <grass/gis.h>
13#include <grass/raster.h>
14#include <grass/gprojects.h>
15#include <grass/glocale.h>
16
17#include "R.h"
18
19static int cmp_wnd(const void *a, const void *b)
20{
21 struct Cell_head *cellhda = &((struct tileinfo *)a)->cellhd;
22 struct Cell_head *cellhdb = &((struct tileinfo *)b)->cellhd;
23
24 /* sort from descending N to S, then ascending from W to E */
25 if (cellhda->south > cellhdb->south)
26 return -1;
27 if (cellhda->south < cellhdb->south)
28 return 1;
29 if (cellhda->north > cellhdb->north)
30 return -1;
31 if (cellhda->north < cellhdb->north)
32 return 1;
33 if (cellhda->west < cellhdb->west)
34 return -1;
35 if (cellhda->west > cellhdb->west)
36 return 1;
37 if (cellhda->east < cellhdb->east)
38 return -1;
39 if (cellhda->east > cellhdb->east)
40 return 1;
41
42 return 0;
43}
44
45struct R_vrt *Rast_get_vrt(const char *vname, const char *vmapset)
46{
47 FILE *fp;
48 int talloc, tilecount;
49 struct tileinfo *ti;
50 struct R_vrt *vrt;
51 struct Cell_head *rd_window = &R__.rd_window;
52 struct ilist *tlist;
53
54 tilecount = 0;
55 ti = NULL;
56
58 return NULL;
59
60 fp = G_fopen_old_misc("cell_misc", "vrt", vname, vmapset);
61 if (!fp)
62 return NULL;
63
64 tlist = G_new_ilist();
65 talloc = 0;
66 while (1) {
67 char buf[GNAME_MAX];
68 char *name;
69 const char *mapset;
70 struct tileinfo *p;
71
72 if (!G_getl2(buf, sizeof(buf), fp))
73 break;
74
75 /* Ignore empty lines */
76 if (!*buf)
77 continue;
78
79 name = buf;
80 if ((mapset = G_find_raster(name, "")) == NULL)
81 G_fatal_error(_("Tile raster map <%s> not found"), name);
82
83 if (strcmp(name, vname) == 0)
84 G_fatal_error(_("A virtual raster can not contain itself"));
85
86 if (tilecount >= talloc) {
87 talloc += 100;
88 ti = G_realloc(ti, talloc * sizeof(struct tileinfo));
89 }
90 p = &ti[tilecount];
91
92 p->name = G_store(name);
93 p->mapset = G_store(mapset);
94 Rast_get_cellhd(p->name, p->mapset, &(p->cellhd));
95 p->clist = NULL;
96
97 if (rd_window->proj == PROJECTION_LL) {
98 while (p->cellhd.west >= rd_window->east) {
99 p->cellhd.west -= 360.0;
100 p->cellhd.east -= 360.0;
101 }
102 while (p->cellhd.east <= rd_window->west) {
103 p->cellhd.west += 360.0;
104 p->cellhd.east += 360.0;
105 }
106 }
107
108 if (p->cellhd.north > rd_window->south &&
109 p->cellhd.south <= rd_window->north &&
110 p->cellhd.west < rd_window->east &&
111 p->cellhd.east >= rd_window->west) {
112
113 int col;
114 double east;
115
116 G_ilist_add(tlist, tilecount);
117
118 p->clist = G_new_ilist();
119 for (col = 0; col < rd_window->cols; col++) {
120 east = rd_window->west + rd_window->ew_res * (col + 0.5);
121
122 if (rd_window->proj == PROJECTION_LL) {
123 while (east > p->cellhd.east)
124 east -= 360.0;
125 while (east < p->cellhd.west)
126 east += 360.0;
127 }
128 if (east >= p->cellhd.west && east < p->cellhd.east)
129 G_ilist_add(p->clist, col);
130 }
131 }
132 tilecount++;
133 }
134
135 if (tilecount > 1)
136 qsort(ti, tilecount, sizeof(struct tileinfo), cmp_wnd);
137
138 fclose(fp);
139
140 vrt = G_calloc(1, sizeof(struct R_vrt));
141 vrt->tilecount = tilecount;
142 vrt->tileinfo = ti;
143 vrt->tlist = tlist;
144
145 return vrt;
146}
147
148void Rast_close_vrt(struct R_vrt *vrt)
149{
150 int i;
151
152 for (i = 0; i < vrt->tilecount; i++) {
153 struct tileinfo *p;
154
155 p = &(vrt->tileinfo[i]);
156
157 G_free(p->name);
158 G_free(p->mapset);
159 if (p->clist)
161 }
162 G_free(vrt->tileinfo);
163 G_free_ilist(vrt->tlist);
164 G_free(vrt);
165}
166
167/* must only be called by get_map_row_nomask()
168 * move to get_row.c as read_data_vrt() ? */
169int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
170{
171 struct R_vrt *vrt;
172 struct tileinfo *ti;
173 struct Cell_head *rd_window = &R__.rd_window;
174 double rown, rows;
175 int i, j;
176 int have_tile;
177 void *tmpbuf;
178 size_t size = Rast_cell_size(data_type);
179
180 // R__.fileinfo can be reallocated by concurrent open/close calls,
181 // so we extract the vrt pointer under the same lock that protects the I/O
182 // below. This expects callers to open the raster once per thread before
183 // entering any parallel code.
184#pragma omp critical(raster_vrt_read)
185 {
186 vrt = R__.fileinfo[fd].vrt;
187 }
188 ti = vrt->tileinfo;
189
190 rown = rd_window->north - rd_window->ns_res * row;
191 rows = rd_window->north - rd_window->ns_res * (row + 1);
192
193 Rast_set_null_value(buf, rd_window->cols, data_type);
194 tmpbuf = Rast_allocate_input_buf(data_type);
195 have_tile = 0;
196
197 /* parallelised reading of the real raster maps
198 * constituting a GRASS virtual raster
199 * causes IO read errors and segmentation faults:
200 * enforce reading of the different rasters in only one thread
201 * Serialize the entire open/read/close cycle for each tile
202 * because they all access the non-thread-safe global R__.fileinfo array. */
203#pragma omp critical(raster_vrt_read)
204 for (i = 0; i < vrt->tlist->n_values; i++) {
205 struct tileinfo *p = &ti[vrt->tlist->value[i]];
206
207 /* open the tile only if it overlaps with the current reading
208 * row and the current reading EW extents */
209 if (p->cellhd.north > rows && p->cellhd.south <= rown &&
210 p->cellhd.west < rd_window->east &&
211 p->cellhd.east > rd_window->west) {
212 int tfd;
213 void *p1, *p2;
214
215 /* recurse into get_map_row(), collect data for all tiles
216 * a mask is applied to the collected data
217 * after this function returns */
218 Rast_set_null_value(tmpbuf, rd_window->cols, data_type);
219 /* avoid Rast__check_for_auto_masking() */
220 tfd = Rast__open_old(p->name, p->mapset);
221 Rast_get_row_nomask(tfd, tmpbuf, row, data_type);
223
224 /* restrict to start and end col ? */
225 for (j = 0; j < p->clist->n_values; j++) {
226 p1 = (unsigned char *)buf + size * p->clist->value[j];
227 p2 = (unsigned char *)tmpbuf + size * p->clist->value[j];
228
229 if (!Rast_is_null_value(p2, data_type)) {
230 memcpy(p1, p2, size);
231 }
232 }
233 have_tile = 1;
234 }
235 }
236 G_free(tmpbuf);
237
238 return have_tile;
239}
#define NULL
Definition ccmath.h:32
const char * G_find_raster(char *, const char *)
Find a raster map.
Definition find_rast.c:52
struct ilist * G_new_ilist(void)
Return a new integer list.
Definition ilist.c:40
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition getl.c:58
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_realloc(p, n)
Definition defs/gis.h:138
#define G_calloc(m, n)
Definition defs/gis.h:137
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_free_ilist(struct ilist *)
Free allocated memory of an integer list.
Definition ilist.c:24
FILE * G_fopen_old_misc(const char *, const char *, const char *, const char *)
open a database misc file for reading
Definition open_misc.c:210
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
void G_ilist_add(struct ilist *, int)
Add item to ilist.
Definition ilist.c:75
const char * G_find_raster2(const char *, const char *)
Find a raster map (look but don't touch)
Definition find_rast.c:73
int Rast_is_null_value(const void *, RASTER_MAP_TYPE)
To check if a raster value is set to NULL.
Definition null_val.c:174
void Rast_unopen(int)
Unopen a raster map.
void Rast_get_row_nomask(int, void *, int, RASTER_MAP_TYPE)
Read raster row without masking.
int Rast__open_old(const char *, const char *)
Lower level function, open cell files, supercell files, and the mask file.
size_t Rast_cell_size(RASTER_MAP_TYPE)
Returns size of a raster cell in bytes.
Definition alloc_cell.c:35
void Rast_set_null_value(void *, int, RASTER_MAP_TYPE)
To set one or more raster values to null.
Definition null_val.c:96
void Rast_get_cellhd(const char *, const char *, struct Cell_head *)
Read the raster header.
Definition get_cellhd.c:39
void * Rast_allocate_input_buf(RASTER_MAP_TYPE)
Definition alloc_cell.c:153
#define GNAME_MAX
Definition gis.h:193
#define PROJECTION_LL
Projection code - Latitude-Longitude.
Definition gis.h:126
#define _(str)
Definition glocale.h:10
const char * name
Definition named_colr.c:6
double b
Definition r_raster.c:37
int RASTER_MAP_TYPE
Definition raster.h:25
2D/3D raster map header (used also for region)
Definition gis.h:443
double ew_res
Resolution - east to west cell size for 2D data.
Definition gis.h:479
double north
Extent coordinates (north)
Definition gis.h:489
double east
Extent coordinates (east)
Definition gis.h:493
double ns_res
Resolution - north to south cell size for 2D data.
Definition gis.h:483
int rows
Number of rows for 2D data.
Definition gis.h:458
int cols
Number of columns for 2D data.
Definition gis.h:462
int proj
Projection code.
Definition gis.h:475
double south
Extent coordinates (south)
Definition gis.h:491
double west
Extent coordinates (west)
Definition gis.h:495
Definition R.h:82
struct fileinfo * fileinfo
Definition R.h:96
struct Cell_head rd_window
Definition R.h:92
Definition R.h:41
struct tileinfo * tileinfo
Definition R.h:43
struct ilist * tlist
Definition R.h:44
int tilecount
Definition R.h:42
List of integers.
Definition gis.h:712
Definition R.h:34
struct Cell_head cellhd
Definition R.h:37
char * name
Definition R.h:35
struct ilist * clist
Definition R.h:38
char * mapset
Definition R.h:36
void Rast_close_vrt(struct R_vrt *vrt)
Definition vrt.c:148
struct R_vrt * Rast_get_vrt(const char *vname, const char *vmapset)
Definition vrt.c:45
int Rast_get_vrt_row(int fd, void *buf, int row, RASTER_MAP_TYPE data_type)
Definition vrt.c:169