main.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. /**********************************************************************
  2. *
  3. * MODULE: r.resamp.bspline
  4. *
  5. * AUTHOR(S): Markus Metz
  6. *
  7. * PURPOSE: Spline Interpolation
  8. *
  9. * COPYRIGHT: (C) 2010, 2012 by GRASS development team
  10. *
  11. * This program is free software under the GNU General
  12. * Public License (>=v2). Read the file COPYING that
  13. * comes with GRASS for details.
  14. *
  15. **********************************************************************/
  16. /* INCLUDES */
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <fcntl.h>
  22. #include <math.h>
  23. #include "bspline.h"
  24. #define SEGSIZE 64
  25. /*--------------------------------------------------------------------*/
  26. int main(int argc, char *argv[])
  27. {
  28. /* Variable declarations */
  29. int nsply, nsplx, row, col, nrows, ncols, nsplx_adj, nsply_adj;
  30. int nsubregion_col, nsubregion_row, subregion_row, subregion_col;
  31. int subregion = 0, nsubregions = 0;
  32. int last_row, last_column, interp_method; /* booleans */
  33. double lambda, mean;
  34. double N_extension, E_extension, edgeE, edgeN;
  35. double stepN, stepE;
  36. const char *inrast, *outrast;
  37. char title[64];
  38. int dim_vect, nparameters, BW;
  39. double *TN, *Q, *parVect; /* Interpolating and least-square vectors */
  40. double **N, **obsVect; /* Interpolation and least-square matrix */
  41. SEGMENT in_seg, out_seg, mask_seg;
  42. const char *in_file, *out_file, *mask_file;
  43. int in_fd, out_fd, mask_fd;
  44. double seg_size;
  45. int seg_mb, segments_in_memory;
  46. int have_mask;
  47. int inrastfd, outrastfd;
  48. DCELL *drastbuf, dval;
  49. struct History history;
  50. struct Map_info Grid;
  51. struct line_pnts *Points;
  52. struct line_cats *Cats;
  53. int cat = 1;
  54. struct GModule *module;
  55. struct Option *in_opt, *out_opt, *grid_opt, *stepE_opt, *stepN_opt,
  56. *lambda_f_opt, *method_opt, *mask_opt, *memory_opt;
  57. struct Flag *null_flag, *cross_corr_flag;
  58. struct Reg_dimens dims;
  59. struct Cell_head elaboration_reg, src_reg, dest_reg;
  60. struct bound_box general_box, overlap_box, dest_box;
  61. struct bound_box last_overlap_box, last_general_box;
  62. struct Point *observ;
  63. struct Point *observ_marked;
  64. /*----------------------------------------------------------------*/
  65. /* Options declarations */
  66. module = G_define_module();
  67. G_add_keyword(_("raster"));
  68. G_add_keyword(_("surface"));
  69. G_add_keyword(_("resample"));
  70. G_add_keyword(_("interpolation"));
  71. module->description =
  72. _("Performs bilinear or bicubic spline interpolation with Tykhonov regularization.");
  73. in_opt = G_define_standard_option(G_OPT_R_INPUT);
  74. out_opt = G_define_standard_option(G_OPT_R_OUTPUT);
  75. grid_opt = G_define_standard_option(G_OPT_V_OUTPUT);
  76. grid_opt->key = "grid";
  77. grid_opt->description = _("Name for output vector map with interpolation grid");
  78. grid_opt->required = NO;
  79. mask_opt = G_define_standard_option(G_OPT_R_INPUT);
  80. mask_opt->key = "mask";
  81. mask_opt->label = _("Name of raster map to use for masking");
  82. mask_opt->description = _("Only cells that are not NULL and not zero are interpolated");
  83. mask_opt->required = NO;
  84. stepE_opt = G_define_option();
  85. stepE_opt->key = "ew_step";
  86. stepE_opt->type = TYPE_DOUBLE;
  87. stepE_opt->required = NO;
  88. stepE_opt->description =
  89. _("Length of each spline step in the east-west direction. Default: 1.5 * ewres.");
  90. stepE_opt->guisection = _("Settings");
  91. stepN_opt = G_define_option();
  92. stepN_opt->key = "ns_step";
  93. stepN_opt->type = TYPE_DOUBLE;
  94. stepN_opt->required = NO;
  95. stepN_opt->description =
  96. _("Length of each spline step in the north-south direction. Default: 1.5 * nsres.");
  97. stepN_opt->guisection = _("Settings");
  98. method_opt = G_define_standard_option(G_OPT_R_INTERP_TYPE);
  99. method_opt->description = _("Spline interpolation algorithm");
  100. method_opt->options = "bilinear,bicubic";
  101. method_opt->answer = "bicubic";
  102. method_opt->guisection = _("Settings");
  103. G_asprintf((char **) &(method_opt->descriptions),
  104. "bilinear;%s;bicubic;%s",
  105. _("Bilinear interpolation"),
  106. _("Bicubic interpolation"));
  107. lambda_f_opt = G_define_option();
  108. lambda_f_opt->key = "lambda";
  109. lambda_f_opt->type = TYPE_DOUBLE;
  110. lambda_f_opt->required = NO;
  111. lambda_f_opt->description = _("Tykhonov regularization parameter (affects smoothing)");
  112. lambda_f_opt->answer = "0.01";
  113. lambda_f_opt->guisection = _("Settings");
  114. null_flag = G_define_flag();
  115. null_flag->key = 'n';
  116. null_flag->label = _("Only interpolate null cells in input raster map");
  117. null_flag->guisection = _("Settings");
  118. cross_corr_flag = G_define_flag();
  119. cross_corr_flag->key = 'c';
  120. cross_corr_flag->description =
  121. _("Find the best Tykhonov regularizing parameter using a \"leave-one-out\" cross validation method");
  122. memory_opt = G_define_option();
  123. memory_opt->key = "memory";
  124. memory_opt->type = TYPE_INTEGER;
  125. memory_opt->required = NO;
  126. memory_opt->answer = "300";
  127. memory_opt->label = _("Maximum memory to be used (in MB)");
  128. memory_opt->description = _("Cache size for raster rows");
  129. /*----------------------------------------------------------------*/
  130. /* Parsing */
  131. G_gisinit(argv[0]);
  132. if (G_parser(argc, argv))
  133. exit(EXIT_FAILURE);
  134. inrast = in_opt->answer;
  135. outrast = out_opt->answer;
  136. if (!strcmp(method_opt->answer, "bilinear"))
  137. interp_method = P_BILINEAR;
  138. else
  139. interp_method = P_BICUBIC;
  140. lambda = atof(lambda_f_opt->answer);
  141. /* Setting regions and boxes */
  142. G_debug(1, "Interpolation: Setting regions and boxes");
  143. G_get_set_window(&dest_reg);
  144. G_get_set_window(&elaboration_reg);
  145. Vect_region_box(&dest_reg, &dest_box);
  146. Vect_region_box(&elaboration_reg, &overlap_box);
  147. Vect_region_box(&elaboration_reg, &general_box);
  148. nrows = Rast_window_rows();
  149. ncols = Rast_window_cols();
  150. /* get window of input map */
  151. Rast_get_cellhd(in_opt->answer, "", &src_reg);
  152. if (stepE_opt->answer) {
  153. stepE = atof(stepE_opt->answer);
  154. if (stepE <= .0)
  155. G_fatal_error(_("ew_step must be positive"));
  156. }
  157. else
  158. stepE = src_reg.ew_res * 1.5;
  159. if (stepN_opt->answer) {
  160. stepN = atof(stepN_opt->answer);
  161. if (stepN <= .0)
  162. G_fatal_error(_("ns_step must be positive"));
  163. }
  164. else
  165. stepN = src_reg.ns_res * 1.5;
  166. /*------------------------------------------------------------------
  167. | Subdividing and working with tiles:
  168. | Each original region will be divided into several subregions.
  169. | Each one will be overlaped by its neighbouring subregions.
  170. | The overlapping is calculated as a fixed OVERLAP_SIZE times
  171. | the largest spline step plus 2 * orlo
  172. ----------------------------------------------------------------*/
  173. /* Fixing parameters of the elaboration region */
  174. P_zero_dim(&dims); /* Set dim struct to zero */
  175. nsplx_adj = NSPLX_MAX;
  176. nsply_adj = NSPLY_MAX;
  177. if (interp_method == P_BICUBIC) {
  178. nsplx_adj = 100;
  179. nsply_adj = 100;
  180. }
  181. dims.overlap = OVERLAP_SIZE * (stepN > stepE ? stepN : stepE);
  182. P_get_edge(interp_method, &dims, stepE, stepN);
  183. P_set_dim(&dims, stepE, stepN, &nsplx_adj, &nsply_adj);
  184. G_verbose_message(_("spline step in ew direction %g"), stepE);
  185. G_verbose_message(_("spline step in ns direction %g"), stepN);
  186. G_verbose_message(_("adjusted EW splines %d"), nsplx_adj);
  187. G_verbose_message(_("adjusted NS splines %d"), nsply_adj);
  188. /* calculate number of subregions */
  189. edgeE = dims.ew_size - dims.overlap - 2 * dims.edge_v;
  190. edgeN = dims.sn_size - dims.overlap - 2 * dims.edge_h;
  191. N_extension = dest_reg.north - dest_reg.south;
  192. E_extension = dest_reg.east - dest_reg.west;
  193. nsubregion_col = ceil(E_extension / edgeE) + 0.5;
  194. nsubregion_row = ceil(N_extension / edgeN) + 0.5;
  195. if (nsubregion_col < 0)
  196. nsubregion_col = 0;
  197. if (nsubregion_row < 0)
  198. nsubregion_row = 0;
  199. nsubregions = nsubregion_row * nsubregion_col;
  200. G_debug(1, "-------------------------------------");
  201. G_debug(1, "source north %f", src_reg.north);
  202. G_debug(1, "source south %f", src_reg.south);
  203. G_debug(1, "source west %f", src_reg.west);
  204. G_debug(1, "source east %f", src_reg.east);
  205. G_debug(1, "-------------------------------------");
  206. /* adjust source window */
  207. if (1) {
  208. double north = dest_reg.north + 2 * dims.edge_h;
  209. double south = dest_reg.south - 2 * dims.edge_h;
  210. int r0 = (int)(floor(Rast_northing_to_row(north, &src_reg)) - 0.5);
  211. int r1 = (int)(floor(Rast_northing_to_row(south, &src_reg)) + 0.5);
  212. double east = dest_reg.east + 2 * dims.edge_v;
  213. double west = dest_reg.west - 2 * dims.edge_v;
  214. /* NOTE: Rast_easting_to_col() is broken because of G_adjust_easting() */
  215. /*
  216. int c0 = (int)floor(Rast_easting_to_col(east, &src_reg) + 0.5);
  217. int c1 = (int)floor(Rast_easting_to_col(west, &src_reg) + 0.5);
  218. */
  219. int c0 = (int)(floor(((east - src_reg.west) / src_reg.ew_res)) + 0.5);
  220. int c1 = (int)(floor(((west - src_reg.west) / src_reg.ew_res)) - 0.5);
  221. src_reg.north -= src_reg.ns_res * (r0);
  222. src_reg.south -= src_reg.ns_res * (r1 - src_reg.rows);
  223. src_reg.east += src_reg.ew_res * (c0 - src_reg.cols);
  224. src_reg.west += src_reg.ew_res * (c1);
  225. src_reg.rows = r1 - r0;
  226. src_reg.cols = c0 - c1;
  227. }
  228. /* switch to buffered input raster window */
  229. G_set_window(&src_reg);
  230. Rast_set_window(&src_reg);
  231. G_debug(1, "new source north %f", src_reg.north);
  232. G_debug(1, "new source south %f", src_reg.south);
  233. G_debug(1, "new source west %f", src_reg.west);
  234. G_debug(1, "new source east %f", src_reg.east);
  235. G_debug(1, "-------------------------------------");
  236. nrows = Rast_window_rows();
  237. ncols = Rast_window_cols();
  238. G_debug(1, "%d new rows, %d new cols", nrows, ncols);
  239. seg_mb = atoi(memory_opt->answer);
  240. if (seg_mb < 3)
  241. G_fatal_error(_("Memory in MB must be >= 3"));
  242. if (mask_opt->answer || null_flag->answer) {
  243. seg_size = sizeof(double) * 2 + sizeof(char);
  244. }
  245. else {
  246. seg_size = sizeof(double) * 2;
  247. }
  248. seg_size = (seg_size * SEGSIZE * SEGSIZE) / (1 << 20);
  249. segments_in_memory = seg_mb / seg_size + 0.5;
  250. if (segments_in_memory < 1)
  251. segments_in_memory = 1;
  252. in_file = G_tempfile();
  253. in_fd = creat(in_file, 0666);
  254. if (Segment_format(in_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(double)) != 1)
  255. G_fatal_error(_("Can not create temporary file"));
  256. close(in_fd);
  257. in_fd = open(in_file, 2);
  258. if (Segment_init(&in_seg, in_fd, segments_in_memory) != 1)
  259. G_fatal_error(_("Can not initialize temporary file"));
  260. /* read raster input */
  261. inrastfd = Rast_open_old(in_opt->answer, "");
  262. drastbuf = Rast_allocate_buf(DCELL_TYPE);
  263. G_message(_("Loading input raster <%s>"), in_opt->answer);
  264. if (1) {
  265. int got_one = 0;
  266. for (row = 0; row < nrows; row++) {
  267. DCELL dval;
  268. G_percent(row, nrows, 9);
  269. Rast_get_d_row_nomask(inrastfd, drastbuf, row);
  270. for (col = 0; col < ncols; col++) {
  271. dval = drastbuf[col];
  272. if (!Rast_is_d_null_value(&dval)) {
  273. got_one++;
  274. }
  275. }
  276. Segment_put_row(&in_seg, drastbuf, row);
  277. }
  278. if (!got_one)
  279. G_fatal_error(_("Only NULL cells in input raster"));
  280. }
  281. G_percent(row, nrows, 2);
  282. G_free(drastbuf);
  283. Rast_close(inrastfd);
  284. /* switch back to destination = current window */
  285. G_set_window(&dest_reg);
  286. Rast_set_window(&dest_reg);
  287. nrows = Rast_window_rows();
  288. ncols = Rast_window_cols();
  289. G_debug(1, "-------------------------------------");
  290. G_debug(1, "dest north %f", dest_reg.north);
  291. G_debug(1, "dest south %f", dest_reg.south);
  292. G_debug(1, "dest west %f", dest_reg.west);
  293. G_debug(1, "dest east %f", dest_reg.east);
  294. G_debug(1, "-------------------------------------");
  295. /* cross-correlation */
  296. if (cross_corr_flag->answer) {
  297. G_debug(1, "CrossCorrelation()");
  298. if (cross_correlation(&in_seg, &src_reg, stepE, stepN) != TRUE)
  299. G_fatal_error(_("Cross validation didn't finish correctly"));
  300. else {
  301. G_debug(1, "Cross validation finished correctly");
  302. G_done_msg(_("Cross validation finished for ew_step = %f and ns_step = %f"), stepE, stepN);
  303. Segment_release(&in_seg); /* release memory */
  304. close(in_fd);
  305. unlink(in_file);
  306. exit(EXIT_SUCCESS);
  307. }
  308. }
  309. /* Alloc and load masking matrix */
  310. /* encoding: 0 = do not interpolate, 1 = interpolate */
  311. have_mask = mask_opt->answer || null_flag->answer;
  312. if (have_mask) {
  313. int maskfd;
  314. int null_count = 0;
  315. CELL cval;
  316. CELL *maskbuf;
  317. char mask_val;
  318. G_message(_("Mark cells for interpolation"));
  319. /* use destination window */
  320. mask_file = G_tempfile();
  321. mask_fd = creat(mask_file, 0666);
  322. if (Segment_format(mask_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(char)) != 1)
  323. G_fatal_error(_("Can not create temporary file"));
  324. close(mask_fd);
  325. mask_fd = open(mask_file, 2);
  326. if (Segment_init(&mask_seg, mask_fd, segments_in_memory) != 1)
  327. G_fatal_error(_("Can not initialize temporary file"));
  328. if (mask_opt->answer) {
  329. maskfd = Rast_open_old(mask_opt->answer, "");
  330. maskbuf = Rast_allocate_buf(CELL_TYPE);
  331. }
  332. else {
  333. maskfd = -1;
  334. maskbuf = NULL;
  335. }
  336. if (null_flag->answer) {
  337. inrastfd = Rast_open_old(in_opt->answer, "");
  338. drastbuf = Rast_allocate_buf(DCELL_TYPE);
  339. }
  340. else {
  341. inrastfd = -1;
  342. drastbuf = NULL;
  343. }
  344. for (row = 0; row < nrows; row++) {
  345. G_percent(row, nrows, 9);
  346. if (mask_opt->answer)
  347. Rast_get_c_row(maskfd, maskbuf, row);
  348. if (null_flag->answer)
  349. Rast_get_d_row(inrastfd, drastbuf, row);
  350. for (col = 0; col < ncols; col++) {
  351. mask_val = 1;
  352. if (mask_opt->answer) {
  353. cval = maskbuf[col];
  354. if (Rast_is_c_null_value(&cval) || cval == 0)
  355. mask_val = 0;
  356. }
  357. if (null_flag->answer && mask_val == 1) {
  358. dval = drastbuf[col];
  359. if (!Rast_is_d_null_value(&dval))
  360. mask_val = 0;
  361. else
  362. null_count++;
  363. }
  364. Segment_put(&mask_seg, &mask_val, row, col);
  365. }
  366. }
  367. G_percent(row, nrows, 2);
  368. if (null_flag->answer) {
  369. G_free(drastbuf);
  370. Rast_close(inrastfd);
  371. }
  372. if (mask_opt->answer) {
  373. G_free(maskbuf);
  374. Rast_close(maskfd);
  375. }
  376. if (null_flag->answer && null_count == 0 && !mask_opt->answer) {
  377. G_fatal_error(_("No NULL cells found in input raster."));
  378. }
  379. }
  380. out_file = G_tempfile();
  381. out_fd = creat(out_file, 0666);
  382. if (Segment_format(out_fd, nrows, ncols, SEGSIZE, SEGSIZE, sizeof(double)) != 1)
  383. G_fatal_error(_("Can not create temporary file"));
  384. close(out_fd);
  385. out_fd = open(out_file, 2);
  386. if (Segment_init(&out_seg, out_fd, segments_in_memory) != 1)
  387. G_fatal_error(_("Can not initialize temporary file"));
  388. /* initialize output */
  389. G_message(_("Initializing output..."));
  390. drastbuf = Rast_allocate_buf(DCELL_TYPE);
  391. Rast_set_d_null_value(drastbuf, ncols);
  392. for (row = 0; row < nrows; row++) {
  393. G_percent(row, nrows, 9);
  394. Segment_put_row(&out_seg, drastbuf, row);
  395. }
  396. G_percent(row, nrows, 2);
  397. if (grid_opt->answer) {
  398. if (0 > Vect_open_new(&Grid, grid_opt->answer, WITH_Z))
  399. G_fatal_error(_("Unable to create vector map <%s>"),
  400. grid_opt->answer);
  401. Points = Vect_new_line_struct();
  402. Cats = Vect_new_cats_struct();
  403. }
  404. subregion_row = 0;
  405. elaboration_reg.south = dest_reg.north;
  406. last_row = FALSE;
  407. overlap_box.S = dest_box.N;
  408. general_box.S = dest_box.N;
  409. while (last_row == FALSE) { /* For each subregion row */
  410. subregion_row++;
  411. last_overlap_box.S = overlap_box.S;
  412. last_general_box.S = general_box.S;
  413. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  414. GENERAL_ROW);
  415. /* only works if source reg = dest reg with buffer */
  416. /* messing with elaboration region is dangerous... */
  417. /* align_elaboration_box(&elaboration_reg, &src_reg, GENERAL_ROW); */
  418. align_interp_boxes(&general_box, &overlap_box, &dest_reg,
  419. last_general_box, last_overlap_box, GENERAL_ROW);
  420. if (elaboration_reg.north > dest_reg.north) { /* First row */
  421. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  422. FIRST_ROW);
  423. /* align_elaboration_box(&elaboration_reg, &src_reg, GENERAL_ROW); */
  424. align_interp_boxes(&general_box, &overlap_box, &dest_reg,
  425. last_general_box, last_overlap_box, FIRST_ROW);
  426. }
  427. if (elaboration_reg.south <= dest_reg.south) { /* Last row */
  428. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  429. LAST_ROW);
  430. last_row = TRUE;
  431. }
  432. nsply =
  433. ceil((elaboration_reg.north -
  434. elaboration_reg.south) / stepN) + 0.5;
  435. G_debug(1, "Interpolation: nsply = %d", nsply);
  436. elaboration_reg.east = dest_reg.west;
  437. last_column = FALSE;
  438. subregion_col = 0;
  439. overlap_box.E = dest_box.W;
  440. general_box.E = dest_box.W;
  441. while (last_column == FALSE) { /* For each subregion column */
  442. int npoints = 0;
  443. int npoints_marked = 1; /* default: all points in output */
  444. subregion_col++;
  445. subregion++;
  446. if (nsubregions > 1)
  447. G_message(_("subregion %d of %d"), subregion, nsubregions);
  448. last_overlap_box.E = overlap_box.E;
  449. last_general_box.E = general_box.E;
  450. P_set_regions(&elaboration_reg, &general_box, &overlap_box, dims,
  451. GENERAL_COLUMN);
  452. /* only works if source reg = dest reg with buffer */
  453. /* messing with elaboration region is dangerous... */
  454. /* align_elaboration_box(&elaboration_reg, &src_reg, GENERAL_COLUMN); */
  455. align_interp_boxes(&general_box, &overlap_box, &dest_reg,
  456. last_general_box, last_overlap_box, GENERAL_COLUMN);
  457. if (elaboration_reg.west < dest_reg.west) { /* First column */
  458. P_set_regions(&elaboration_reg, &general_box, &overlap_box,
  459. dims, FIRST_COLUMN);
  460. /* align_elaboration_box(&elaboration_reg, &src_reg, GENERAL_COLUMN); */
  461. align_interp_boxes(&general_box, &overlap_box, &dest_reg,
  462. last_general_box, last_overlap_box, FIRST_COLUMN);
  463. }
  464. if (elaboration_reg.east >= dest_reg.east) { /* Last column */
  465. P_set_regions(&elaboration_reg, &general_box, &overlap_box,
  466. dims, LAST_COLUMN);
  467. last_column = TRUE;
  468. }
  469. nsplx =
  470. ceil((elaboration_reg.east -
  471. elaboration_reg.west) / stepE) + 0.5;
  472. G_debug(1, "Interpolation: nsplx = %d", nsplx);
  473. if (grid_opt->answer) {
  474. Vect_reset_cats(Cats);
  475. Vect_cat_set(Cats, 1, cat++);
  476. Vect_reset_line(Points);
  477. Vect_append_point(Points, general_box.W, general_box.S, 0);
  478. Vect_append_point(Points, general_box.E, general_box.S, 0);
  479. Vect_append_point(Points, general_box.E, general_box.N, 0);
  480. Vect_append_point(Points, general_box.W, general_box.N, 0);
  481. Vect_append_point(Points, general_box.W, general_box.S, 0);
  482. Vect_write_line(&Grid, GV_LINE, Points, Cats);
  483. Vect_reset_line(Points);
  484. Vect_append_point(Points, (general_box.E + general_box.W) / 2,
  485. (general_box.N + general_box.S) / 2, 0);
  486. Vect_write_line(&Grid, GV_POINT, Points, Cats);
  487. }
  488. /* reading points in interpolation region */
  489. G_debug(1, "reading points from input raster...");
  490. dim_vect = nsplx * nsply;
  491. observ =
  492. P_Read_Raster_Region_Map(&in_seg, &elaboration_reg,
  493. &src_reg, &npoints, dim_vect);
  494. G_debug(1, "%d valid points", npoints);
  495. G_debug(1,
  496. "Interpolation: (%d,%d): Number of points in <elaboration_box> is %d",
  497. subregion_row, subregion_col, npoints);
  498. /* Mean calculation for observed non-NULL points */
  499. if (npoints > 0)
  500. mean = P_Mean_Calc(&elaboration_reg, observ, npoints);
  501. else
  502. mean = 0;
  503. G_debug(1, "Interpolation: (%d,%d): mean=%lf",
  504. subregion_row, subregion_col, mean);
  505. observ_marked = NULL;
  506. if (have_mask) {
  507. /* collect unmasked output cells */
  508. G_debug(1, "collect unmasked output cells");
  509. observ_marked =
  510. P_Read_Raster_Region_masked(&mask_seg, &dest_reg,
  511. dest_box, general_box,
  512. &npoints_marked, dim_vect, mean);
  513. G_debug(1, "%d cells marked in general", npoints_marked);
  514. if (npoints_marked == 0) {
  515. G_free(observ_marked);
  516. observ_marked = NULL;
  517. npoints = 1; /* disable warning below */
  518. }
  519. }
  520. if (npoints > 0 && npoints_marked > 0) { /* */
  521. int i;
  522. nparameters = nsplx * nsply;
  523. BW = P_get_BandWidth(interp_method, nsply > nsplx ? nsply : nsplx);
  524. /* Least Squares system */
  525. N = G_alloc_matrix(nparameters, BW); /* Normal matrix */
  526. TN = G_alloc_vector(nparameters); /* vector */
  527. parVect = G_alloc_vector(nparameters); /* Parameters vector */
  528. obsVect = G_alloc_matrix(npoints, 3); /* Observation vector */
  529. Q = G_alloc_vector(npoints); /* "a priori" var-cov matrix */
  530. for (i = 0; i < npoints; i++) { /* Setting obsVect vector & Q matrix */
  531. Q[i] = 1; /* Q=I */
  532. obsVect[i][0] = observ[i].coordX;
  533. obsVect[i][1] = observ[i].coordY;
  534. obsVect[i][2] = observ[i].coordZ - mean;
  535. }
  536. G_free(observ);
  537. /* Bilinear interpolation */
  538. if (interp_method == P_BILINEAR) {
  539. G_debug(1,
  540. "Interpolation: (%d,%d): Bilinear interpolation...",
  541. subregion_row, subregion_col);
  542. normalDefBilin(N, TN, Q, obsVect, stepE, stepN, nsplx,
  543. nsply, elaboration_reg.west,
  544. elaboration_reg.south, npoints,
  545. nparameters, BW);
  546. nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN);
  547. }
  548. /* Bicubic interpolation */
  549. else {
  550. G_debug(1,
  551. "Interpolation: (%d,%d): Bicubic interpolation...",
  552. subregion_row, subregion_col);
  553. normalDefBicubic(N, TN, Q, obsVect, stepE, stepN, nsplx,
  554. nsply, elaboration_reg.west,
  555. elaboration_reg.south, npoints,
  556. nparameters, BW);
  557. nCorrectGrad(N, lambda, nsplx, nsply, stepE, stepN);
  558. }
  559. G_math_solver_cholesky_sband(N, parVect, TN, nparameters, BW);
  560. G_free_matrix(N);
  561. G_free_vector(TN);
  562. G_free_vector(Q);
  563. if (!observ_marked) { /* interpolate full output raster */
  564. G_debug(1, "Interpolation: (%d,%d): Regular_Points...",
  565. subregion_row, subregion_col);
  566. P_Regular_Points(&elaboration_reg, &dest_reg, general_box,
  567. overlap_box, &out_seg,
  568. parVect, stepN, stepE, dims.overlap, mean,
  569. nsplx, nsply, nrows, ncols, interp_method);
  570. }
  571. else { /* only interpolate selected cells */
  572. G_debug(1, "Interpolation of %d selected cells...",
  573. npoints_marked);
  574. P_Sparse_Raster_Points(&out_seg,
  575. &elaboration_reg, &dest_reg,
  576. general_box, overlap_box,
  577. observ_marked, parVect,
  578. stepE, stepN,
  579. dims.overlap, nsplx, nsply,
  580. npoints_marked, interp_method, mean);
  581. G_free(observ_marked);
  582. } /* end NULL cells */
  583. G_free_vector(parVect);
  584. G_free_matrix(obsVect);
  585. }
  586. else {
  587. if (observ)
  588. G_free(observ);
  589. if (npoints == 0)
  590. G_warning(_("No data within this subregion. "
  591. "Consider increasing the spline step."));
  592. }
  593. } /*! END WHILE; last_column = TRUE */
  594. } /*! END WHILE; last_row = TRUE */
  595. Segment_release(&in_seg); /* release memory */
  596. close(in_fd);
  597. unlink(in_file);
  598. if (have_mask) {
  599. Segment_release(&mask_seg); /* release memory */
  600. close(mask_fd);
  601. unlink(mask_file);
  602. }
  603. G_message(_("Writing output..."));
  604. /* Writing the output raster map */
  605. Rast_set_fp_type(DCELL_TYPE);
  606. outrastfd = Rast_open_fp_new(out_opt->answer);
  607. /* check */
  608. {
  609. int nonulls = 0;
  610. Segment_flush(&out_seg);
  611. drastbuf = Rast_allocate_d_buf();
  612. for (row = 0; row < dest_reg.rows; row++) {
  613. G_percent(row, dest_reg.rows, 9);
  614. Segment_get_row(&out_seg, drastbuf, row);
  615. for (col = 0; col < dest_reg.cols; col++) {
  616. dval = drastbuf[col];
  617. if (!Rast_is_d_null_value(&dval))
  618. nonulls++;
  619. }
  620. Rast_put_d_row(outrastfd, drastbuf);
  621. }
  622. G_percent(1, 1, 1);
  623. if (!nonulls)
  624. G_warning("only NULL cells in output raster");
  625. }
  626. Segment_release(&out_seg); /* release memory */
  627. close(out_fd);
  628. unlink(out_file);
  629. Rast_close(outrastfd);
  630. /* set map title */
  631. sprintf(title, "%s interpolation with Tykhonov regularization",
  632. method_opt->answer);
  633. Rast_put_cell_title(out_opt->answer, title);
  634. /* write map history */
  635. Rast_short_history(out_opt->answer, "raster", &history);
  636. Rast_command_history(&history);
  637. Rast_write_history(out_opt->answer, &history);
  638. if (grid_opt->answer) {
  639. Vect_build(&Grid);
  640. Vect_hist_command(&Grid);
  641. Vect_close(&Grid);
  642. }
  643. G_done_msg(" ");
  644. exit(EXIT_SUCCESS);
  645. } /*END MAIN */