segmen2d.c 10 KB

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