sample.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*!
  2. \file sample.c
  3. \brief GIS 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-2008 by the GRASS Development Team
  7. This program is free software under the
  8. GNU General Public License (>=v2).
  9. Read the file COPYING that comes with GRASS
  10. for details.
  11. \author James Darrell McCauley <darrell mccauley-usa.com>, http://mccauley-usa.com/
  12. \date 1994
  13. */
  14. #include <string.h>
  15. #include <unistd.h>
  16. #include <math.h>
  17. #include <grass/gis.h>
  18. #include <grass/glocale.h>
  19. /* prototypes */
  20. static double scancatlabel(const char *);
  21. static void raster_row_error(const struct Cell_head *window, double north,
  22. double east);
  23. /*!
  24. * \brief Extract a cell value from raster map.
  25. *
  26. * Extract a cell value from raster map at given northing and easting
  27. * with a sampled 3x3 window using a specified interpolation method.
  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 G_get_raster_sample(
  40. int fd,
  41. const struct Cell_head *window,
  42. struct Categories *cats,
  43. double north, double east,
  44. int usedesc, INTERP_TYPE itype)
  45. {
  46. double retval;
  47. switch (itype) {
  48. case NEAREST:
  49. retval = G_get_raster_sample_nearest(fd, window, cats, north, east, usedesc);
  50. break;
  51. case BILINEAR:
  52. retval = G_get_raster_sample_bilinear(fd, window, cats, north, east, usedesc);
  53. break;
  54. case CUBIC:
  55. retval = G_get_raster_sample_cubic(fd, window, cats, north, east, usedesc);
  56. break;
  57. default:
  58. G_fatal_error("G_get_raster_sample: %s",
  59. _("Unknown interpolation type"));
  60. }
  61. return retval;
  62. }
  63. DCELL G_get_raster_sample_nearest(
  64. int fd,
  65. const struct Cell_head *window,
  66. struct Categories *cats,
  67. double north, double east, int usedesc)
  68. {
  69. int row, col;
  70. DCELL result;
  71. DCELL *maprow = G_allocate_d_raster_buf();
  72. /* convert northing and easting to row and col, resp */
  73. row = (int)floor(G_northing_to_row(north, window));
  74. col = (int)floor(G_easting_to_col(east, window));
  75. if (row < 0 || row >= G_window_rows() ||
  76. col < 0 || col >= G_window_cols()) {
  77. G_set_d_null_value(&result, 1);
  78. goto done;
  79. }
  80. if (G_get_d_raster_row(fd, maprow, row) < 0)
  81. raster_row_error(window, north, east);
  82. if (G_is_d_null_value(&maprow[col])) {
  83. G_set_d_null_value(&result, 1);
  84. goto done;
  85. }
  86. if (usedesc) {
  87. char *buf = G_get_cat(maprow[col], cats);
  88. G_squeeze(buf);
  89. result = scancatlabel(buf);
  90. }
  91. else
  92. result = maprow[col];
  93. done:
  94. G_free(maprow);
  95. return result;
  96. }
  97. DCELL G_get_raster_sample_bilinear(
  98. int fd,
  99. const struct Cell_head *window,
  100. struct Categories *cats,
  101. double north, double east, int usedesc)
  102. {
  103. int row, col;
  104. double grid[2][2];
  105. DCELL *arow = G_allocate_d_raster_buf();
  106. DCELL *brow = G_allocate_d_raster_buf();
  107. double frow, fcol, trow, tcol;
  108. DCELL result;
  109. frow = G_northing_to_row(north, window);
  110. fcol = G_easting_to_col(east, window);
  111. /* convert northing and easting to row and col, resp */
  112. row = (int)floor(frow - 0.5);
  113. col = (int)floor(fcol - 0.5);
  114. trow = frow - row - 0.5;
  115. tcol = fcol - col - 0.5;
  116. if (row < 0 || row + 1 >= G_window_rows() ||
  117. col < 0 || col + 1 >= G_window_cols()) {
  118. G_set_d_null_value(&result, 1);
  119. goto done;
  120. }
  121. if (G_get_d_raster_row(fd, arow, row) < 0)
  122. raster_row_error(window, north, east);
  123. if (G_get_d_raster_row(fd, brow, row + 1) < 0)
  124. raster_row_error(window, north, east);
  125. if (G_is_d_null_value(&arow[col]) || G_is_d_null_value(&arow[col + 1]) ||
  126. G_is_d_null_value(&brow[col]) || G_is_d_null_value(&brow[col + 1])) {
  127. G_set_d_null_value(&result, 1);
  128. goto done;
  129. }
  130. /*-
  131. * now were ready to do bilinear interpolation over
  132. * arow[col], arow[col+1],
  133. * brow[col], brow[col+1]
  134. */
  135. if (usedesc) {
  136. char *buf;
  137. G_squeeze(buf = G_get_cat((int)arow[col], cats));
  138. grid[0][0] = scancatlabel(buf);
  139. G_squeeze(buf = G_get_cat((int)arow[col + 1], cats));
  140. grid[0][1] = scancatlabel(buf);
  141. G_squeeze(buf = G_get_cat((int)brow[col], cats));
  142. grid[1][0] = scancatlabel(buf);
  143. G_squeeze(buf = G_get_cat((int)brow[col + 1], cats));
  144. grid[1][1] = scancatlabel(buf);
  145. }
  146. else {
  147. grid[0][0] = arow[col];
  148. grid[0][1] = arow[col + 1];
  149. grid[1][0] = brow[col];
  150. grid[1][1] = brow[col + 1];
  151. }
  152. result = G_interp_bilinear(tcol, trow,
  153. grid[0][0], grid[0][1], grid[1][0], grid[1][1]);
  154. done:
  155. G_free(arow);
  156. G_free(brow);
  157. return result;
  158. }
  159. DCELL G_get_raster_sample_cubic(
  160. int fd,
  161. const struct Cell_head *window,
  162. struct Categories *cats,
  163. double north, double east, int usedesc)
  164. {
  165. int i, j, row, col;
  166. double grid[4][4];
  167. DCELL *rows[4];
  168. double frow, fcol, trow, tcol;
  169. DCELL result;
  170. for (i = 0; i < 4; i++)
  171. rows[i] = G_allocate_d_raster_buf();
  172. frow = G_northing_to_row(north, window);
  173. fcol = G_easting_to_col(east, window);
  174. /* convert northing and easting to row and col, resp */
  175. row = (int)floor(frow - 1.5);
  176. col = (int)floor(fcol - 1.5);
  177. trow = frow - row - 1.5;
  178. tcol = fcol - col - 1.5;
  179. if (row < 0 || row + 3 >= G_window_rows() ||
  180. col < 0 || col + 3 >= G_window_cols()) {
  181. G_set_d_null_value(&result, 1);
  182. goto done;
  183. }
  184. for (i = 0; i < 4; i++)
  185. if (G_get_d_raster_row(fd, rows[i], row + i) < 0)
  186. raster_row_error(window, north, east);
  187. for (i = 0; i < 4; i++)
  188. for (j = 0; j < 4; j++)
  189. if (G_is_d_null_value(&rows[i][col + j])) {
  190. G_set_d_null_value(&result, 1);
  191. goto done;
  192. }
  193. /*
  194. * now were ready to do cubic interpolation over
  195. * arow[col], arow[col+1], arow[col+2], arow[col+3],
  196. * brow[col], brow[col+1], brow[col+2], brow[col+3],
  197. * crow[col], crow[col+1], crow[col+2], crow[col+3],
  198. * drow[col], drow[col+1], drow[col+2], drow[col+3],
  199. */
  200. if (usedesc) {
  201. char *buf;
  202. for (i = 0; i < 4; i++) {
  203. for (j = 0; j < 4; j++) {
  204. G_squeeze(buf = G_get_cat(rows[i][col + j], cats));
  205. grid[i][j] = scancatlabel(buf);
  206. }
  207. }
  208. }
  209. else {
  210. for (i = 0; i < 4; i++)
  211. for (j = 0; j < 4; j++)
  212. grid[i][j] = rows[i][col + j];
  213. }
  214. result = G_interp_bicubic(tcol, trow,
  215. grid[0][0], grid[0][1], grid[0][2], grid[0][3],
  216. grid[1][0], grid[1][1], grid[1][2], grid[1][3],
  217. grid[2][0], grid[2][1], grid[2][2], grid[2][3],
  218. grid[3][0], grid[3][1], grid[3][2], grid[3][3]);
  219. done:
  220. for (i = 0; i < 4; i++)
  221. G_free(rows[i]);
  222. return result;
  223. }
  224. static double scancatlabel(const char *str)
  225. {
  226. double val;
  227. if (strcmp(str, "no data") != 0)
  228. sscanf(str, "%lf", &val);
  229. else {
  230. G_warning(_("\"no data\" label found; setting to zero"));
  231. val = 0.0;
  232. }
  233. return val;
  234. }
  235. static void raster_row_error(const struct Cell_head *window, double north,
  236. double east)
  237. {
  238. G_debug(3, "DIAG: \tRegion is: n=%g s=%g e=%g w=%g",
  239. window->north, window->south, window->east, window->west);
  240. G_debug(3, " \tData point is north=%g east=%g", north, east);
  241. G_fatal_error(_("Problem reading raster map"));
  242. }