GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
tilemath.c
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include "raster3d_intern.h"
6 
7 /*---------------------------------------------------------------------------*/
8 
9 /*!
10  * \brief
11  *
12  * Converts index <em>tileIndex</em> into tile-coordinates
13  * <em>(xTile, yTile, zTile)</em>.
14  *
15  * \param map
16  * \param tileIndex
17  * \param xTile
18  * \param yTile
19  * \param zTile
20  * \return void
21  */
22 
23 void Rast3d_tile_index2tile(RASTER3D_Map *map, int tileIndex, int *xTile,
24  int *yTile, int *zTile)
25 {
26  int tileIndex2d;
27 
28  *zTile = tileIndex / map->nxy;
29  tileIndex2d = tileIndex % map->nxy;
30  *yTile = tileIndex2d / map->nx;
31  *xTile = tileIndex2d % map->nx;
32 }
33 
34 /*---------------------------------------------------------------------------*/
35 
36 /*!
37  * \brief
38  *
39  * Returns tile-index corresponding to tile-coordinates <em>(xTile,
40  * yTile, zTile)</em>.
41  *
42  * \param map
43  * \param xTile
44  * \param yTile
45  * \param zTile
46  * \return int
47  */
48 
49 int Rast3d_tile2tile_index(RASTER3D_Map *map, int xTile, int yTile, int zTile)
50 {
51  return map->nxy * zTile + map->nx * yTile + xTile;
52 }
53 
54 /*---------------------------------------------------------------------------*/
55 
56 /*!
57  * \brief
58  *
59  * Computes the cell-coordinates <em>(x, y, z)</em>
60  * which correspond to the origin of the tile with tile-coordinates <em>(xTile,
61  * yTile, zTile)</em>.
62  *
63  * \param map
64  * \param xTile
65  * \param yTile
66  * \param zTile
67  * \param x
68  * \param y
69  * \param z
70  * \return void
71  */
72 
73 void Rast3d_tile_coord_origin(RASTER3D_Map *map, int xTile, int yTile,
74  int zTile, int *x, int *y, int *z)
75 {
76  *x = map->tileX * xTile;
77  *y = map->tileY * yTile;
78  *z = map->tileZ * zTile;
79 }
80 
81 /*---------------------------------------------------------------------------*/
82 
83 /*!
84  * \brief
85  *
86  * Computes the cell-coordinates <em>(x, y, z)</em> which correspond to
87  * the origin of the tile with <em>tileIndex</em>.
88  *
89  * \param map
90  * \param tileIndex
91  * \param x
92  * \param y
93  * \param z
94  * \return void
95  */
96 
97 void Rast3d_tile_index_origin(RASTER3D_Map *map, int tileIndex, int *x, int *y,
98  int *z)
99 {
100  int xTile, yTile, zTile;
101 
102  Rast3d_tile_index2tile(map, tileIndex, &xTile, &yTile, &zTile);
103  Rast3d_tile_coord_origin(map, xTile, yTile, zTile, x, y, z);
104 }
105 
106 /*---------------------------------------------------------------------------*/
107 
108 /*!
109  * \brief
110  *
111  * Converts
112  * cell-coordinates <em>(x, y, z)</em> into tile-coordinates <em>(xTile, yTile,
113  * zTile)</em> and the coordinate of the cell <em>(xOffs, yOffs, zOffs)</em>
114  * within the tile.
115  *
116  * \param map
117  * \param x
118  * \param y
119  * \param z
120  * \param xTile
121  * \param yTile
122  * \param zTile
123  * \param xOffs
124  * \param yOffs
125  * \param zOffs
126  * \return void
127  */
128 
129 void Rast3d_coord2tile_coord(RASTER3D_Map *map, int x, int y, int z, int *xTile,
130  int *yTile, int *zTile, int *xOffs, int *yOffs,
131  int *zOffs)
132 {
133  *xTile = x / map->tileX;
134  *xOffs = x % map->tileX;
135  *yTile = y / map->tileY;
136  *yOffs = y % map->tileY;
137  *zTile = z / map->tileZ;
138  *zOffs = z % map->tileZ;
139 }
140 
141 /*---------------------------------------------------------------------------*/
142 
143 /*!
144  * \brief
145  *
146  * Converts cell-coordinates <em>(x, y, z)</em> into
147  * <em>tileIndex</em> and the <em>offset</em> of the cell within the tile.
148  *
149  * \param map
150  * \param x
151  * \param y
152  * \param z
153  * \param tileIndex
154  * \param offset
155  * \return void
156  */
157 
158 void Rast3d_coord2tile_index(RASTER3D_Map *map, int x, int y, int z,
159  int *tileIndex, int *offset)
160 {
161  int xTile, yTile, zTile, xOffs, yOffs, zOffs;
162 
163  Rast3d_coord2tile_coord(map, x, y, z, &xTile, &yTile, &zTile, &xOffs,
164  &yOffs, &zOffs);
165  *tileIndex = Rast3d_tile2tile_index(map, xTile, yTile, zTile);
166  *offset = zOffs * map->tileXY + yOffs * map->tileX + xOffs;
167 }
168 
169 /*---------------------------------------------------------------------------*/
170 
171 /*!
172  * \brief
173  *
174  * Returns 1 if
175  * cell-coordinate <em>(x, y, z)</em> is a coordinate inside the region. Returns
176  * 0 otherwise.
177  *
178  * \param map
179  * \param x
180  * \param y
181  * \param z
182  * \return int
183  */
184 
185 int Rast3d_coord_in_range(RASTER3D_Map *map, int x, int y, int z)
186 {
187  return (x >= 0) && (x < map->region.cols) && (y >= 0) &&
188  (y < map->region.rows) && (z >= 0) && (z < map->region.depths);
189 }
190 
191 /*---------------------------------------------------------------------------*/
192 
193 /*!
194  * \brief
195  *
196  * Returns 1 if <em>tileIndex</em> is a valid index for <em>map</em>.
197  * Returns 0 otherwise.
198  *
199  * \param map
200  * \param tileIndex
201  * \return int
202  */
203 
204 int Rast3d_tile_index_in_range(RASTER3D_Map *map, int tileIndex)
205 {
206  return (tileIndex < map->nTiles) && (tileIndex >= 0);
207 }
208 
209 /*---------------------------------------------------------------------------*/
210 
211 /*!
212  * \brief
213  *
214  * Returns 1 if
215  * tile-coordinate <em>(x, y, z)</em> is a coordinate inside tile cube. Returns
216  * 0 otherwise.
217  *
218  * \param map
219  * \param x
220  * \param y
221  * \param z
222  * \return int
223  */
224 
225 int Rast3d_tile_in_range(RASTER3D_Map *map, int x, int y, int z)
226 {
227  return (x >= 0) && (x < map->nx) && (y >= 0) && (y < map->ny) && (z >= 0) &&
228  (z < map->nz);
229 }
230 
231 /*---------------------------------------------------------------------------*/
232 
233 /*!
234  * \brief
235  *
236  * Computes the dimensions of the tile when clipped to fit the
237  * region of <em>map</em>. The clipped dimensions are returned in <em>rows</em>,
238  * <em>cols</em>, <em>depths</em>. The complement is returned in
239  * <em>xRedundant</em>, <em>yRedundant</em>, and <em>zRedundant</em>. This
240  * function returns the number of cells in the clipped tile.
241  *
242  * \param map
243  * \param tileIndex
244  * \param rows
245  * \param cols
246  * \param depths
247  * \param xRedundant
248  * \param yRedundant
249  * \param zRedundant
250  * \return int
251  */
252 
254  int *rows, int *cols, int *depths,
255  int *xRedundant, int *yRedundant,
256  int *zRedundant)
257 {
258  int x, y, z;
259 
260  Rast3d_tile_index2tile(map, tileIndex, &x, &y, &z);
261 
262  if ((x != map->clipX) && (y != map->clipY) && (z != map->clipZ)) {
263  return map->tileSize;
264  }
265 
266  if (x != map->clipX) {
267  *cols = map->tileX;
268  *xRedundant = 0;
269  }
270  else {
271  *cols = (map->region.cols - 1) % map->tileX + 1;
272  *xRedundant = map->tileX - *cols;
273  }
274  if (y != map->clipY) {
275  *rows = map->tileY;
276  *yRedundant = 0;
277  }
278  else {
279  *rows = (map->region.rows - 1) % map->tileY + 1;
280  *yRedundant = map->tileY - *rows;
281  }
282  if (z != map->clipZ) {
283  *depths = map->tileZ;
284  *zRedundant = 0;
285  }
286  else {
287  *depths = (map->region.depths - 1) % map->tileZ + 1;
288  *zRedundant = map->tileZ - *depths;
289  }
290 
291  /* printf ("%d (%d %d %d): (%d %d) (%d %d) (%d %d), %d\n", */
292  /* tileIndex, x, y, z, *rows, *xRedundant, *cols, *yRedundant, */
293  /* *depths, *zRedundant, *depths * *cols * *rows); */
294 
295  return *depths * *cols * *rows;
296 }
297 
298 /*---------------------------------------------------------------------------*/
299 
300 /*!
301  * \brief Compute the optimal tile size.
302  *
303  * This function computes tile sizes with an optimal ratio between tile
304  * dimensions and minimized border tile overlapping. Large dimensions (in most
305  * cases x and y) will be reduced more often than small dimensions to fit the
306  * maxSize criteria.
307  *
308  * \param region The region of the map
309  * \param type The type of the map (FCELL_TYPE or DCELL_TYPE)
310  * \param tileX Pointer of the tile size in x direction for result storage
311  * \param tileY Pointer of the tile size in y direction for result storage
312  * \param tileZ Pointer of the tile size in z direction for result storage
313  * \param maxSize The max size of the tile in kilo bytes
314  * \return void
315  */
316 
318  int *tileX, int *tileY, int *tileZ,
319  int maxSize)
320 {
321  unsigned long size = 0;
322  unsigned long x, y, z;
323  unsigned long i = 0;
324  unsigned long tileSize;
325  unsigned long divx = 2;
326  unsigned long divy = 2;
327  unsigned long divz = 2;
328 
329  if (type == FCELL_TYPE)
330  size = sizeof(FCELL);
331 
332  if (type == DCELL_TYPE)
333  size = sizeof(DCELL);
334 
335  x = region->cols;
336  y = region->rows;
337  z = region->depths;
338 
339  while (1) {
340  tileSize = size * x * y * z;
341 
342  G_debug(2,
343  "Rast3d_compute_optimal_tile_dimension: tilesize %li x %li y "
344  "%li z %li\n",
345  tileSize, x, y, z);
346 
347  if (maxSize < 0 || tileSize <= (unsigned int)maxSize * 1024)
348  break;
349 
350  /* Compute weighted tile sizes. Take care that the tile size is computed
351  based on the dimension ratio and reduce the border tile overlapping.
352  In case one dimension is much larger than the other, reduce
353  the large dimension by a factor till the maxSize is reached or till
354  the the other dimensions are only by factor 2 smaller. */
355  if ((y / x) <= 2 && (z / x) <= 2) {
356  if (region->cols % divx != 0)
357  x = region->cols / divx + 1;
358  else
359  x = region->cols / divx;
360  divx += 1;
361  }
362  if ((x / y) <= 2 && (z / y) <= 2) {
363  if (region->rows % divy != 0)
364  y = region->rows / divy + 1;
365  else
366  y = region->rows / divy;
367  divy += 1;
368  }
369  if ((x / z) <= 2 && (y / z) <= 2) {
370  if (region->depths % divz != 0)
371  z = region->depths / divz + 1;
372  else
373  z = region->depths / divz;
374  divz += 1;
375  }
376 
377  /* Avoid infinite loop */
378  i++;
379  if (i > 10000)
380  break;
381  }
382 
383  *tileX = (int)x;
384  *tileY = (int)y;
385  *tileZ = (int)z;
386 }
int G_debug(int, const char *,...) __attribute__((format(printf
float FCELL
Definition: gis.h:630
double DCELL
Definition: gis.h:629
#define FCELL_TYPE
Definition: raster.h:12
#define DCELL_TYPE
Definition: raster.h:13
RASTER3D_Region region
Definition: raster3d.h:82
int tileSize
Definition: raster3d.h:180
int Rast3d_tile_in_range(RASTER3D_Map *map, int x, int y, int z)
Returns 1 if tile-coordinate (x, y, z) is a coordinate inside tile cube. Returns 0 otherwise.
Definition: tilemath.c:225
void Rast3d_tile_coord_origin(RASTER3D_Map *map, int xTile, int yTile, int zTile, int *x, int *y, int *z)
Computes the cell-coordinates (x, y, z) which correspond to the origin of the tile with tile-coordina...
Definition: tilemath.c:73
int Rast3d_tile2tile_index(RASTER3D_Map *map, int xTile, int yTile, int zTile)
Returns tile-index corresponding to tile-coordinates (xTile, yTile, zTile).
Definition: tilemath.c:49
void Rast3d_tile_index_origin(RASTER3D_Map *map, int tileIndex, int *x, int *y, int *z)
Computes the cell-coordinates (x, y, z) which correspond to the origin of the tile with tileIndex.
Definition: tilemath.c:97
void Rast3d_tile_index2tile(RASTER3D_Map *map, int tileIndex, int *xTile, int *yTile, int *zTile)
Converts index tileIndex into tile-coordinates (xTile, yTile, zTile).
Definition: tilemath.c:23
void Rast3d_coord2tile_index(RASTER3D_Map *map, int x, int y, int z, int *tileIndex, int *offset)
Converts cell-coordinates (x, y, z) into tileIndex and the offset of the cell within the tile.
Definition: tilemath.c:158
int Rast3d_tile_index_in_range(RASTER3D_Map *map, int tileIndex)
Returns 1 if tileIndex is a valid index for map. Returns 0 otherwise.
Definition: tilemath.c:204
int Rast3d_compute_clipped_tile_dimensions(RASTER3D_Map *map, int tileIndex, int *rows, int *cols, int *depths, int *xRedundant, int *yRedundant, int *zRedundant)
Computes the dimensions of the tile when clipped to fit the region of map. The clipped dimensions are...
Definition: tilemath.c:253
void Rast3d_compute_optimal_tile_dimension(RASTER3D_Region *region, int type, int *tileX, int *tileY, int *tileZ, int maxSize)
Compute the optimal tile size.
Definition: tilemath.c:317
void Rast3d_coord2tile_coord(RASTER3D_Map *map, int x, int y, int z, int *xTile, int *yTile, int *zTile, int *xOffs, int *yOffs, int *zOffs)
Converts cell-coordinates (x, y, z) into tile-coordinates (xTile, yTile, zTile) and the coordinate of...
Definition: tilemath.c:129
int Rast3d_coord_in_range(RASTER3D_Map *map, int x, int y, int z)
Returns 1 if cell-coordinate (x, y, z) is a coordinate inside the region. Returns 0 otherwise.
Definition: tilemath.c:185
#define x