resamp.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /***********************************************************************
  2. *
  3. * MODULE: r.resamp.bspline
  4. *
  5. * AUTHOR(S): Markus Metz
  6. *
  7. * PURPOSE: Spline Interpolation and cross correlation
  8. *
  9. * COPYRIGHT: (C) 2010 GRASS development team
  10. *
  11. * This program is free software under the
  12. * GNU General Public License (>=v2).
  13. * Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. **************************************************************************/
  17. #include <grass/config.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <math.h>
  21. #include "bspline.h"
  22. struct Point *P_Read_Raster_Region_masked(SEGMENT *mask_seg,
  23. struct Cell_head *Original,
  24. struct bound_box output_box,
  25. struct bound_box General,
  26. int *num_points, int dim_vect,
  27. double mean)
  28. {
  29. int col, row, startcol, endcol, startrow, endrow, nrows, ncols;
  30. int pippo, npoints;
  31. double X, Y;
  32. struct Point *obs;
  33. char mask_val;
  34. pippo = dim_vect;
  35. obs = (struct Point *)G_calloc(pippo, sizeof(struct Point));
  36. /* Reading points inside output box and inside General box */
  37. npoints = 0;
  38. nrows = Original->rows;
  39. ncols = Original->cols;
  40. /* original region = output region
  41. * -> General box is somewhere inside output region */
  42. if (Original->north > General.N) {
  43. startrow = (double)((Original->north - General.N) / Original->ns_res - 1);
  44. if (startrow < 0)
  45. startrow = 0;
  46. }
  47. else
  48. startrow = 0;
  49. if (Original->south < General.S) {
  50. endrow = (double)((Original->north - General.S) / Original->ns_res + 1);
  51. if (endrow > nrows)
  52. endrow = nrows;
  53. }
  54. else
  55. endrow = nrows;
  56. if (General.W > Original->west) {
  57. startcol = (double)((General.W - Original->west) / Original->ew_res - 1);
  58. if (startcol < 0)
  59. startcol = 0;
  60. }
  61. else
  62. startcol = 0;
  63. if (General.E < Original->east) {
  64. endcol = (double)((General.E - Original->west) / Original->ew_res + 1);
  65. if (endcol > ncols)
  66. endcol = ncols;
  67. }
  68. else
  69. endcol = ncols;
  70. for (row = startrow; row < endrow; row++) {
  71. for (col = startcol; col < endcol; col++) {
  72. Segment_get(mask_seg, &mask_val, row, col);
  73. if (!mask_val)
  74. continue;
  75. X = Rast_col_to_easting((double)(col) + 0.5, Original);
  76. Y = Rast_row_to_northing((double)(row) + 0.5, Original);
  77. /* Here, mean is just for asking if obs point is in box */
  78. if (Vect_point_in_box(X, Y, mean, &General)) { /* General */
  79. if (npoints >= pippo) {
  80. pippo += dim_vect;
  81. obs =
  82. (struct Point *)G_realloc((void *)obs,
  83. (signed int)pippo *
  84. sizeof(struct Point));
  85. }
  86. /* Storing observation vector */
  87. obs[npoints].coordX = X;
  88. obs[npoints].coordY = Y;
  89. obs[npoints].coordZ = 0;
  90. npoints++;
  91. }
  92. }
  93. }
  94. *num_points = npoints;
  95. return obs;
  96. }
  97. int P_Sparse_Raster_Points(SEGMENT *out_seg, struct Cell_head *Elaboration,
  98. struct Cell_head *Original, struct bound_box General, struct bound_box Overlap,
  99. struct Point *obs, double *param, double pe, double pn,
  100. double overlap, int nsplx, int nsply, int num_points,
  101. int bilin, double mean)
  102. {
  103. int i, row, col;
  104. double X, Y, interpolation, csi, eta, weight, dval;
  105. int points_in_box = 0;
  106. /* Reading points inside output region and inside general box */
  107. /* all points available here are inside the output box,
  108. * selected by P_Read_Raster_Region_Nulls(), no check needed */
  109. for (i = 0; i < num_points; i++) {
  110. X = obs[i].coordX;
  111. Y = obs[i].coordY;
  112. /* X,Y are cell center cordinates, MUST be inside General box */
  113. row = (int) (floor(Rast_northing_to_row(Y, Original)) + 0.1);
  114. col = (int) (floor((X - Original->west) / Original->ew_res) + 0.1);
  115. if (row < 0 || row >= Original->rows) {
  116. G_fatal_error("row index out of range");
  117. continue;
  118. }
  119. if (col < 0 || col >= Original->cols) {
  120. G_fatal_error("col index out of range");
  121. continue;
  122. }
  123. points_in_box++;
  124. G_debug(3, "P_Sparse_Raster_Points: interpolate point %d...", i);
  125. if (bilin)
  126. interpolation =
  127. dataInterpolateBilin(X, Y, pe, pn, nsplx,
  128. nsply, Elaboration->west,
  129. Elaboration->south, param);
  130. else
  131. interpolation =
  132. dataInterpolateBicubic(X, Y, pe, pn, nsplx,
  133. nsply, Elaboration->west,
  134. Elaboration->south, param);
  135. interpolation += mean;
  136. if (Vect_point_in_box(X, Y, interpolation, &Overlap)) { /* (5) */
  137. dval = interpolation;
  138. }
  139. else {
  140. Segment_get(out_seg, &dval, row, col);
  141. if ((X > Overlap.E) && (X < General.E)) {
  142. if ((Y > Overlap.N) && (Y < General.N)) { /* (3) */
  143. csi = (General.E - X) / overlap;
  144. eta = (General.N - Y) / overlap;
  145. weight = csi * eta;
  146. interpolation *= weight;
  147. dval += interpolation;
  148. }
  149. else if ((Y < Overlap.S) && (Y > General.S)) { /* (1) */
  150. csi = (General.E - X) / overlap;
  151. eta = (Y - General.S) / overlap;
  152. weight = csi * eta;
  153. interpolation *= weight;
  154. dval = interpolation;
  155. }
  156. else if ((Y >= Overlap.S) && (Y <= Overlap.N)) { /* (1) */
  157. weight = (General.E - X ) / overlap;
  158. interpolation *= weight;
  159. dval = interpolation;
  160. }
  161. }
  162. else if ((X < Overlap.W) && (X > General.W)) {
  163. if ((Y > Overlap.N) && (Y < General.N)) { /* (4) */
  164. csi = (X - General.W) / overlap;
  165. eta = (General.N - Y) / overlap;
  166. weight = eta * csi;
  167. interpolation *= weight;
  168. dval += interpolation;
  169. }
  170. else if ((Y < Overlap.S) && (Y > General.S)) { /* (2) */
  171. csi = (X - General.W) / overlap;
  172. eta = (Y - General.S) / overlap;
  173. weight = csi * eta;
  174. interpolation *= weight;
  175. dval += interpolation;
  176. }
  177. else if ((Y >= Overlap.S) && (Y <= Overlap.N)) { /* (2) */
  178. weight = (X - General.W) / overlap;
  179. interpolation *= weight;
  180. dval += interpolation;
  181. }
  182. }
  183. else if ((X >= Overlap.W) && (X <= Overlap.E)) {
  184. if ((Y > Overlap.N) && (Y < General.N)) { /* (3) */
  185. weight = (General.N - Y) / overlap;
  186. interpolation *= weight;
  187. dval += interpolation;
  188. }
  189. else if ((Y < Overlap.S) && (Y > General.S)) { /* (1) */
  190. weight = (Y - General.S) / overlap;
  191. interpolation *= weight;
  192. dval = interpolation;
  193. }
  194. }
  195. } /* end not in overlap */
  196. Segment_put(out_seg, &dval, row, col);
  197. } /* for num_points */
  198. return 1;
  199. }
  200. /* align elaboration box to source region
  201. * grow each side */
  202. int align_elaboration_box(struct Cell_head *elaboration, struct Cell_head *original, int type)
  203. {
  204. int row, col;
  205. switch (type) {
  206. case GENERAL_ROW: /* General case N-S direction */
  207. /* northern edge */
  208. row = (int)((original->north - elaboration->north) / original->ns_res);
  209. if (row < 0)
  210. row = 0;
  211. elaboration->north = original->north - original->ns_res * row;
  212. /* southern edge */
  213. row = (int)((original->north - elaboration->south) / original->ns_res) + 1;
  214. if (row > original->rows + 1)
  215. row = original->rows + 1;
  216. elaboration->south = original->north - original->ns_res * row;
  217. return 1;
  218. case GENERAL_COLUMN: /* General case E-W direction */
  219. /* eastern edge */
  220. col = (int)((elaboration->east - original->west) / original->ew_res) + 1;
  221. if (col > original->cols + 1)
  222. col = original->cols + 1;
  223. elaboration->east = original->west + original->ew_res * col;
  224. /* western edge */
  225. col = (int)((elaboration->west - original->west) / original->ew_res);
  226. if (col < 0)
  227. col = 0;
  228. elaboration->west = original->west + original->ew_res * col;
  229. return 1;
  230. }
  231. return 0;
  232. }
  233. /* align interpolation boxes to destination region
  234. * return 1 on success, 0 on failure */
  235. int align_interp_boxes(struct bound_box *general, struct bound_box *overlap,
  236. struct Cell_head *original, struct bound_box last_general,
  237. struct bound_box last_overlap, int type)
  238. {
  239. int row, col;
  240. switch (type) {
  241. case GENERAL_ROW: /* General case N-S direction */
  242. /* general box */
  243. /* grow north */
  244. general->N = last_overlap.S;
  245. /* shrink south */
  246. row = (int)((original->north - general->S) / original->ns_res);
  247. if (row > original->rows + 1)
  248. row = original->rows + 1;
  249. general->S = original->north - original->ns_res * row;
  250. /* overlap box */
  251. /* grow north */
  252. overlap->N = last_general.S;
  253. /* shrink south */
  254. row = (int)((original->north - overlap->S) / original->ns_res);
  255. if (row > original->rows + 1)
  256. row = original->rows + 1;
  257. overlap->S = original->north - original->ns_res * row;
  258. return 1;
  259. case GENERAL_COLUMN: /* General case E-W direction */
  260. /* general box */
  261. /* grow west */
  262. general->W = last_overlap.E;
  263. /* shrink east */
  264. col = (int)((general->E - original->west) / original->ew_res);
  265. if (col > original->cols + 1)
  266. col = original->cols + 1;
  267. general->E = original->west + original->ew_res * col;
  268. /* overlap box */
  269. /* grow west */
  270. overlap->W = last_general.E;
  271. /* shrink east */
  272. col = (int)((overlap->E - original->west) / original->ew_res);
  273. if (col > original->cols + 1)
  274. col = original->cols + 1;
  275. overlap->E = original->west + original->ew_res * col;
  276. return 1;
  277. case FIRST_ROW: /* Just started with first row */
  278. general->N = original->north;
  279. overlap->N = original->north;
  280. /* shrink south */
  281. row = (int)((original->north - general->S) / original->ns_res);
  282. if (row > original->rows)
  283. row = original->rows;
  284. general->S = original->north - original->ns_res * row;
  285. row = (int)((original->north - overlap->S) / original->ns_res);
  286. if (row > original->rows + 1)
  287. row = original->rows + 1;
  288. overlap->S = original->north - original->ns_res * row;
  289. return 1;
  290. case LAST_ROW: /* Reached last row */
  291. general->S = original->south;
  292. overlap->S = original->south;
  293. return 1;
  294. case FIRST_COLUMN: /* Just started with first column */
  295. general->W = original->west;
  296. overlap->W = original->west;
  297. /* shrink east */
  298. col = (int)((general->E - original->west) / original->ew_res);
  299. if (col > original->cols + 1)
  300. col = original->cols + 1;
  301. general->E = original->west + original->ew_res * col;
  302. col = (int)((overlap->E - original->west) / original->ew_res);
  303. if (col > original->cols + 1)
  304. col = original->cols + 1;
  305. overlap->E = original->west + original->ew_res * col;
  306. return 1;
  307. case LAST_COLUMN: /* Reached last column */
  308. general->E = original->east;
  309. overlap->E = original->east;
  310. return 1;
  311. }
  312. return 0;
  313. }