main.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  1. /***************************************************************************
  2. *
  3. * MODULE: r.fill.stats
  4. * AUTHOR(S): Benjamin Ducke
  5. * Anna Petrasova (speedup with -p, fix of median, mode computation)
  6. * PURPOSE: Rapidly fill "no data" cells in a raster map by simple interpolation.
  7. *
  8. * COPYRIGHT: (C) 2011-2018 by the GRASS Development Team
  9. *
  10. * This program is free software under the GPL (>=v2)
  11. * Read the file COPYING that comes with GRASS for details.
  12. *
  13. ****************************************************************************
  14. */
  15. /*
  16. DOCS:
  17. - docs need a lot of updates!
  18. - dropped medoid (since we always have an odd number of cells, median=medoid).
  19. - flag -p(reserve) reversed (preservation is now default)
  20. - flag for including center cell has been dropped; center always included
  21. - "method" renamed to "mode"
  22. - by default, neighborhood size is now assumed to be in cells,
  23. unless -m(ap units) is given
  24. - only -m(ap units) will result in an exact, circular neighborhood;
  25. if (default) cells size specification is used, then the neighborhood
  26. shape is a less exact rectangle; in that case the neighborhood dimensions
  27. will also be different for x and y if the cell dimensions are different
  28. - lat/lon data is allowed, but distance measure for -m(ap units) is straight line!
  29. - cell weights are now normalized to be in range [0;1]
  30. - center cell weight for "wmean" is now "1.0"
  31. BUGS:
  32. - mode, median and mode produce large areas of "no data" where there is input data!!!
  33. NEXT VERSION:
  34. - add lat/lon distance and cost map distance measures (lat/lon currently throws an error).
  35. - allow user to set which cell value should be filled (i.e. interpreted as "no data")
  36. */
  37. #include <math.h>
  38. #include <string.h>
  39. #include <stdlib.h>
  40. #include <time.h>
  41. #include <errno.h>
  42. #include <grass/gis.h>
  43. #include <grass/glocale.h>
  44. #include "cell_funcs.h"
  45. /* Global variables :-) */
  46. double **WEIGHTS; /* neighborhood weights */
  47. double SUM_WEIGHTS; /* sum of weights in all cells (with or without data) of neighborhood */
  48. unsigned long WINDOW_WIDTH = 0; /* dimensions of neighborhood window */
  49. unsigned long WINDOW_HEIGHT = 0;
  50. unsigned long DATA_WIDTH = 0;
  51. unsigned long DATA_HEIGHT = 0;
  52. unsigned long PADDING_WIDTH = 0;
  53. unsigned long PADDING_HEIGHT = 0;
  54. void **CELL_INPUT = NULL;
  55. void **CELL_INPUT_HANDLES = NULL;
  56. void *CELL_OUTPUT = NULL;
  57. FCELL *ERR_OUTPUT = NULL;
  58. /* holds statistics of cells within the neighborhood */
  59. typedef struct
  60. {
  61. unsigned long num_values; /* number of cells with values in input raster */
  62. double *values; /* individual values of all cells */
  63. double *weights; /* individual weights of all cells */
  64. double result; /* weighted mean of values in entire neighborhood */
  65. double certainty; /* certainty measure, always between 0 (lowest) and 1 (highest) */
  66. unsigned long *frequencies; /* frequency count for each value */
  67. double *overwrite_value; /* will be set to non-null to overwrite the statistical result with this value */
  68. int overwrite; /* 1 to overwrite the statistical result with the original value */
  69. } stats_struct;
  70. /* function pointers for operation modes */
  71. void (*GET_STATS) (unsigned long, unsigned long, double, double, int,
  72. stats_struct *);
  73. void (*COLLECT_DATA) (double, double, double, double, stats_struct *);
  74. /*
  75. * Returns a rough estimate of the amount of RAM
  76. * (in bytes) that this program will require.
  77. */
  78. //TODO: this also needs to take into account additional input and output maps (once implemented).
  79. long int estimate_mem_needed(long int cols, char *mode)
  80. {
  81. long int mem_count = 0;
  82. long int in_bytes = 0;
  83. long int out_bytes = 0;
  84. long int stat_bytes = 0;
  85. /* memory for neighborhood weights and statistics */
  86. if (!strcmp(mode, "wmean")) {
  87. stat_bytes += sizeof(double) * (DATA_WIDTH * DATA_HEIGHT); /* weights matrix */
  88. }
  89. stat_bytes += sizeof(double) * (DATA_WIDTH * DATA_HEIGHT); /* max. cell values */
  90. stat_bytes += sizeof(double) * (DATA_WIDTH * DATA_HEIGHT); /* max. cell weights */
  91. stat_bytes += sizeof(unsigned long) * (DATA_WIDTH * DATA_HEIGHT); /* max. cell frequencies */
  92. /* input data rows with padded buffers */
  93. in_bytes = (unsigned long)(WINDOW_HEIGHT * (cols + (PADDING_WIDTH * 2)));
  94. if (IN_TYPE == CELL_TYPE) {
  95. in_bytes += in_bytes * sizeof(CELL);
  96. }
  97. if (IN_TYPE == FCELL_TYPE) {
  98. in_bytes += in_bytes * sizeof(FCELL);
  99. }
  100. if (IN_TYPE == DCELL_TYPE) {
  101. in_bytes += in_bytes * sizeof(DCELL);
  102. }
  103. /* output data row */
  104. out_bytes = (unsigned long)cols;
  105. if (OUT_TYPE == CELL_TYPE) {
  106. out_bytes += out_bytes * sizeof(CELL);
  107. }
  108. if (OUT_TYPE == FCELL_TYPE) {
  109. out_bytes += out_bytes * sizeof(FCELL);
  110. }
  111. if (OUT_TYPE == DCELL_TYPE) {
  112. out_bytes += out_bytes * sizeof(DCELL);
  113. }
  114. mem_count = stat_bytes + in_bytes + out_bytes;
  115. return (mem_count);
  116. }
  117. /*
  118. * Prints the spatial weights matrix to the console.
  119. * This uses a fixed layout which may not be able to print very
  120. * large matrices.
  121. */
  122. void print_weights_matrix(long int rows, long int cols)
  123. {
  124. int i, j;
  125. int weight_matrix_line_length = 80;
  126. char weight_matrix_line_buf[weight_matrix_line_length + 1];
  127. char weight_matrix_weight_buf[weight_matrix_line_length + 1];
  128. G_message(_("Spatial weights neighborhood (cells):"));
  129. for (i = 0; i < rows; i++) {
  130. weight_matrix_line_buf[0] = '\0';
  131. for (j = 0; j < cols; j++) {
  132. if (WEIGHTS[i][j] != -1.0) {
  133. snprintf(weight_matrix_weight_buf, weight_matrix_line_length,
  134. "%06.2f ", WEIGHTS[i][j]);
  135. }
  136. else {
  137. snprintf(weight_matrix_weight_buf, weight_matrix_line_length,
  138. "...... ");
  139. }
  140. if (strlen(weight_matrix_weight_buf) +
  141. strlen(weight_matrix_line_buf) > weight_matrix_line_length) {
  142. strncpy(weight_matrix_line_buf, "[line too long to print]",
  143. weight_matrix_line_length);
  144. break;
  145. }
  146. else {
  147. strcat(weight_matrix_line_buf, weight_matrix_weight_buf);
  148. }
  149. }
  150. fprintf(stdout, "%s\n", weight_matrix_line_buf);
  151. }
  152. }
  153. /*
  154. * Returns a void* that points to the first valid data cell in the
  155. * input data row corresponding to "row_idx".
  156. */
  157. void *get_input_row(unsigned long row_idx)
  158. {
  159. unsigned long i;
  160. void *my_cell = NULL;
  161. my_cell = CELL_INPUT_HANDLES[row_idx];
  162. for (i = 0; i < PADDING_WIDTH; i++)
  163. my_cell += CELL_IN_SIZE;
  164. return (my_cell);
  165. }
  166. /* NEIGHBORHOOD STATISTICS
  167. *
  168. * The following function provide the different neighborhood statistics (interpolators)
  169. * that have been implemented in this software.
  170. *
  171. * Only those cells go into the statistics that are within the circular neighborhood window.
  172. *
  173. * Since the input buffers are padded with NULL data for rows lying to the South or North,
  174. * West or East of the current region, these functions can just blindly read values above and
  175. * below the current position on the W-E axis.
  176. *
  177. * The parameter "col" must be set to actual GRASS region column number on the W-E axis.
  178. *
  179. * "min" and "max" define the smallest and largest values to use for interpolation. Set
  180. * filter_min and filter_max to !=0 to use these for range filtering the data.
  181. *
  182. * The results will be stored in the cell_stats object passed to this function. This object
  183. * must have been properly initialized before passing it to any of the functions below!
  184. */
  185. /*
  186. * The different types of neighborhood statistics required different
  187. * types of information to be collected.
  188. */
  189. void collect_values_unfiltered(double val1, double val2, double min,
  190. double max, stats_struct * stats)
  191. {
  192. stats->values[stats->num_values] = val1;
  193. stats->certainty += val2;
  194. stats->num_values++;
  195. }
  196. void collect_values_filtered(double val1, double val2, double min, double max,
  197. stats_struct * stats)
  198. {
  199. if (val1 >= min && val1 <= max) {
  200. collect_values_unfiltered(val1, val2, min, max, stats);
  201. }
  202. }
  203. void collect_values_and_weights_unfiltered(double val1, double val2,
  204. double min, double max,
  205. stats_struct * stats)
  206. {
  207. stats->values[stats->num_values] = val1;
  208. stats->weights[stats->num_values] = val2;
  209. stats->certainty += val2;
  210. stats->num_values++;
  211. }
  212. void collect_values_and_weights_filtered(double val1, double val2, double min,
  213. double max, stats_struct * stats)
  214. {
  215. if (val1 >= min && val1 <= max) {
  216. collect_values_and_weights_unfiltered(val1, val2, min, max, stats);
  217. }
  218. }
  219. void collect_values_and_frequencies_unfiltered(double val1, double val2,
  220. double min, double max,
  221. stats_struct * stats)
  222. {
  223. unsigned long i;
  224. stats->certainty += val2;
  225. /* extreme case: no values collected yet */
  226. if (stats->num_values == 0) {
  227. stats->values[0] = val1;
  228. stats->frequencies[0] = 1;
  229. stats->num_values++;
  230. return;
  231. }
  232. /* at least one value already collected */
  233. for (i = 0; i < stats->num_values; i++) {
  234. /* does this value already exist in the stats object? */
  235. if (stats->values[i] == val1) {
  236. /* yes: increase its counter and abort search */
  237. stats->frequencies[i]++;
  238. stats->values[stats->num_values] = val1;
  239. stats->num_values++;
  240. return;
  241. }
  242. }
  243. /* no: first occurrence of this value: store as new entry */
  244. stats->values[i] = val1;
  245. stats->frequencies[i] = 1;
  246. stats->num_values++;
  247. }
  248. void collect_values_and_frequencies_filtered(double val1, double val2,
  249. double min, double max,
  250. stats_struct * stats)
  251. {
  252. if (val1 >= min && val1 <= max) {
  253. collect_values_and_frequencies_unfiltered(val1, val2, min, max,
  254. stats);
  255. }
  256. }
  257. /*
  258. * Simple double comparison function for use by qsort().
  259. * This is needed for calculating median statistics.
  260. */
  261. int compare_dbl(const void *val1, const void *val2)
  262. {
  263. if (*(double *)val1 == *(double *)val2)
  264. return 0;
  265. if (*(double *)val1 < *(double *)val2)
  266. return -1;
  267. return 1;
  268. }
  269. /*
  270. * Collecting the cell data from the neighborhood is the same
  271. * basic loop for every type of statistics: collect only non-null
  272. * cells, and collect only within the neighborhood mask.
  273. */
  274. void read_neighborhood(unsigned long row_index, unsigned long col,
  275. double min, double max, int preserve,
  276. stats_struct * stats)
  277. {
  278. unsigned long i, j;
  279. void *cell;
  280. double cell_value;
  281. stats->overwrite = 0;
  282. if (preserve == TRUE) {
  283. cell = CELL_INPUT_HANDLES[row_index];
  284. cell += CELL_IN_SIZE * col;
  285. cell += CELL_IN_SIZE * ((DATA_WIDTH - 1) / 2);
  286. if (!IS_NULL(cell)) {
  287. stats->overwrite = 1;
  288. *stats->overwrite_value =
  289. (double)Rast_get_d_value(cell, IN_TYPE);
  290. return;
  291. }
  292. }
  293. /* read data */
  294. unsigned long row_position = row_index - PADDING_HEIGHT;
  295. stats->num_values = 0;
  296. stats->certainty = 0.0;
  297. for (i = 0; i < DATA_HEIGHT; i++) {
  298. cell = CELL_INPUT_HANDLES[i + row_position];
  299. cell += CELL_IN_SIZE * col;
  300. for (j = 0; j < DATA_WIDTH; j++) {
  301. /* read cell from input buffer */
  302. if (!IS_NULL(cell)) {
  303. /* only add non-null cells to stats */
  304. cell_value = (double)Rast_get_d_value(cell, IN_TYPE);
  305. /* only add if within neighborhood */
  306. if (WEIGHTS[i][j] != -1.0) {
  307. /* get data needed for chosen statistic */
  308. COLLECT_DATA(cell_value, WEIGHTS[i][j], min, max,
  309. stats);
  310. }
  311. }
  312. /* go to next cell on current row */
  313. cell += CELL_IN_SIZE;
  314. }
  315. }
  316. }
  317. /*
  318. * NEIGHBORHOOD STATISTICS FUNCTION WMEAN
  319. * Spatially weighted mean.
  320. *
  321. * The cell values are multiplied by their spatial weights before they are stored.
  322. */
  323. void get_statistics_wmean(unsigned long row_index, unsigned long col,
  324. double min, double max, int preserve,
  325. stats_struct * stats)
  326. {
  327. unsigned long i;
  328. double total;
  329. double total_weight;
  330. read_neighborhood(row_index, col, min, max, preserve, stats);
  331. if (stats->overwrite)
  332. return;
  333. /* compute weighted average of all valid input cells */
  334. total = 0;
  335. total_weight = 0;
  336. for (i = 0; i < stats->num_values; i++) {
  337. total += stats->values[i] * stats->weights[i];
  338. total_weight += stats->weights[i];
  339. }
  340. stats->result = total / total_weight;
  341. }
  342. /*
  343. * NEIGHBORHOOD STATISTICS FUNCTION MEAN
  344. * Simple, unweighted mean.
  345. */
  346. void get_statistics_mean(unsigned long row_index, unsigned long col,
  347. double min, double max, int preserve,
  348. stats_struct * stats)
  349. {
  350. unsigned long i;
  351. double total;
  352. read_neighborhood(row_index, col, min, max, preserve, stats);
  353. if (stats->overwrite)
  354. return;
  355. /* compute total of all valid input cells */
  356. total = 0;
  357. for (i = 0; i < stats->num_values; i++) {
  358. total += stats->values[i];
  359. }
  360. stats->result = total / ((double)stats->num_values);
  361. }
  362. /*
  363. * NEIGHBORHOOD STATISTICS FUNCTION MEDIAN
  364. * Simple, unweighted median. For an even number of data points, the median is the
  365. * average of the two central elements in the sorted data list.
  366. */
  367. void get_statistics_median(unsigned long row_index, unsigned long col,
  368. double min, double max, int preserve,
  369. stats_struct * stats)
  370. {
  371. read_neighborhood(row_index, col, min, max, preserve, stats);
  372. if (stats->overwrite)
  373. return;
  374. /* sort list of values */
  375. qsort(&stats->values[0], stats->num_values, sizeof(double), &compare_dbl);
  376. if (stats->num_values % 2 == 0.0) {
  377. /* even number of elements: result is average of the two central values */
  378. stats->result =
  379. (stats->values[stats->num_values / 2 - 1] +
  380. stats->values[(stats->num_values / 2)]) / 2.0;
  381. }
  382. else {
  383. /* odd number of elements: result is the central element */
  384. stats->result = stats->values[(stats->num_values / 2)];
  385. }
  386. }
  387. /*
  388. * NEIGHBORHOOD STATISTICS FUNCTION MODE
  389. * Simple, unweighted mode. Mathematically, the mode is not always unique. If there is more than
  390. * one value with highest frequency, the smallest one is chosen to represent the mode.
  391. */
  392. void get_statistics_mode(unsigned long row_index, unsigned long col,
  393. double min, double max, int preserve,
  394. stats_struct * stats)
  395. {
  396. unsigned long i;
  397. double mode;
  398. unsigned long freq;
  399. read_neighborhood(row_index, col, min, max, preserve, stats);
  400. if (stats->overwrite)
  401. return;
  402. if (stats->num_values < 1)
  403. return;
  404. mode = stats->values[0];
  405. freq = stats->frequencies[0];
  406. for (i = 1; i < stats->num_values; i++) {
  407. if (stats->frequencies[i] > freq) {
  408. mode = stats->values[i];
  409. freq = stats->frequencies[i];
  410. }
  411. }
  412. stats->result = mode;
  413. /* need to initialize, otherwise old values sometimes stay */
  414. for (i = 0; i < WINDOW_WIDTH * WINDOW_HEIGHT; i++)
  415. stats->frequencies[i] = 0;
  416. }
  417. /*
  418. * Initializes handlers to point to corresponding data rows.
  419. */
  420. void init_handles()
  421. {
  422. unsigned long i;
  423. for (i = 0; i < WINDOW_HEIGHT; i++) {
  424. CELL_INPUT_HANDLES[i] = CELL_INPUT[i];
  425. }
  426. }
  427. /*
  428. * Replaces upper-most data row in input buffer with
  429. * a new row from disk.
  430. * Re-shuffles the data row handlers, so that the new row
  431. * becomes the last row in the index and all other rows move
  432. * up one. This procedure is a bit complex, but it is a lot faster
  433. * to move around a few pointers in memory, than to re-read all
  434. * the data rows for the neighborhood every time we go down one
  435. * row in the current region.
  436. */
  437. void advance_one_row(int file_desc, long current_row)
  438. {
  439. unsigned long i, j;
  440. void *cell_input;
  441. static unsigned long replace_row = 0; /* points to the row which will be replaced next */
  442. unsigned long replace_pos = 0;
  443. /* the actual replacement position needs to consider the "no data" padding offset, as well */
  444. replace_pos = replace_row + PADDING_HEIGHT;
  445. /* get address of data row to replace */
  446. cell_input = CELL_INPUT[replace_pos];
  447. for (i = 0; i < PADDING_WIDTH; i++)
  448. cell_input += CELL_IN_SIZE;
  449. /* get next row from disk */
  450. Rast_get_row(file_desc, cell_input, current_row + DATA_HEIGHT, IN_TYPE);
  451. /* re-assign all row handlers below current replacement position */
  452. j = PADDING_HEIGHT;
  453. for (i = 0; i < DATA_HEIGHT - (replace_row + 1); i++) {
  454. CELL_INPUT_HANDLES[j] = CELL_INPUT[replace_pos + 1 + i];
  455. j++;
  456. }
  457. /* re-assign all row handlers up to and including replacement position */
  458. for (i = 0; i <= replace_row; i++) {
  459. CELL_INPUT_HANDLES[j] = CELL_INPUT[PADDING_HEIGHT + i];
  460. j++;
  461. }
  462. replace_row++;
  463. if (replace_row > (DATA_HEIGHT - 1)) {
  464. /* start over once end of data area has been reached */
  465. replace_row = 0;
  466. }
  467. }
  468. /*
  469. * Interpolates one row of input data, stores result in CELL_OUTPUT (global var)
  470. */
  471. void interpolate_row(unsigned long row_index, unsigned long cols,
  472. double min, double max, int preserve,
  473. unsigned long min_cells,
  474. stats_struct * stats, int write_err)
  475. {
  476. unsigned long j;
  477. void *cell_output;
  478. FCELL *err_output;
  479. cell_output = CELL_OUTPUT;
  480. err_output = ERR_OUTPUT;
  481. for (j = 0; j < cols; j++) {
  482. /* get neighborhood statistics */
  483. GET_STATS(row_index, j, min, max, preserve, stats);
  484. /* original value is preserved */
  485. if (stats->overwrite) {
  486. WRITE_DOUBLE_VAL(cell_output, *stats->overwrite_value);
  487. /* write error/uncertainty output map? */
  488. if (write_err) {
  489. Rast_set_f_value(err_output, 0,
  490. FCELL_TYPE);
  491. }
  492. }
  493. /* enough reachable cells in input map? */
  494. else if (stats->num_values < min_cells) {
  495. SET_NULL(cell_output, 1);
  496. if (write_err)
  497. Rast_set_f_null_value(err_output, 1);
  498. }
  499. else {
  500. /* write interpolation result into output map */
  501. WRITE_DOUBLE_VAL(cell_output, stats->result);
  502. /* write error/uncertainty output map? */
  503. if (write_err) {
  504. Rast_set_f_value(err_output,
  505. (FCELL) 1.0 -
  506. (stats->certainty / SUM_WEIGHTS),
  507. FCELL_TYPE);
  508. }
  509. }
  510. /* advance cell pointers by one cell size */
  511. cell_output += CELL_OUT_SIZE;
  512. err_output++;
  513. }
  514. }
  515. /*
  516. * Pre-computes the matrix of spatial weights.
  517. * For operation mode "wmean" (spatially weighted mean), "constant" is passed as "0"
  518. * and distance-dependent weights are calculated. For all other modes, "constant" is
  519. * passed as "1" and all cells within the circular neighborhood will be set to "1.0".
  520. * In both cases, all cells outside the neighborhood will be set to "-1.0".
  521. */
  522. void build_weights_matrix(double radius, double power, double res_x,
  523. double res_y, int constant, int use_map_units)
  524. {
  525. unsigned long i, j;
  526. double p1_x, p1_y, p2_x, p2_y, A, B, C, W;
  527. double tolerance;
  528. /* alloc enough mem for weights matrix */
  529. WEIGHTS = G_malloc(sizeof(double *) * DATA_HEIGHT);
  530. for (i = 0; i < DATA_HEIGHT; i++) {
  531. WEIGHTS[i] = G_malloc(sizeof(double) * DATA_WIDTH);
  532. }
  533. /* center of the neighborhood window in real map units */
  534. p1_x = (DATA_WIDTH / 2 * res_x) + (res_x / 2.0);
  535. p1_y = (DATA_HEIGHT / 2 * res_y) + (res_y / 2.0);
  536. /* tolerance for including half cells in the neighborhood */
  537. tolerance = (sqrt(pow(res_x, 2) + pow(res_y, 2))) / 2;
  538. /* 1st pass: get largest possible weight for normalization */
  539. double max = -1.0;
  540. for (i = 0; i < DATA_HEIGHT; i++) {
  541. for (j = 0; j < DATA_WIDTH; j++) {
  542. p2_x = (j * res_x) + (res_x / 2.0);
  543. p2_y = (i * res_y) + (res_y / 2.0);
  544. A = fabs(p2_x - p1_x);
  545. B = fabs(p2_y - p1_y);
  546. C = sqrt(pow(A, 2) + pow(B, 2));
  547. if (use_map_units) {
  548. if (C > radius + tolerance) {
  549. WEIGHTS[i][j] = -1.0;
  550. }
  551. else {
  552. WEIGHTS[i][j] = C;
  553. }
  554. }
  555. else {
  556. WEIGHTS[i][j] = C;
  557. }
  558. if (WEIGHTS[i][j] > max) {
  559. /* update max value */
  560. max = WEIGHTS[i][j];
  561. }
  562. }
  563. }
  564. /* Build the weights matrix */
  565. SUM_WEIGHTS = 0.0;
  566. for (i = 0; i < DATA_HEIGHT; i++) {
  567. for (j = 0; j < DATA_WIDTH; j++) {
  568. /* Assign neighborhood coordinates with 0/0
  569. at the top left of the cell neighborhood matrix. */
  570. p2_x = (j * res_x) + (res_x / 2.0);
  571. p2_y = (i * res_y) + (res_y / 2.0);
  572. /* get distance from window center */
  573. A = fabs(p2_x - p1_x);
  574. B = fabs(p2_y - p1_y);
  575. C = sqrt(pow(A, 2) + pow(B, 2));
  576. if (constant) {
  577. W = 1.0;
  578. }
  579. else {
  580. W = ((pow(1 - (C / max), power)));
  581. }
  582. /* exclude neighborhood locations that are farther
  583. from the center than the user-defined distance
  584. plus a tolerance of half the current region's
  585. cell diagonal */
  586. if (use_map_units) {
  587. if (C > radius + tolerance) {
  588. WEIGHTS[i][j] = -1.0;
  589. }
  590. else {
  591. WEIGHTS[i][j] = W;
  592. WEIGHTS[DATA_HEIGHT / 2][DATA_WIDTH / 2] = 0.0; /* safeguard against total weight growing by center cell weight (InF) */
  593. SUM_WEIGHTS += WEIGHTS[i][j];
  594. }
  595. }
  596. else {
  597. WEIGHTS[i][j] = W;
  598. WEIGHTS[DATA_HEIGHT / 2][DATA_WIDTH / 2] = 0.0; /* safeguard against total weight growing by center cell weight (InF) */
  599. SUM_WEIGHTS += WEIGHTS[i][j];
  600. }
  601. }
  602. }
  603. /* weight of center cell is always = 1 */
  604. WEIGHTS[DATA_HEIGHT / 2][DATA_WIDTH / 2] = 1.0;
  605. }
  606. /*
  607. *
  608. * MAIN FUNCTION
  609. *
  610. */
  611. int main(int argc, char *argv[])
  612. {
  613. /* processing time keepers */
  614. time_t start, finish;
  615. /* GRASS region properties */
  616. struct Cell_head cellhd, region;
  617. struct Range int_range;
  618. struct FPRange fp_range;
  619. struct History hist;
  620. unsigned long rows = 0;
  621. unsigned long cols = 0;
  622. double res_x, res_y = 0.0;
  623. int projection;
  624. /* GRASS module options */
  625. struct GModule *module;
  626. struct
  627. {
  628. struct Option
  629. *input, *output, *error,
  630. *radius, *mode, *power, *min, *max, *minpts;
  631. struct Flag
  632. *dist_m, *preserve, *print_w, *print_u, *center,
  633. *single_precision;
  634. } parm;
  635. /* program settings */
  636. char *input;
  637. char *output;
  638. const char *mapset;
  639. double radius = 1.0;
  640. unsigned long min_cells = 12;
  641. double power = 2.0;
  642. double min = 0.0;
  643. double max = 0.0;
  644. int filter_min = 0;
  645. int filter_max = 0;
  646. int write_error;
  647. /* file handlers */
  648. void *cell_input;
  649. int in_fd;
  650. int out_fd;
  651. int err_fd;
  652. /* cell statistics object */
  653. stats_struct cell_stats;
  654. /* generic indices, loop counters, etc. */
  655. unsigned long i, j;
  656. long l;
  657. start = time(NULL);
  658. G_gisinit(argv[0]);
  659. module = G_define_module();
  660. G_add_keyword(_("raster"));
  661. G_add_keyword(_("surface"));
  662. G_add_keyword(_("interpolation"));
  663. G_add_keyword(_("IDW"));
  664. G_add_keyword(_("no-data filling"));
  665. module->description =
  666. _("Rapidly fills 'no data' cells (NULLs) of a raster map with interpolated values (IDW).");
  667. /* parameters */
  668. parm.input = G_define_standard_option(G_OPT_R_INPUT);
  669. parm.input->key = "input";
  670. parm.input->required = YES;
  671. parm.input->multiple = NO;
  672. parm.input->description = _("Raster map with data gaps to fill");
  673. parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
  674. parm.output->required = YES;
  675. parm.output->key = "output";
  676. parm.output->description = _("Name of result output map");
  677. parm.error = G_define_standard_option(G_OPT_R_OUTPUT);
  678. parm.error->required = NO;
  679. parm.error->key = "uncertainty";
  680. parm.error->description = _("Name of uncertainty output map");
  681. parm.radius = G_define_option();
  682. parm.radius->key = "distance";
  683. parm.radius->key_desc = "value";
  684. parm.radius->required = YES;
  685. parm.radius->multiple = NO;
  686. parm.radius->type = TYPE_DOUBLE;
  687. parm.radius->description =
  688. _("Distance threshold (default: in cells) for interpolation");
  689. parm.radius->answer = "3";
  690. parm.mode = G_define_option();
  691. parm.mode->key = "mode";
  692. parm.mode->key_desc = "name";
  693. parm.mode->required = YES;
  694. parm.mode->multiple = NO;
  695. parm.mode->type = TYPE_STRING;
  696. parm.mode->description = _("Statistic for interpolated cell values");
  697. parm.mode->options = "wmean,mean,median,mode";
  698. parm.mode->answer = "wmean";
  699. parm.min = G_define_option();
  700. parm.min->key = "minimum";
  701. parm.min->key_desc = "value";
  702. parm.min->required = NO;
  703. parm.min->multiple = NO;
  704. parm.min->type = TYPE_DOUBLE;
  705. parm.min->description =
  706. _("Minimum input data value to include in interpolation");
  707. parm.max = G_define_option();
  708. parm.max->key = "maximum";
  709. parm.max->key_desc = "value";
  710. parm.max->required = NO;
  711. parm.max->multiple = NO;
  712. parm.max->type = TYPE_DOUBLE;
  713. parm.max->description =
  714. _("Maximum input data value to include in interpolation");
  715. parm.power = G_define_option();
  716. parm.power->key = "power";
  717. parm.power->key_desc = "value";
  718. parm.power->required = YES;
  719. parm.power->multiple = NO;
  720. parm.power->type = TYPE_DOUBLE;
  721. parm.power->answer = "2.0";
  722. parm.power->description = _("Power coefficient for IDW interpolation");
  723. parm.minpts = G_define_option();
  724. parm.minpts->key = "cells";
  725. parm.minpts->key_desc = "value";
  726. parm.minpts->required = YES;
  727. parm.minpts->multiple = NO;
  728. parm.minpts->type = TYPE_INTEGER;
  729. parm.minpts->answer = "8";
  730. parm.minpts->description =
  731. _("Minimum number of data cells within search radius");
  732. parm.dist_m = G_define_flag();
  733. parm.dist_m->key = 'm';
  734. parm.dist_m->description =
  735. _("Interpret distance as map units, not number of cells");
  736. parm.preserve = G_define_flag();
  737. parm.preserve->key = 'k';
  738. parm.preserve->label = _("Keep (preserve) original cell values");
  739. parm.preserve->description =
  740. _("By default original values are smoothed");
  741. parm.print_w = G_define_flag();
  742. parm.print_w->key = 'w';
  743. parm.print_w->description = _("Just print the spatial weights matrix");
  744. parm.print_u = G_define_flag();
  745. parm.print_u->key = 'u';
  746. parm.print_u->description = _("Just print estimated memory usage");
  747. parm.single_precision = G_define_flag();
  748. parm.single_precision->key = 's';
  749. parm.single_precision->description =
  750. _("Single precision floating point output");
  751. if (G_parser(argc, argv))
  752. exit(EXIT_FAILURE);
  753. input = parm.input->answer;
  754. output = parm.output->answer;
  755. /* get setting of current GRASS region */
  756. G_get_window(&region);
  757. projection = region.proj;
  758. if (projection == PROJECTION_LL && parm.dist_m->answer) {
  759. G_warning(_("You are working with lat/lon data."));
  760. G_warning(_("This module uses a straight-line distance metric."));
  761. G_warning(_("Expect inaccuracies."));
  762. }
  763. rows = (unsigned long)region.rows;
  764. cols = (unsigned long)region.cols;
  765. res_x = (double)region.ew_res;
  766. res_y = (double)region.ns_res;
  767. /* get user parameters */
  768. radius = strtod(parm.radius->answer, 0);
  769. power = strtod(parm.power->answer, 0);
  770. min_cells = atol(parm.minpts->answer);
  771. write_error = 0;
  772. if (parm.error->answer) {
  773. write_error = 1;
  774. if (!strcmp(parm.error->answer, parm.output->answer)) {
  775. G_fatal_error(_("Result map name cannot be identical with uncertainty map name."));
  776. }
  777. }
  778. /* validate user parameters */
  779. double max_dist = 0.0;
  780. if (parm.dist_m->answer) {
  781. if (radius < 0) {
  782. G_fatal_error(_("Maximum distance must be larger than zero."));
  783. }
  784. if (res_x < res_y) {
  785. if (radius < res_x)
  786. G_fatal_error(_("Maximum distance must be at least '%.6f' (W-E resolution)."),
  787. res_x);
  788. }
  789. if (res_y < res_x) {
  790. if (radius < res_y)
  791. G_fatal_error(_("Maximum distance must be at least '%.6f' (S-N resolution)."),
  792. res_y);
  793. }
  794. if (res_y == res_x) {
  795. if (radius < res_y)
  796. G_fatal_error(_("Maximum distance must be at least '%.6f' (W-E and S-N resolution)."),
  797. res_y);
  798. }
  799. max_dist = sqrt(pow((cols * res_x), 2) + pow((rows * res_y), 2));
  800. if (radius > max_dist) {
  801. G_warning(_("Maximum distance too large. Adjusted to '%.6f' (diagonal of current region)."),
  802. max_dist);
  803. radius = max_dist;
  804. }
  805. }
  806. else {
  807. unsigned long radius_i = (unsigned long)radius;
  808. radius = (double)radius_i; //truncate to whole cell number
  809. if (radius < 1) {
  810. G_fatal_error(_("Maximum distance must be at least one cell."));
  811. }
  812. unsigned long max_dist_i =
  813. (unsigned long)(sqrt(pow((cols), 2) + pow((rows), 2)));
  814. max_dist = (double)max_dist_i;
  815. if (radius > max_dist) {
  816. G_warning(_("Maximum distance too large. Adjusted to '%lu' cells (diagonal of current region)."),
  817. max_dist_i);
  818. radius = (double)max_dist_i;
  819. }
  820. }
  821. if (min_cells < 1) {
  822. G_fatal_error(_("Minimum number of cells must be at least '1'."));
  823. }
  824. if (min_cells > ((DATA_WIDTH * DATA_HEIGHT) - 1)) {
  825. G_fatal_error(_("Specified minimum number of cells unreachable with current settings."));
  826. }
  827. if (filter_min != 0 && filter_max != 0) {
  828. if (min >= max) {
  829. G_fatal_error(_("Value for 'minimum' must be smaller than value for 'maximum'."));
  830. }
  831. }
  832. if (parm.power->answer && strcmp(parm.mode->answer, "wmean")) {
  833. G_warning(_("The 'power' option has no effect in any mode other than 'wmean'."));
  834. parm.power->answer = 0;
  835. }
  836. /* rounded dimensions of weight matrix (in map cells) */
  837. if (parm.dist_m->answer) {
  838. DATA_WIDTH = ((unsigned long)ceil(radius / res_x)) * 2 + 1;
  839. DATA_HEIGHT = ((unsigned long)ceil(radius / res_y)) * 2 + 1;
  840. if ((!parm.print_w->answer) &&
  841. (fmod(radius, res_x) != 0 || fmod(radius, res_y) != 0)) {
  842. G_warning(_("The specified maximum distance cannot be resolved to whole cells\n at the current resolution settings."));
  843. }
  844. }
  845. else {
  846. DATA_WIDTH = (unsigned long)radius *2 + 1;
  847. DATA_HEIGHT = (unsigned long)radius *2 + 1;
  848. }
  849. PADDING_WIDTH = (DATA_WIDTH - 1) / 2;
  850. PADDING_HEIGHT = (DATA_HEIGHT - 1) / 2;
  851. WINDOW_WIDTH = (PADDING_WIDTH * 2) + DATA_WIDTH;
  852. WINDOW_HEIGHT = (PADDING_HEIGHT * 2) + DATA_HEIGHT;
  853. G_message(_("W-E size of neighborhood is %lu cells."), DATA_WIDTH);
  854. G_message(_("S-N size of neighborhood is %lu cells."), DATA_HEIGHT);
  855. if (DATA_WIDTH < 3 || DATA_HEIGHT < 3) {
  856. G_fatal_error(_("Neighborhood cannot be smaller than 3 cells in X or Y direction."));
  857. }
  858. if (parm.print_w->answer) {
  859. if (!strcmp(parm.mode->answer, "wmean")) {
  860. build_weights_matrix(radius, power, res_x, res_y, 0,
  861. parm.dist_m->answer);
  862. }
  863. if (!strcmp(parm.mode->answer, "mean")) {
  864. build_weights_matrix(radius, power, res_x, res_y, 1,
  865. parm.dist_m->answer);
  866. }
  867. if (!strcmp(parm.mode->answer, "median")) {
  868. build_weights_matrix(radius, power, res_x, res_y, 1,
  869. parm.dist_m->answer);
  870. }
  871. if (!strcmp(parm.mode->answer, "mode")) {
  872. build_weights_matrix(radius, power, res_x, res_y, 1,
  873. parm.dist_m->answer);
  874. }
  875. print_weights_matrix(DATA_HEIGHT, DATA_WIDTH);
  876. /* continue only if "-u" flag has also been given */
  877. if (!parm.print_u->answer)
  878. exit(0);
  879. }
  880. /* open raster input map and get its storage type */
  881. mapset = G_find_raster(input, "");
  882. if (!mapset)
  883. G_fatal_error(_("Raster map <%s> not found"), input);
  884. Rast_get_cellhd(input, mapset, &cellhd);
  885. in_fd = Rast_open_old(input, mapset);
  886. IN_TYPE = Rast_get_map_type(in_fd);
  887. /* minimum and maximum values for interpolating range */
  888. if (IN_TYPE == CELL_TYPE) {
  889. Rast_read_range(input, mapset, &int_range);
  890. min = (double)int_range.min;
  891. max = (double)int_range.max;
  892. }
  893. else {
  894. Rast_read_fp_range(input, mapset, &fp_range);
  895. min = (double)fp_range.min;
  896. max = (double)fp_range.max;
  897. }
  898. if (parm.min->answer) {
  899. min = strtod(parm.min->answer, 0);
  900. filter_min = 1;
  901. }
  902. if (parm.max->answer) {
  903. max = strtod(parm.max->answer, 0);
  904. filter_max = 1;
  905. }
  906. G_message(_("Input data range is %f to %f.\n"), min, max);
  907. /* determine input and output data types, advise user */
  908. OUT_TYPE = IN_TYPE;
  909. if (IN_TYPE == DCELL_TYPE) {
  910. if (parm.single_precision->answer) {
  911. OUT_TYPE = FCELL_TYPE;
  912. }
  913. else {
  914. OUT_TYPE = DCELL_TYPE;
  915. }
  916. }
  917. if (IN_TYPE == CELL_TYPE) {
  918. if ((!strcmp(parm.mode->answer, "wmean")) ||
  919. (!strcmp(parm.mode->answer, "mean"))
  920. || (!strcmp(parm.mode->answer, "median"))) {
  921. G_warning(_("Input data type is integer but interpolation mode is '%s'."),
  922. parm.mode->answer);
  923. if (parm.single_precision->answer) {
  924. OUT_TYPE = FCELL_TYPE;
  925. G_warning(_("Output type changed to floating point (single)."));
  926. }
  927. else {
  928. OUT_TYPE = DCELL_TYPE;
  929. G_warning(_("Output type changed to floating point (double)."));
  930. }
  931. }
  932. else {
  933. if (parm.single_precision->answer) {
  934. G_warning(_("Ignoring '%c' flag. Output data type will be integer."),
  935. parm.single_precision->key);
  936. }
  937. }
  938. }
  939. char *data_type_string_in;
  940. char *data_type_string_out;
  941. if (IN_TYPE == CELL_TYPE) {
  942. data_type_string_in = "integer";
  943. }
  944. else if (IN_TYPE == FCELL_TYPE) {
  945. data_type_string_in = "single";
  946. }
  947. else if (IN_TYPE == DCELL_TYPE) {
  948. data_type_string_in = "double";
  949. }
  950. if (OUT_TYPE == CELL_TYPE) {
  951. data_type_string_out = "integer";
  952. }
  953. else if (OUT_TYPE == FCELL_TYPE) {
  954. data_type_string_out = "single";
  955. }
  956. else if (OUT_TYPE == DCELL_TYPE) {
  957. data_type_string_out = "double";
  958. }
  959. /* initialize data type dependent cell handling functions */
  960. init_cell_funcs();
  961. G_message(_("Input data type is '%s' (%i bytes) and output data type is '%s' (%i bytes)."),
  962. data_type_string_in, CELL_IN_SIZE, data_type_string_out,
  963. CELL_OUT_SIZE);
  964. /* just print projected mem usage if user wants it so */
  965. G_message("Minimal estimated memory usage is %.3f MB.",
  966. ((double)estimate_mem_needed(cols, parm.mode->answer)) / 1024 /
  967. 1024);
  968. if (parm.print_u->answer) {
  969. exit(0);
  970. }
  971. /* Allocate enough memory to read n="distance"x2+1 rows of input map data,
  972. * plus a buffer of "distance" size above and below the actual data
  973. * rows, and to the right and left.
  974. * The buffer will be filled with "no data" cells and has the
  975. * effect that we can later read data anywhere within the search
  976. * neighborhood, without having to worry about alignment problems.
  977. * */
  978. CELL_INPUT = G_malloc(CELL_IN_PTR_SIZE * WINDOW_HEIGHT);
  979. for (i = 0; i < WINDOW_HEIGHT; i++) {
  980. CELL_INPUT[i] = G_malloc(CELL_IN_SIZE * (cols + (PADDING_WIDTH * 2)));
  981. }
  982. for (i = 0; i < WINDOW_HEIGHT; i++) {
  983. Rast_set_null_value(CELL_INPUT[i], cols + (PADDING_WIDTH * 2),
  984. IN_TYPE);
  985. }
  986. /*
  987. * Allocate array of raster row data handlers.
  988. * When reading rows from the input data buffer, we can use these
  989. * handlers instead of the original data pointers. That way, we
  990. * only need to read one new row of data from the disk each time
  991. * the neighborhood advances down one row in the region. Then, we
  992. * re-shuffle the row handlers, so that the first handler always
  993. * points to the first row of the neighborhood data, and the following
  994. * ones to the subsequent rows.
  995. * This should save a lot of disk access time.
  996. */
  997. CELL_INPUT_HANDLES = G_malloc(CELL_IN_PTR_SIZE * WINDOW_HEIGHT);
  998. /* create statistics object */
  999. cell_stats.values =
  1000. G_malloc(sizeof(double) * WINDOW_WIDTH * WINDOW_HEIGHT);
  1001. cell_stats.weights =
  1002. G_malloc(sizeof(double) * WINDOW_WIDTH * WINDOW_HEIGHT);
  1003. cell_stats.frequencies =
  1004. G_malloc(sizeof(unsigned long) * WINDOW_WIDTH * WINDOW_HEIGHT);
  1005. cell_stats.overwrite_value = G_malloc(sizeof(double));
  1006. cell_stats.overwrite = 0;
  1007. /* set statistics functions according to user option setting */
  1008. if (!strcmp(parm.mode->answer, "wmean")) {
  1009. build_weights_matrix(radius, power, res_x, res_y, 0,
  1010. parm.dist_m->answer);
  1011. GET_STATS = &get_statistics_wmean;
  1012. if (filter_min == 1 || filter_max == 1) {
  1013. COLLECT_DATA = &collect_values_and_weights_filtered;
  1014. }
  1015. else {
  1016. COLLECT_DATA = &collect_values_and_weights_unfiltered;
  1017. }
  1018. }
  1019. if (!strcmp(parm.mode->answer, "mean")) {
  1020. build_weights_matrix(radius, power, res_x, res_y, 1,
  1021. parm.dist_m->answer);
  1022. GET_STATS = &get_statistics_mean;
  1023. if (filter_min == 1 || filter_max == 1) {
  1024. COLLECT_DATA = &collect_values_filtered;
  1025. }
  1026. else {
  1027. COLLECT_DATA = &collect_values_unfiltered;
  1028. }
  1029. }
  1030. if (!strcmp(parm.mode->answer, "median")) {
  1031. build_weights_matrix(radius, power, res_x, res_y, 1,
  1032. parm.dist_m->answer);
  1033. GET_STATS = &get_statistics_median;
  1034. if (filter_min == 1 || filter_max == 1) {
  1035. COLLECT_DATA = &collect_values_and_frequencies_filtered;
  1036. }
  1037. else {
  1038. COLLECT_DATA = &collect_values_and_frequencies_unfiltered;
  1039. }
  1040. }
  1041. if (!strcmp(parm.mode->answer, "mode")) {
  1042. build_weights_matrix(radius, power, res_x, res_y, 1,
  1043. parm.dist_m->answer);
  1044. GET_STATS = &get_statistics_mode;
  1045. if (filter_min == 1 || filter_max == 1) {
  1046. COLLECT_DATA = &collect_values_and_frequencies_filtered;
  1047. }
  1048. else {
  1049. COLLECT_DATA = &collect_values_and_frequencies_unfiltered;
  1050. }
  1051. }
  1052. /*
  1053. *
  1054. * MAIN LOOP
  1055. *
  1056. */
  1057. /* Open output map with right data type */
  1058. out_fd = Rast_open_new(output, OUT_TYPE);
  1059. if (out_fd < 0) {
  1060. G_fatal_error("Cannot open output map.");
  1061. exit(EXIT_FAILURE);
  1062. }
  1063. /* Reserve memory for one output row buffer */
  1064. CELL_OUTPUT = Rast_allocate_buf(OUT_TYPE);
  1065. /* initialize output row */
  1066. SET_NULL(CELL_OUTPUT, cols);
  1067. /* produce uncertainty output map? */
  1068. if (parm.error->answer) {
  1069. /* Open output map with right data type */
  1070. err_fd = Rast_open_new(parm.error->answer, FCELL_TYPE);
  1071. if (err_fd < 0) {
  1072. G_fatal_error("Cannot open uncertainty output map.");
  1073. exit(EXIT_FAILURE);
  1074. }
  1075. ERR_OUTPUT = Rast_allocate_buf(FCELL_TYPE);
  1076. /* initialize output row */
  1077. Rast_set_f_null_value(ERR_OUTPUT, cols);
  1078. }
  1079. /* row indices to handle input data buffer */
  1080. unsigned long center_row = (PADDING_HEIGHT * 2);
  1081. unsigned long row_idx = 0;
  1082. /* Visit every row in the input dataset.
  1083. * To avoid making this code complex and having a lot of
  1084. * if/then boundary checks while looping, processing has
  1085. * been split into upper edge, main part and lower edge.
  1086. * The upper and lower edge comprise the diameter of the
  1087. * neighborhood window.
  1088. * */
  1089. G_message(_("Interpolating:"));
  1090. unsigned long current_row = 0;
  1091. /* first part: upper edge of region */
  1092. init_handles();
  1093. for (i = 0; i < DATA_HEIGHT; i++) {
  1094. cell_input = get_input_row(PADDING_HEIGHT + i);
  1095. cell_input = CELL_INPUT[PADDING_HEIGHT + i];
  1096. for (j = 0; j < PADDING_WIDTH; j++) {
  1097. cell_input += CELL_IN_SIZE;
  1098. }
  1099. Rast_get_row(in_fd, cell_input, i, IN_TYPE);
  1100. }
  1101. for (i = 0; i <= PADDING_HEIGHT; i++) {
  1102. row_idx = PADDING_HEIGHT + i;
  1103. interpolate_row(row_idx, cols, min, max, parm.preserve->answer,
  1104. min_cells, &cell_stats, write_error);
  1105. /* write output row buffer to disk */
  1106. Rast_put_row(out_fd, CELL_OUTPUT, OUT_TYPE);
  1107. if (parm.error->answer)
  1108. Rast_put_row(err_fd, ERR_OUTPUT, FCELL_TYPE);
  1109. G_percent(current_row + 1, rows, 2);
  1110. current_row++;
  1111. }
  1112. /* second part: region between upper and lower edge */
  1113. for (i = 0; i < rows - (DATA_HEIGHT + 1); i++) {
  1114. l = i;
  1115. advance_one_row(in_fd, l);
  1116. l++;
  1117. row_idx = center_row;
  1118. interpolate_row(row_idx, cols, min, max, parm.preserve->answer,
  1119. min_cells, &cell_stats, write_error);
  1120. /* write output row buffer to disk */
  1121. Rast_put_row(out_fd, CELL_OUTPUT, OUT_TYPE);
  1122. if (parm.error->answer)
  1123. Rast_put_row(err_fd, ERR_OUTPUT, FCELL_TYPE);
  1124. G_percent(current_row + 1, rows, 2);
  1125. current_row++;
  1126. }
  1127. /* third part: lower edge */
  1128. init_handles();
  1129. for (i = rows - DATA_HEIGHT; i < rows; i++) {
  1130. row_idx = (DATA_HEIGHT + PADDING_HEIGHT) - (rows - i);
  1131. cell_input = get_input_row(row_idx);
  1132. Rast_get_row(in_fd, cell_input, i, IN_TYPE);
  1133. }
  1134. for (i = rows - PADDING_HEIGHT - 1; i < rows; i++) {
  1135. row_idx = PADDING_HEIGHT + (DATA_HEIGHT) - (rows - i);
  1136. interpolate_row(row_idx, cols, min, max, parm.preserve->answer,
  1137. min_cells, &cell_stats, write_error);
  1138. /* write output row buffer to disk */
  1139. Rast_put_row(out_fd, CELL_OUTPUT, OUT_TYPE);
  1140. if (parm.error->answer)
  1141. Rast_put_row(err_fd, ERR_OUTPUT, FCELL_TYPE);
  1142. G_percent(current_row + 1, rows, 2);
  1143. current_row++;
  1144. }
  1145. /* close all maps */
  1146. Rast_close(out_fd);
  1147. Rast_close(in_fd);
  1148. if (parm.error->answer) {
  1149. Rast_close(err_fd);
  1150. }
  1151. /* Free memory */
  1152. for (i = 0; i < DATA_HEIGHT; i++) {
  1153. G_free(WEIGHTS[i]);
  1154. }
  1155. G_free(WEIGHTS);
  1156. if (CELL_INPUT != NULL) {
  1157. for (i = 0; i < DATA_HEIGHT; i++) {
  1158. G_free(CELL_INPUT[i]);
  1159. }
  1160. G_free(CELL_INPUT);
  1161. }
  1162. if (CELL_OUTPUT != NULL)
  1163. G_free(CELL_OUTPUT);
  1164. if (parm.error->answer)
  1165. G_free(ERR_OUTPUT);
  1166. G_free(cell_stats.values);
  1167. G_free(cell_stats.weights);
  1168. G_free(cell_stats.frequencies);
  1169. G_free(cell_stats.overwrite_value);
  1170. /* write metadata into result and error maps */
  1171. Rast_short_history(parm.output->answer, "raster", &hist);
  1172. Rast_put_cell_title(parm.output->answer,
  1173. "Result of interpolation/gap filling");
  1174. if (parm.dist_m->answer) {
  1175. Rast_append_format_history(&hist,
  1176. "Settings: mode=%s, distance (map units)=%.6f, power=%.3f",
  1177. parm.mode->answer, radius, power);
  1178. }
  1179. else {
  1180. Rast_append_format_history(&hist,
  1181. "Settings: mode=%s, distance (cells)=%lu, power=%.3f",
  1182. parm.mode->answer, (unsigned long)radius,
  1183. power);
  1184. }
  1185. Rast_append_format_history(&hist,
  1186. " min=%.3f, max=%.3f, min. points=%lu",
  1187. min, max, min_cells);
  1188. Rast_write_history(parm.output->answer, &hist);
  1189. if (parm.error->answer) {
  1190. Rast_short_history(parm.error->answer, "raster", &hist);
  1191. Rast_put_cell_title(parm.error->answer,
  1192. "Uncertainty of interpolation/gap filling");
  1193. Rast_append_format_history(&hist, "Result map: %s",
  1194. parm.output->answer);
  1195. Rast_append_format_history(&hist,
  1196. "Theoretic range is '0' (lowest) to '1' (highest).");
  1197. Rast_write_history(parm.error->answer, &hist);
  1198. }
  1199. finish = time(NULL);
  1200. double ticks = difftime(finish, start);
  1201. int hours = trunc(ticks / 3600);
  1202. ticks = ticks - (hours * 3600);
  1203. int minutes = trunc(ticks / 60);
  1204. ticks = ticks - (minutes * 60);
  1205. int seconds = trunc(ticks);
  1206. /* DONE */
  1207. G_done_msg(_("Processing time was %ih%im%is."), hours, minutes, seconds);
  1208. return (EXIT_SUCCESS);
  1209. }