sample.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*!
  2. \file lib/raster/sample.c
  3. \brief Raster library - Sampling methods (extract a cell value from
  4. raster map)
  5. 1/2006: moved to libgis from v.sample/v.drape for clone removal
  6. (C) 2001-2009 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. \author James Darrell McCauley <darrell mccauley-usa.com>, http://mccauley-usa.com/
  10. */
  11. #include <string.h>
  12. #include <unistd.h>
  13. #include <math.h>
  14. #include <grass/gis.h>
  15. #include <grass/raster.h>
  16. #include <grass/glocale.h>
  17. /* prototypes */
  18. static double scancatlabel(const char *);
  19. /*!
  20. * \brief Extract a cell value from raster map.
  21. *
  22. * Extract a cell value from raster map at given northing and easting
  23. * with a sampled 3x3 window using a specified interpolation method.
  24. *
  25. * - NEAREST neighbor interpolation
  26. * - BILINEAR bilinear interpolation
  27. * - CUBIC cubic interpolation
  28. *
  29. * \param fd file descriptor
  30. * \param window region settings
  31. * \param cats categories
  32. * \param north northing position
  33. * \param east easting position
  34. * \param usedesc flag to scan category label
  35. * \param itype interpolation method
  36. *
  37. * \return cell value at given position
  38. */
  39. DCELL Rast_get_sample(int fd,
  40. const struct Cell_head *window,
  41. struct Categories *cats,
  42. double north, double east,
  43. int usedesc, INTERP_TYPE itype)
  44. {
  45. double retval;
  46. switch (itype) {
  47. case INTERP_NEAREST:
  48. retval =
  49. Rast_get_sample_nearest(fd, window, cats, north, east, usedesc);
  50. break;
  51. case INTERP_BILINEAR:
  52. retval =
  53. Rast_get_sample_bilinear(fd, window, cats, north, east, usedesc);
  54. break;
  55. case INTERP_BICUBIC:
  56. retval =
  57. Rast_get_sample_cubic(fd, window, cats, north, east, usedesc);
  58. break;
  59. default:
  60. G_fatal_error("Rast_get_sample: %s", _("Unknown interpolation type"));
  61. }
  62. return retval;
  63. }
  64. /*!
  65. * \brief Extract a cell value from raster map (neighbor interpolation)
  66. *
  67. * Extract a cell value from raster map at given northing and easting
  68. * with a sampled 3x3 window using a neighbor interpolation.
  69. *
  70. * \param fd file descriptor
  71. * \param window region settings
  72. * \param cats categories
  73. * \param north northing position
  74. * \param east easting position
  75. * \param usedesc flag to scan category label
  76. *
  77. * \return cell value at given position
  78. */
  79. DCELL Rast_get_sample_nearest(int fd,
  80. const struct Cell_head * window,
  81. struct Categories * cats,
  82. double north, double east, int usedesc)
  83. {
  84. int row, col;
  85. DCELL result;
  86. DCELL *maprow = Rast_allocate_d_buf();
  87. /* convert northing and easting to row and col, resp */
  88. row = (int)floor(Rast_northing_to_row(north, window));
  89. col = (int)floor(Rast_easting_to_col(east, window));
  90. if (row < 0 || row >= Rast_window_rows() ||
  91. col < 0 || col >= Rast_window_cols()) {
  92. Rast_set_d_null_value(&result, 1);
  93. goto done;
  94. }
  95. Rast_get_d_row(fd, maprow, row);
  96. if (Rast_is_d_null_value(&maprow[col])) {
  97. Rast_set_d_null_value(&result, 1);
  98. goto done;
  99. }
  100. if (usedesc) {
  101. char *buf = Rast_get_c_cat((CELL *) & (maprow[col]), cats);
  102. G_squeeze(buf);
  103. result = scancatlabel(buf);
  104. }
  105. else
  106. result = maprow[col];
  107. done:
  108. G_free(maprow);
  109. return result;
  110. }
  111. /*!
  112. * \brief Extract a cell value from raster map (bilinear interpolation).
  113. *
  114. * Extract a cell value from raster map at given northing and easting
  115. * with a sampled 3x3 window using a bilinear interpolation.
  116. *
  117. * \param fd file descriptor
  118. * \param window region settings
  119. * \param cats categories
  120. * \param north northing position
  121. * \param east easting position
  122. * \param usedesc flag to scan category label
  123. *
  124. * \return cell value at given position
  125. */
  126. DCELL Rast_get_sample_bilinear(int fd,
  127. const struct Cell_head * window,
  128. struct Categories * cats,
  129. double north, double east, int usedesc)
  130. {
  131. int row, col;
  132. double grid[2][2];
  133. DCELL *arow = Rast_allocate_d_buf();
  134. DCELL *brow = Rast_allocate_d_buf();
  135. double frow, fcol, trow, tcol;
  136. DCELL result;
  137. frow = Rast_northing_to_row(north, window);
  138. fcol = Rast_easting_to_col(east, window);
  139. /* convert northing and easting to row and col, resp */
  140. row = (int)floor(frow - 0.5);
  141. col = (int)floor(fcol - 0.5);
  142. trow = frow - row - 0.5;
  143. tcol = fcol - col - 0.5;
  144. if (row < 0 || row + 1 >= Rast_window_rows() ||
  145. col < 0 || col + 1 >= Rast_window_cols()) {
  146. Rast_set_d_null_value(&result, 1);
  147. goto done;
  148. }
  149. Rast_get_d_row(fd, arow, row);
  150. Rast_get_d_row(fd, brow, row + 1);
  151. if (Rast_is_d_null_value(&arow[col]) ||
  152. Rast_is_d_null_value(&arow[col + 1]) ||
  153. Rast_is_d_null_value(&brow[col]) ||
  154. Rast_is_d_null_value(&brow[col + 1])) {
  155. Rast_set_d_null_value(&result, 1);
  156. goto done;
  157. }
  158. /*-
  159. * now were ready to do bilinear interpolation over
  160. * arow[col], arow[col+1],
  161. * brow[col], brow[col+1]
  162. */
  163. if (usedesc) {
  164. char *buf;
  165. G_squeeze(buf = Rast_get_c_cat((int *)&(arow[col]), cats));
  166. grid[0][0] = scancatlabel(buf);
  167. G_squeeze(buf = Rast_get_c_cat((CELL *) & (arow[col + 1]), cats));
  168. grid[0][1] = scancatlabel(buf);
  169. G_squeeze(buf = Rast_get_c_cat((CELL *) & (brow[col]), cats));
  170. grid[1][0] = scancatlabel(buf);
  171. G_squeeze(buf = Rast_get_c_cat((CELL *) & (brow[col + 1]), cats));
  172. grid[1][1] = scancatlabel(buf);
  173. }
  174. else {
  175. grid[0][0] = arow[col];
  176. grid[0][1] = arow[col + 1];
  177. grid[1][0] = brow[col];
  178. grid[1][1] = brow[col + 1];
  179. }
  180. result = Rast_interp_bilinear(tcol, trow,
  181. grid[0][0], grid[0][1], grid[1][0],
  182. grid[1][1]);
  183. done:
  184. G_free(arow);
  185. G_free(brow);
  186. return result;
  187. }
  188. /*!
  189. * \brief Extract a cell value from raster map (cubic interpolation).
  190. *
  191. * Extract a cell value from raster map at given northing and easting
  192. * with a sampled 3x3 window using a cubic interpolation.
  193. *
  194. * \param fd file descriptor
  195. * \param window region settings
  196. * \param cats categories
  197. * \param north northing position
  198. * \param east easting position
  199. * \param usedesc flag to scan category label
  200. *
  201. * \return cell value at given position
  202. */
  203. DCELL Rast_get_sample_cubic(int fd,
  204. const struct Cell_head * window,
  205. struct Categories * cats,
  206. double north, double east, int usedesc)
  207. {
  208. int i, j, row, col;
  209. double grid[4][4];
  210. DCELL *rows[4];
  211. double frow, fcol, trow, tcol;
  212. DCELL result;
  213. for (i = 0; i < 4; i++)
  214. rows[i] = Rast_allocate_d_buf();
  215. frow = Rast_northing_to_row(north, window);
  216. fcol = Rast_easting_to_col(east, window);
  217. /* convert northing and easting to row and col, resp */
  218. row = (int)floor(frow - 1.5);
  219. col = (int)floor(fcol - 1.5);
  220. trow = frow - row - 1.5;
  221. tcol = fcol - col - 1.5;
  222. if (row < 0 || row + 3 >= Rast_window_rows() ||
  223. col < 0 || col + 3 >= Rast_window_cols()) {
  224. Rast_set_d_null_value(&result, 1);
  225. goto done;
  226. }
  227. for (i = 0; i < 4; i++)
  228. Rast_get_d_row(fd, rows[i], row + i);
  229. for (i = 0; i < 4; i++)
  230. for (j = 0; j < 4; j++)
  231. if (Rast_is_d_null_value(&rows[i][col + j])) {
  232. Rast_set_d_null_value(&result, 1);
  233. goto done;
  234. }
  235. /*
  236. * now were ready to do cubic interpolation over
  237. * arow[col], arow[col+1], arow[col+2], arow[col+3],
  238. * brow[col], brow[col+1], brow[col+2], brow[col+3],
  239. * crow[col], crow[col+1], crow[col+2], crow[col+3],
  240. * drow[col], drow[col+1], drow[col+2], drow[col+3],
  241. */
  242. if (usedesc) {
  243. char *buf;
  244. for (i = 0; i < 4; i++) {
  245. for (j = 0; j < 4; j++) {
  246. G_squeeze(buf =
  247. Rast_get_c_cat((CELL *) & (rows[i][col + j]),
  248. cats));
  249. grid[i][j] = scancatlabel(buf);
  250. }
  251. }
  252. }
  253. else {
  254. for (i = 0; i < 4; i++)
  255. for (j = 0; j < 4; j++)
  256. grid[i][j] = rows[i][col + j];
  257. }
  258. result = Rast_interp_bicubic(tcol, trow,
  259. grid[0][0], grid[0][1], grid[0][2],
  260. grid[0][3], grid[1][0], grid[1][1],
  261. grid[1][2], grid[1][3], grid[2][0],
  262. grid[2][1], grid[2][2], grid[2][3],
  263. grid[3][0], grid[3][1], grid[3][2],
  264. grid[3][3]);
  265. done:
  266. for (i = 0; i < 4; i++)
  267. G_free(rows[i]);
  268. return result;
  269. }
  270. static double scancatlabel(const char *str)
  271. {
  272. double val;
  273. if (strcmp(str, "no data") != 0)
  274. sscanf(str, "%lf", &val);
  275. else {
  276. G_warning(_("\"no data\" label found; setting to zero"));
  277. val = 0.0;
  278. }
  279. return val;
  280. }