segmen2d.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*!
  2. * \file segmen2d.c
  3. *
  4. * \author H. Mitasova, I. Kosinovsky, D. Gerdes
  5. *
  6. * \copyright
  7. * (C) 1993 by Helena Mitasova and the GRASS Development Team
  8. *
  9. * \copyright
  10. * This program is free software under the
  11. * GNU General Public License (>=v2).
  12. * Read the file COPYING that comes with GRASS
  13. * for details.
  14. *
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <math.h>
  19. #include <grass/gis.h>
  20. #include <grass/glocale.h>
  21. #include <grass/interpf.h>
  22. #include <grass/gmath.h>
  23. /*!
  24. * Interpolate recursively a tree of segments
  25. *
  26. * Recursively processes each segment in a tree by:
  27. * - finding points from neighbouring segments so that the total number of
  28. * points is between KMIN and KMAX2 by calling tree function MT_get_region().
  29. * - creating and solving the system of linear equations using these points
  30. * and interp() by calling matrix_create() and G_ludcmp().
  31. * - checking the interpolating function values at points by calling
  32. * check_points().
  33. * - computing grid for this segment using points and interp() by calling
  34. * grid_calc().
  35. *
  36. * \todo
  37. * Isn't this in fact the updated version of the function (IL_interp_segments_new_2d)?
  38. * The function IL_interp_segments_new_2d has the following, better behavior:
  39. * The difference between this function and IL_interp_segments_2d() is making
  40. * sure that additional points are taken from all directions, i.e. it finds
  41. * equal number of points from neighboring segments in each of 8 neighborhoods.
  42. */
  43. int IL_interp_segments_2d(struct interp_params *params,
  44. struct tree_info *info, /*!< info for the quad tree */
  45. struct multtree *tree, /*!< current leaf of the quad tree */
  46. struct BM *bitmask, /*!< bitmask */
  47. double zmin, double zmax, /*!< min and max input z-values */
  48. double *zminac, double *zmaxac, /*!< min and max interp. z-values */
  49. double *gmin, double *gmax, /*!< min and max inperp. slope val. */
  50. double *c1min, double *c1max, /*!< min and max interp. curv. val. */
  51. double *c2min, double *c2max, /*!< min and max interp. curv. val. */
  52. double *ertot, /*!< total interplating func. error */
  53. int totsegm, /*!< total number of segments */
  54. off_t offset1, /*!< offset for temp file writing */
  55. double dnorm)
  56. {
  57. double xmn, xmx, ymn, ymx, distx, disty, distxp, distyp, temp1, temp2;
  58. int i, npt, nptprev, MAXENC;
  59. struct quaddata *data;
  60. static int cursegm = 0;
  61. static double *b = NULL;
  62. static int *indx = NULL;
  63. static double **matrix = NULL;
  64. double ew_res, ns_res;
  65. static int first_time = 1;
  66. static double smseg;
  67. int MINPTS;
  68. double pr;
  69. struct triple *point;
  70. struct triple skip_point;
  71. int m_skip, skip_index, j, k, segtest;
  72. double xx, yy, zz;
  73. /* find the size of the smallest segment once */
  74. if (first_time) {
  75. smseg = smallest_segment(info->root, 4);
  76. first_time = 0;
  77. }
  78. ns_res = (((struct quaddata *)(info->root->data))->ymax -
  79. ((struct quaddata *)(info->root->data))->y_orig) /
  80. params->nsizr;
  81. ew_res =
  82. (((struct quaddata *)(info->root->data))->xmax -
  83. ((struct quaddata *)(info->root->data))->x_orig) / params->nsizc;
  84. if (tree == NULL)
  85. return -1;
  86. if (tree->data == NULL)
  87. return -1;
  88. if (((struct quaddata *)(tree->data))->points == NULL) {
  89. for (i = 0; i < 4; i++) {
  90. IL_interp_segments_2d(params, info, tree->leafs[i],
  91. bitmask, zmin, zmax, zminac, zmaxac, gmin,
  92. gmax, c1min, c1max, c2min, c2max, ertot,
  93. totsegm, offset1, dnorm);
  94. }
  95. return 1;
  96. }
  97. else {
  98. distx = (((struct quaddata *)(tree->data))->n_cols * ew_res) * 0.1;
  99. disty = (((struct quaddata *)(tree->data))->n_rows * ns_res) * 0.1;
  100. distxp = 0;
  101. distyp = 0;
  102. xmn = ((struct quaddata *)(tree->data))->x_orig;
  103. xmx = ((struct quaddata *)(tree->data))->xmax;
  104. ymn = ((struct quaddata *)(tree->data))->y_orig;
  105. ymx = ((struct quaddata *)(tree->data))->ymax;
  106. i = 0;
  107. MAXENC = 0;
  108. /* data is a window with zero points; some fields don't make sense in this case
  109. so they are zero (like resolution,dimensions */
  110. /* CHANGE */
  111. /* Calcutaing kmin for surrent segment (depends on the size) */
  112. /*****if (smseg <= 0.00001) MINPTS=params->kmin; else {} ***/
  113. pr = pow(2., (xmx - xmn) / smseg - 1.);
  114. MINPTS =
  115. params->kmin * (pr / (1 + params->kmin * pr / params->KMAX2));
  116. /* fprintf(stderr,"MINPTS=%d, KMIN=%d, KMAX=%d, pr=%lf, smseg=%lf, DX=%lf \n", MINPTS,params->kmin,params->KMAX2,pr,smseg,xmx-xmn); */
  117. data =
  118. (struct quaddata *)quad_data_new(xmn - distx, ymn - disty,
  119. xmx + distx, ymx + disty, 0, 0,
  120. 0, params->KMAX2);
  121. npt = MT_region_data(info, info->root, data, params->KMAX2, 4);
  122. while ((npt < MINPTS) || (npt > params->KMAX2)) {
  123. if (i >= 70) {
  124. G_warning(_("Taking too long to find points for interpolation - "
  125. "please change the region to area where your points are. "
  126. "Continuing calculations..."));
  127. break;
  128. }
  129. i++;
  130. if (npt > params->KMAX2)
  131. /* decrease window */
  132. {
  133. MAXENC = 1;
  134. nptprev = npt;
  135. temp1 = distxp;
  136. distxp = distx;
  137. distx = distxp - fabs(distx - temp1) * 0.5;
  138. temp2 = distyp;
  139. distyp = disty;
  140. disty = distyp - fabs(disty - temp2) * 0.5;
  141. /* decrease by 50% of a previous change in window */
  142. }
  143. else {
  144. nptprev = npt;
  145. temp1 = distyp;
  146. distyp = disty;
  147. temp2 = distxp;
  148. distxp = distx;
  149. if (MAXENC) {
  150. disty = fabs(disty - temp1) * 0.5 + distyp;
  151. distx = fabs(distx - temp2) * 0.5 + distxp;
  152. }
  153. else {
  154. distx += distx;
  155. disty += disty;
  156. }
  157. /* decrease by 50% of extra distance */
  158. }
  159. data->x_orig = xmn - distx; /* update window */
  160. data->y_orig = ymn - disty;
  161. data->xmax = xmx + distx;
  162. data->ymax = ymx + disty;
  163. data->n_points = 0;
  164. npt = MT_region_data(info, info->root, data, params->KMAX2, 4);
  165. }
  166. if (totsegm != 0) {
  167. G_percent(cursegm, totsegm, 1);
  168. }
  169. data->n_rows = ((struct quaddata *)(tree->data))->n_rows;
  170. data->n_cols = ((struct quaddata *)(tree->data))->n_cols;
  171. /* for printing out overlapping segments */
  172. ((struct quaddata *)(tree->data))->x_orig = xmn - distx;
  173. ((struct quaddata *)(tree->data))->y_orig = ymn - disty;
  174. ((struct quaddata *)(tree->data))->xmax = xmx + distx;
  175. ((struct quaddata *)(tree->data))->ymax = ymx + disty;
  176. data->x_orig = xmn;
  177. data->y_orig = ymn;
  178. data->xmax = xmx;
  179. data->ymax = ymx;
  180. if (!matrix) {
  181. if (!
  182. (matrix =
  183. G_alloc_matrix(params->KMAX2 + 1, params->KMAX2 + 1))) {
  184. G_warning(_("Out of memory"));
  185. return -1;
  186. }
  187. }
  188. if (!indx) {
  189. if (!(indx = G_alloc_ivector(params->KMAX2 + 1))) {
  190. G_warning(_("Out of memory"));
  191. return -1;
  192. }
  193. }
  194. if (!b) {
  195. if (!(b = G_alloc_vector(params->KMAX2 + 3))) {
  196. G_warning(_("Out of memory"));
  197. return -1;
  198. }
  199. }
  200. /* allocate memory for CV points only if cv is performed */
  201. if (params->cv) {
  202. if (!
  203. (point =
  204. (struct triple *)G_malloc(sizeof(struct triple) *
  205. data->n_points))) {
  206. G_warning(_("Out of memory"));
  207. return -1;
  208. }
  209. }
  210. /*normalize the data so that the side of average segment is about 1m */
  211. /* put data_points into point only if CV is performed */
  212. for (i = 0; i < data->n_points; i++) {
  213. data->points[i].x = (data->points[i].x - data->x_orig) / dnorm;
  214. data->points[i].y = (data->points[i].y - data->y_orig) / dnorm;
  215. if (params->cv) {
  216. point[i].x = data->points[i].x; /*cv stuff */
  217. point[i].y = data->points[i].y; /*cv stuff */
  218. point[i].z = data->points[i].z; /*cv stuff */
  219. }
  220. /* commented out by Helena january 1997 as this is not necessary
  221. although it may be useful to put normalization of z back?
  222. data->points[i].z = data->points[i].z / dnorm;
  223. this made smoothing self-adjusting based on dnorm
  224. if (params->rsm < 0.) data->points[i].sm = data->points[i].sm / dnorm;
  225. */
  226. }
  227. /* cv stuff */
  228. if (params->cv)
  229. m_skip = data->n_points;
  230. else
  231. m_skip = 1;
  232. /* remove after cleanup - this is just for testing */
  233. skip_point.x = 0.;
  234. skip_point.y = 0.;
  235. skip_point.z = 0.;
  236. /*** TODO: parallelize this loop instead of the LU solver! ***/
  237. for (skip_index = 0; skip_index < m_skip; skip_index++) {
  238. if (params->cv) {
  239. segtest = 0;
  240. j = 0;
  241. xx = point[skip_index].x * dnorm + data->x_orig +
  242. params->x_orig;
  243. yy = point[skip_index].y * dnorm + data->y_orig +
  244. params->y_orig;
  245. zz = point[skip_index].z;
  246. if (xx >= data->x_orig + params->x_orig &&
  247. xx <= data->xmax + params->x_orig &&
  248. yy >= data->y_orig + params->y_orig &&
  249. yy <= data->ymax + params->y_orig) {
  250. segtest = 1;
  251. skip_point.x = point[skip_index].x;
  252. skip_point.y = point[skip_index].y;
  253. skip_point.z = point[skip_index].z;
  254. for (k = 0; k < m_skip; k++) {
  255. if (k != skip_index && params->cv) {
  256. data->points[j].x = point[k].x;
  257. data->points[j].y = point[k].y;
  258. data->points[j].z = point[k].z;
  259. j++;
  260. }
  261. }
  262. } /* segment area test */
  263. }
  264. if (!params->cv) {
  265. if (params->
  266. matrix_create(params, data->points, data->n_points,
  267. matrix, indx) < 0)
  268. return -1;
  269. }
  270. else if (segtest == 1) {
  271. if (params->
  272. matrix_create(params, data->points, data->n_points - 1,
  273. matrix, indx) < 0)
  274. return -1;
  275. }
  276. if (!params->cv) {
  277. for (i = 0; i < data->n_points; i++)
  278. b[i + 1] = data->points[i].z;
  279. b[0] = 0.;
  280. G_lubksb(matrix, data->n_points + 1, indx, b);
  281. /* put here condition to skip error if not needed */
  282. params->check_points(params, data, b, ertot, zmin, dnorm,
  283. skip_point);
  284. }
  285. else if (segtest == 1) {
  286. for (i = 0; i < data->n_points - 1; i++)
  287. b[i + 1] = data->points[i].z;
  288. b[0] = 0.;
  289. G_lubksb(matrix, data->n_points, indx, b);
  290. params->check_points(params, data, b, ertot, zmin, dnorm,
  291. skip_point);
  292. }
  293. } /*end of cv loop */
  294. if (!params->cv)
  295. if ((params->Tmp_fd_z != NULL) || (params->Tmp_fd_dx != NULL) ||
  296. (params->Tmp_fd_dy != NULL) || (params->Tmp_fd_xx != NULL) ||
  297. (params->Tmp_fd_yy != NULL) || (params->Tmp_fd_xy != NULL)) {
  298. if (params->grid_calc(params, data, bitmask,
  299. zmin, zmax, zminac, zmaxac, gmin, gmax,
  300. c1min, c1max, c2min, c2max, ertot, b,
  301. offset1, dnorm) < 0)
  302. return -1;
  303. }
  304. /* show after to catch 100% */
  305. cursegm++;
  306. if (totsegm < cursegm)
  307. G_debug(1, "%d %d", totsegm, cursegm);
  308. if (totsegm != 0) {
  309. G_percent(cursegm, totsegm, 1);
  310. }
  311. /*
  312. G_free_matrix(matrix);
  313. G_free_ivector(indx);
  314. G_free_vector(b);
  315. */
  316. G_free(data->points);
  317. G_free(data);
  318. }
  319. return 1;
  320. }
  321. double smallest_segment(struct multtree *tree, int n_leafs)
  322. {
  323. static int first_time = 1;
  324. int ii;
  325. static double minside;
  326. double side;
  327. if (tree == NULL)
  328. return 0;
  329. if (tree->data == NULL)
  330. return 0;
  331. if (tree->leafs != NULL) {
  332. for (ii = 0; ii < n_leafs; ii++) {
  333. side = smallest_segment(tree->leafs[ii], n_leafs);
  334. if (first_time) {
  335. minside = side;
  336. first_time = 0;
  337. }
  338. if (side < minside)
  339. minside = side;
  340. }
  341. }
  342. else {
  343. side = ((struct quaddata *)(tree->data))->xmax -
  344. ((struct quaddata *)(tree->data))->x_orig;
  345. return side;
  346. }
  347. return minside;
  348. }