main.c 46 KB

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