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