segmen2d.c 10 KB

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