main.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /****************************************************************************
  2. *
  3. * MODULE: r.series.interp
  4. * AUTHOR(S): Soeren Gebbert <soerengebbert googlemail.com>
  5. * Code is based on r.series from Glynn Clements <glynn gclements.plus.com>
  6. *
  7. * PURPOSE: Interpolate raster maps located (temporal or spatial) in between input raster maps at specific sampling positions
  8. * COPYRIGHT: (C) 2011-2012 by the GRASS Development Team
  9. *
  10. * This program is free software under the GNU General Public
  11. * License (>=v2). Read the infile COPYING that comes with GRASS
  12. * for details.
  13. *
  14. *****************************************************************************/
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <math.h>
  19. #include <grass/gis.h>
  20. #include <grass/raster.h>
  21. #include <grass/glocale.h>
  22. #include <grass/stats.h>
  23. #define LINEAR_INTERPOLATION 1
  24. #define SPLINE_INTERPOLATION 2
  25. struct map_store
  26. {
  27. const char *name;
  28. double pos;
  29. DCELL *buf;
  30. int fd;
  31. int has_run;
  32. };
  33. void selection_sort(struct map_store **array, int num);
  34. static struct map_store *get_parameter_input(const char *type, char **map_names, char **positions, char *file, int *number_of_maps);
  35. static void linear_interpolation(struct map_store **inp, int num_inputs, struct map_store **outp, int num_outputs);
  36. static void interpolate_row_linear(struct map_store *left, struct map_store *right, struct map_store *out, int ncols);
  37. static void start_interpolation(struct map_store *inputs, int num_inputs, struct map_store *outputs, int num_outputs, int interpol_method);
  38. /* *************************************************************** */
  39. /* *************************************************************** */
  40. /* *************************************************************** */
  41. int main(int argc, char *argv[])
  42. {
  43. struct GModule *module;
  44. struct
  45. {
  46. struct Option *input, *datapos, *infile, *output, *samplingpos, *outfile, *method;
  47. } parm;
  48. int num_outputs;
  49. int num_inputs;
  50. struct map_store *inputs = NULL;
  51. struct map_store *outputs = NULL;
  52. int interpol_method = LINEAR_INTERPOLATION;
  53. G_gisinit(argv[0]);
  54. module = G_define_module();
  55. G_add_keyword(_("raster"));
  56. G_add_keyword(_("series"));
  57. G_add_keyword(_("interpolation"));
  58. /* TODO: re-phrase the description */
  59. module->description =
  60. _("Interpolates raster maps located (temporal or spatial) "
  61. "in between input raster maps at specific sampling positions.");
  62. parm.input = G_define_standard_option(G_OPT_R_INPUTS);
  63. parm.input->required = NO;
  64. parm.datapos = G_define_option();
  65. parm.datapos->key = "datapos";
  66. parm.datapos->type = TYPE_DOUBLE;
  67. parm.datapos->required = NO;
  68. parm.datapos->description = _("Data point position for each input map");
  69. parm.datapos->multiple = YES;
  70. parm.infile = G_define_standard_option(G_OPT_F_INPUT);
  71. parm.infile->key = "infile";
  72. parm.infile->description = _("Input file with one input raster map name and data point position per line,"
  73. " field separator between name and sample point is |");
  74. parm.infile->required = NO;
  75. parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
  76. parm.output->multiple = YES;
  77. parm.output->required = NO;
  78. parm.samplingpos = G_define_option();
  79. parm.samplingpos->key = "samplingpos";
  80. parm.samplingpos->type = TYPE_DOUBLE;
  81. parm.samplingpos->required = NO;
  82. parm.samplingpos->multiple = YES;
  83. parm.samplingpos->description = _("Sampling point position for each output map");
  84. parm.outfile = G_define_standard_option(G_OPT_F_INPUT);
  85. parm.outfile->key = "outfile";
  86. parm.outfile->description = _("Input file with one output raster map name and sample point position per line,"
  87. " field separator between name and sample point is |");
  88. parm.outfile->required = NO;
  89. parm.method = G_define_option();
  90. parm.method->key = "method";
  91. parm.method->type = TYPE_STRING;
  92. parm.method->required = NO;
  93. parm.method->options = "linear";
  94. parm.method->answer = "linear";
  95. parm.method->description = _("Interpolation method, currently only linear interpolation is supported");
  96. parm.method->multiple = NO;
  97. if (G_parser(argc, argv))
  98. exit(EXIT_FAILURE);
  99. if (parm.output->answer && parm.outfile->answer)
  100. G_fatal_error(_("%s= and %s= are mutually exclusive"),
  101. parm.output->key, parm.outfile->key);
  102. if (parm.samplingpos->answer && parm.outfile->answer)
  103. G_fatal_error(_("%s= and %s= are mutually exclusive"),
  104. parm.samplingpos->key, parm.outfile->key);
  105. if (!parm.output->answer && !parm.outfile->answer)
  106. G_fatal_error(_("Please specify %s= or %s="),
  107. parm.output->key, parm.outfile->key);
  108. if (parm.output->answer && !parm.samplingpos->answer)
  109. G_fatal_error(_("Please specify %s= and %s="),
  110. parm.output->key, parm.samplingpos->key);
  111. if (parm.input->answer && parm.infile->answer)
  112. G_fatal_error(_("%s= and %s= are mutually exclusive"),
  113. parm.input->key, parm.infile->key);
  114. if (parm.datapos->answer && parm.infile->answer)
  115. G_fatal_error(_("%s= and %s= are mutually exclusive"),
  116. parm.datapos->key, parm.infile->key);
  117. if (!parm.input->answer && !parm.infile->answer)
  118. G_fatal_error(_("Please specify %s= or %s="),
  119. parm.input->key, parm.infile->key);
  120. if (parm.input->answer && !parm.datapos->answer)
  121. G_fatal_error(_("Please specify %s= and %s="),
  122. parm.input->key, parm.datapos->key);
  123. if(G_strncasecmp(parm.method->answer, "linear", 6) == 0)
  124. interpol_method = LINEAR_INTERPOLATION;
  125. if(G_strncasecmp(parm.method->answer, "spline", 6) == 0)
  126. interpol_method = SPLINE_INTERPOLATION;
  127. inputs = get_parameter_input("input", parm.input->answers, parm.datapos->answers, parm.infile->answer, &num_inputs);
  128. outputs = get_parameter_input("output", parm.output->answers, parm.samplingpos->answers, parm.outfile->answer, &num_outputs);
  129. start_interpolation(inputs, num_inputs, outputs, num_outputs, interpol_method);
  130. exit(EXIT_SUCCESS);
  131. }
  132. /* *************************************************************** */
  133. /* *************************************************************** */
  134. /* *************************************************************** */
  135. struct map_store *get_parameter_input(const char *type, char **map_names, char **positions, char *file, int *number_of_maps)
  136. {
  137. struct map_store *maps = NULL;
  138. int max_maps;
  139. int num_maps;
  140. int num_points;
  141. /* process the output maps from the infile */
  142. if (file) {
  143. FILE *in;
  144. in = fopen(file, "r");
  145. if (!in)
  146. G_fatal_error(_("Unable to open %s file <%s>"), type, file);
  147. num_maps = 0;
  148. max_maps = 0;
  149. for (;;) {
  150. char buf[GNAME_MAX + 50]; /* Name and position */
  151. char tok_buf[GNAME_MAX + 50]; /* Name and position */
  152. char *name;
  153. int ntokens;
  154. char **tokens;
  155. struct map_store *p;
  156. double pos = -1;
  157. if (!G_getl2(buf, sizeof(buf), in))
  158. break;
  159. strcpy(tok_buf, buf);
  160. tokens = G_tokenize(tok_buf, "|");
  161. ntokens = G_number_of_tokens(tokens);
  162. if(ntokens > 1) {
  163. name = G_chop(tokens[0]);
  164. pos = atof(G_chop(tokens[1]));
  165. } else {
  166. name = G_chop(buf);
  167. }
  168. /* Ignore empty lines */
  169. if (!*name)
  170. continue;
  171. if(pos == -1)
  172. G_fatal_error(_("Missing point position for %s map <%s>"
  173. " in file <%s> near line %i"),
  174. type, name, file, num_maps);
  175. if (num_maps >= max_maps) {
  176. max_maps += 100;
  177. maps = G_realloc(maps, max_maps * sizeof(struct map_store));
  178. }
  179. p = &maps[num_maps++];
  180. p->name = G_store(name);
  181. p->pos = pos;
  182. p->fd = -1;
  183. p->buf = NULL;
  184. p->has_run = 0;
  185. G_verbose_message(_("Preparing %s map <%s> at position %g"), type, p->name, p->pos);
  186. }
  187. if (num_maps < 1)
  188. G_fatal_error(_("No raster map name found in %s file <%s>"), type, file);
  189. fclose(in);
  190. }
  191. else {
  192. int i;
  193. for (i = 0; map_names[i]; i++)
  194. ;
  195. num_maps = i;
  196. if (num_maps < 1)
  197. G_fatal_error(_("No %s raster map not found"), type);
  198. for (i = 0; positions[i]; i++)
  199. ;
  200. num_points = i;
  201. if (num_points != num_maps)
  202. G_fatal_error(_("The number of %s maps and %s point positions must be equal"), type, type);
  203. maps = G_malloc(num_maps * sizeof(struct map_store));
  204. for (i = 0; i < num_maps; i++) {
  205. struct map_store *p = &maps[i];
  206. p->name = map_names[i];
  207. p->pos = (DCELL)atof(positions[i]);
  208. p->fd = -1;
  209. p->buf = NULL;
  210. p->has_run = 0;
  211. G_verbose_message(_("Preparing %s map <%s> at position %g"), type, p->name, p->pos);
  212. }
  213. }
  214. *number_of_maps = num_maps;
  215. return maps;
  216. }
  217. /* *************************************************************** */
  218. /* *************************************************************** */
  219. /* *************************************************************** */
  220. void start_interpolation(struct map_store *inputs, int num_inputs, struct map_store *outputs, int num_outputs, int interpol_method)
  221. {
  222. int i;
  223. struct map_store **inp = (struct map_store**) G_malloc(num_inputs * sizeof(struct map_store*));
  224. struct map_store **outp = (struct map_store**) G_malloc(num_outputs * sizeof(struct map_store*));
  225. G_verbose_message(_("Start interpolation run with %i input maps and %i output maps"),
  226. num_inputs, num_outputs);
  227. for(i = 0; i < num_inputs; i++)
  228. inp[i] = &inputs[i];
  229. for(i = 0; i < num_outputs; i++)
  230. outp[i] = &outputs[i];
  231. /* Sort input and output pointer by their point position
  232. * using brute force. :)
  233. */
  234. selection_sort(inp, num_inputs);
  235. selection_sort(outp, num_outputs);
  236. if(interpol_method == LINEAR_INTERPOLATION)
  237. linear_interpolation(inp, num_inputs, outp, num_outputs);
  238. for(i = 0; i < num_outputs; i++) {
  239. if(outp[i]->has_run == 0)
  240. G_warning(_("map <%s> at position %g was not interpolated. Check the interpolation interval."), outp[i]->name, outp[i]->pos);
  241. }
  242. }
  243. /* *************************************************************** */
  244. /* *************************************************************** */
  245. /* *************************************************************** */
  246. void linear_interpolation(struct map_store **inp, int num_inputs,
  247. struct map_store **outp, int num_outputs)
  248. {
  249. struct map_store *left;
  250. struct map_store *right;
  251. struct History history;
  252. int interval, l, row;
  253. int nrows = Rast_window_rows();
  254. int ncols = Rast_window_cols();
  255. int start = 0;
  256. if(num_inputs < 2)
  257. G_fatal_error(_("At least 2 input maps are required for linear interpolation"));
  258. /* Interpolate for each interval */
  259. for(interval = 0; interval < num_inputs - 1; interval++) {
  260. left = inp[interval];
  261. right = inp[interval + 1];
  262. left->fd = Rast_open_old(left->name, "");
  263. right->fd = Rast_open_old(right->name, "");
  264. left->buf = Rast_allocate_d_buf();
  265. right->buf = Rast_allocate_d_buf();
  266. for(l = start; l < num_outputs; l++) {
  267. /* Check if the map is in the interval and process it */
  268. if(outp[l]->pos >= left->pos && outp[l]->pos <= right->pos) {
  269. outp[l]->fd = Rast_open_new(outp[l]->name, DCELL_TYPE);
  270. outp[l]->buf = Rast_allocate_d_buf();
  271. G_verbose_message(_("Interpolate map <%s> at position %g in interval (%g;%g)"),
  272. outp[l]->name, outp[l]->pos, left->pos, right->pos);
  273. G_verbose_message(_("Percent complete..."));
  274. for (row = 0; row < nrows; row++) {
  275. G_percent(row, nrows, 2);
  276. Rast_get_d_row(left->fd, left->buf, row);
  277. Rast_get_d_row(right->fd, right->buf, row);
  278. interpolate_row_linear(left, right, outp[l], ncols);
  279. Rast_put_d_row(outp[l]->fd, outp[l]->buf);
  280. }
  281. G_percent(row, nrows, 2);
  282. Rast_close(outp[l]->fd);
  283. Rast_short_history(outp[l]->name, "raster", &history);
  284. Rast_command_history(&history);
  285. Rast_write_history(outp[l]->name, &history);
  286. G_free(outp[l]->buf);
  287. outp[l]->has_run = 1;
  288. start = l;
  289. }
  290. }
  291. Rast_close(left->fd);
  292. G_free(left->buf);
  293. Rast_close(right->fd);
  294. G_free(right->buf);
  295. }
  296. }
  297. /* *************************************************************** */
  298. /* *************************************************************** */
  299. /* *************************************************************** */
  300. /* linear function v = (1 - pos/dist) * u1 + pos/dist * u2
  301. *
  302. * v -> The value of the output map
  303. * pos -> The normalized position of the output map
  304. * u1 -> The value of the left input map
  305. * u2 -> The value of the right input map
  306. * dist -> The distance between the position of u1 and u2
  307. *
  308. * */
  309. void interpolate_row_linear(struct map_store *left, struct map_store *right, struct map_store *out, int ncols)
  310. {
  311. DCELL v;
  312. DCELL u1;
  313. DCELL u2;
  314. DCELL dist;
  315. int col;
  316. for (col = 0; col < ncols; col++) {
  317. u1 = left->buf[col];
  318. u2 = right->buf[col];
  319. dist = fabs(right->pos - left->pos);
  320. if(Rast_is_d_null_value(&u1) || Rast_is_d_null_value(&u2)) {
  321. Rast_set_d_null_value(&v, 1);
  322. } else {
  323. v = (1 - ((out->pos - left->pos)/dist)) * u1 + ((out->pos - left->pos)/dist) * u2;
  324. }
  325. out->buf[col] = v;
  326. }
  327. return;
  328. }
  329. /* *************************************************************** */
  330. /* *************************************************************** */
  331. /* *************************************************************** */
  332. void selection_sort(struct map_store **array, int num)
  333. {
  334. int i, j, b;
  335. struct map_store *min;
  336. for (i = 0; i < num - 1; i++) {
  337. b = i;
  338. min = array[b];
  339. for (j = i + 1; j < num; j++) {
  340. if (array[j]->pos < min->pos) {
  341. b = j;
  342. min = array[b];
  343. }
  344. }
  345. array[b] = array[i];
  346. array[i] = min;
  347. }
  348. }