tilemath.c 9.4 KB

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