dataquad.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*!
  2. * \file qtree.c
  3. *
  4. * \author
  5. * H. Mitasova, I. Kosinovsky, D. Gerdes, Fall 1993,
  6. * University of Illinois and
  7. * US Army Construction Engineering Research Lab
  8. *
  9. * \author H. Mitasova (University of Illinois),
  10. * \author I. Kosinovsky, (USA-CERL)
  11. * \author D.Gerdes (USA-CERL)
  12. *
  13. * \author modified by H. Mitasova, November 1996 (include variable smoothing)
  14. *
  15. * \copyright
  16. * (C) 1993-1996 by Helena Mitasova and the GRASS Development Team
  17. *
  18. * \copyright
  19. * This program is free software under the
  20. * GNU General Public License (>=v2).
  21. * Read the file COPYING that comes with GRASS for details.
  22. */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <grass/dataquad.h>
  26. /*!
  27. * Initialize point structure with given arguments
  28. *
  29. * This is a constructor of the point structure and it allocates memory.
  30. *
  31. * \note
  32. * Smoothing is part of the point structure
  33. */
  34. struct triple *quad_point_new(double x, double y, double z, double sm)
  35. {
  36. struct triple *point;
  37. if (!(point = (struct triple *)malloc(sizeof(struct triple)))) {
  38. return NULL;
  39. }
  40. point->x = x;
  41. point->y = y;
  42. point->z = z;
  43. point->sm = sm;
  44. return point;
  45. }
  46. /*!
  47. * Initialize quaddata structure with given arguments
  48. *
  49. * This is a constructor of the quaddata structure and it allocates memory.
  50. * It also creates (and allocates memory for) the given number of points
  51. * (given by *kmax*). The point attributes are set to zero.
  52. */
  53. struct quaddata *quad_data_new(double x_or, double y_or, double xmax,
  54. double ymax, int rows, int cols, int n_points,
  55. int kmax)
  56. {
  57. struct quaddata *data;
  58. int i;
  59. if (!(data = (struct quaddata *)malloc(sizeof(struct quaddata)))) {
  60. return NULL;
  61. }
  62. data->x_orig = x_or;
  63. data->y_orig = y_or;
  64. data->xmax = xmax;
  65. data->ymax = ymax;
  66. data->n_rows = rows;
  67. data->n_cols = cols;
  68. data->n_points = n_points;
  69. data->points =
  70. (struct triple *)malloc(sizeof(struct triple) * (kmax + 1));
  71. if (!data->points)
  72. return NULL;
  73. for (i = 0; i <= kmax; i++) {
  74. data->points[i].x = 0.;
  75. data->points[i].y = 0.;
  76. data->points[i].z = 0.;
  77. data->points[i].sm = 0.;
  78. }
  79. return data;
  80. }
  81. /*!
  82. * Return the quadrant the point should be inserted in
  83. */
  84. int quad_compare(struct triple *point, struct quaddata *data)
  85. {
  86. int cond1, cond2, cond3, cond4, rows, cols;
  87. double ew_res, ns_res;
  88. ew_res = (data->xmax - data->x_orig) / data->n_cols;
  89. ns_res = (data->ymax - data->y_orig) / data->n_rows;
  90. if (data == NULL)
  91. return -1;
  92. if (data->n_rows % 2 == 0) {
  93. rows = data->n_rows / 2;
  94. }
  95. else {
  96. rows = (int)(data->n_rows / 2) + 1;
  97. }
  98. if (data->n_cols % 2 == 0) {
  99. cols = data->n_cols / 2;
  100. }
  101. else {
  102. cols = (int)(data->n_cols / 2) + 1;
  103. }
  104. cond1 = (point->x >= data->x_orig);
  105. cond2 = (point->x >= data->x_orig + ew_res * cols);
  106. cond3 = (point->y >= data->y_orig);
  107. cond4 = (point->y >= data->y_orig + ns_res * rows);
  108. if (cond1 && cond3) {
  109. if (cond2 && cond4)
  110. return NE;
  111. if (cond2)
  112. return SE;
  113. if (cond4)
  114. return NW;
  115. return SW;
  116. }
  117. else
  118. return 0;
  119. }
  120. /*!
  121. * Add point to a given *data*.
  122. */
  123. int quad_add_data(struct triple *point, struct quaddata *data, double dmin)
  124. {
  125. int n, i, cond;
  126. double xx, yy, r;
  127. cond = 1;
  128. if (data == NULL) {
  129. fprintf(stderr, "add_data: data is NULL \n");
  130. return -5;
  131. }
  132. for (i = 0; i < data->n_points; i++) {
  133. xx = data->points[i].x - point->x;
  134. yy = data->points[i].y - point->y;
  135. r = xx * xx + yy * yy;
  136. if (r <= dmin) {
  137. cond = 0;
  138. break;
  139. }
  140. }
  141. if (cond) {
  142. n = (data->n_points)++;
  143. data->points[n].x = point->x;
  144. data->points[n].y = point->y;
  145. data->points[n].z = point->z;
  146. data->points[n].sm = point->sm;
  147. }
  148. return cond;
  149. }
  150. /*!
  151. * Check intersection of two quaddata structures
  152. *
  153. * Checks if region defined by *data* intersects the region defined
  154. * by *data_inter*.
  155. */
  156. int quad_intersect(struct quaddata *data_inter, struct quaddata *data)
  157. {
  158. double xmin, xmax, ymin, ymax;
  159. xmin = data_inter->x_orig;
  160. xmax = data_inter->xmax;
  161. ymin = data_inter->y_orig;
  162. ymax = data_inter->ymax;
  163. if (((data->x_orig >= xmin) && (data->x_orig <= xmax)
  164. && (((data->y_orig >= ymin) && (data->y_orig <= ymax))
  165. || ((ymin >= data->y_orig) && (ymin <= data->ymax))
  166. )
  167. )
  168. || ((xmin >= data->x_orig) && (xmin <= data->xmax)
  169. && (((ymin >= data->y_orig) && (ymin <= data->ymax))
  170. || ((data->y_orig >= ymin) && (data->y_orig <= ymax))
  171. )
  172. )
  173. ) {
  174. return 1;
  175. }
  176. else
  177. return 0;
  178. }
  179. /*!
  180. * Check if *data* needs to be divided
  181. *
  182. * Checks if *data* needs to be divided. If `data->points` is empty,
  183. * returns -1; if its not empty but there aren't enough points
  184. * in *data* for division returns 0. Otherwise (if its not empty and
  185. * there are too many points) returns 1.
  186. *
  187. * \returns 1 if division is needed
  188. * \returns 0 if division is not needed
  189. * \returns -1 if there are no points
  190. */
  191. int quad_division_check(struct quaddata *data, int kmax)
  192. {
  193. if (data->points == NULL)
  194. return -1;
  195. if (data->n_points < kmax)
  196. return 0;
  197. else
  198. return 1;
  199. }
  200. /*!
  201. * Divide *data* into four new ones
  202. *
  203. * Divides *data* into 4 new datas reinserting `data->points` in
  204. * them by calling data function `quad_compare()` to determine
  205. * were to insert. Returns array of 4 new datas (allocates memory).
  206. */
  207. struct quaddata **quad_divide_data(struct quaddata *data, int kmax,
  208. double dmin)
  209. {
  210. struct quaddata **datas;
  211. int cols1, cols2, rows1, rows2, i; /*j1, j2, jmin = 0; */
  212. double dx, dy; /* x2, y2, dist, mindist; */
  213. double xr, xm, xl, yr, ym, yl; /* left, right, middle coord */
  214. double ew_res, ns_res;
  215. ew_res = (data->xmax - data->x_orig) / data->n_cols;
  216. ns_res = (data->ymax - data->y_orig) / data->n_rows;
  217. if ((data->n_cols <= 1) || (data->n_rows <= 1)) {
  218. fprintf(stderr,
  219. "Points are too concentrated -- please increase DMIN\n");
  220. exit(0);
  221. }
  222. if (data->n_cols % 2 == 0) {
  223. cols1 = data->n_cols / 2;
  224. cols2 = cols1;
  225. }
  226. else {
  227. cols2 = (int)(data->n_cols / 2);
  228. cols1 = cols2 + 1;
  229. }
  230. if (data->n_rows % 2 == 0) {
  231. rows1 = data->n_rows / 2;
  232. rows2 = rows1;
  233. }
  234. else {
  235. rows2 = (int)(data->n_rows / 2);
  236. rows1 = rows2 + 1;
  237. }
  238. dx = cols1 * ew_res;
  239. dy = rows1 * ns_res;
  240. xl = data->x_orig;
  241. xm = xl + dx;
  242. xr = data->xmax;
  243. yl = data->y_orig;
  244. ym = yl + dy;
  245. yr = data->ymax;
  246. if (!(datas = (struct quaddata **)malloc(sizeof(struct quaddata *) * 5))) {
  247. return NULL;
  248. }
  249. datas[NE] = quad_data_new(xm, ym, xr, yr, rows2, cols2, 0, kmax);
  250. datas[SW] = quad_data_new(xl, yl, xm, ym, rows1, cols1, 0, kmax);
  251. datas[SE] = quad_data_new(xm, yl, xr, ym, rows1, cols2, 0, kmax);
  252. datas[NW] = quad_data_new(xl, ym, xm, yr, rows2, cols1, 0, kmax);
  253. for (i = 0; i < data->n_points; i++) {
  254. switch (quad_compare(data->points + i, data)) {
  255. case SW:
  256. {
  257. quad_add_data(data->points + i, datas[SW], dmin);
  258. break;
  259. }
  260. case SE:
  261. {
  262. quad_add_data(data->points + i, datas[SE], dmin);
  263. break;
  264. }
  265. case NW:
  266. {
  267. quad_add_data(data->points + i, datas[NW], dmin);
  268. break;
  269. }
  270. case NE:
  271. {
  272. quad_add_data(data->points + i, datas[NE], dmin);
  273. break;
  274. }
  275. }
  276. }
  277. data->points = NULL;
  278. return datas;
  279. }
  280. /*!
  281. * Gets such points from *data* that lie within region determined by
  282. * *data_inter*. Called by tree function `region_data()`.
  283. */
  284. int
  285. quad_get_points(struct quaddata *data_inter, struct quaddata *data, int MAX)
  286. {
  287. int i, ind;
  288. int n = 0;
  289. int l = 0;
  290. double xmin, xmax, ymin, ymax;
  291. struct triple *point;
  292. xmin = data_inter->x_orig;
  293. xmax = data_inter->xmax;
  294. ymin = data_inter->y_orig;
  295. ymax = data_inter->ymax;
  296. for (i = 0; i < data->n_points; i++) {
  297. point = data->points + i;
  298. if (l >= MAX)
  299. return MAX + 1;
  300. if ((point->x > xmin) && (point->x < xmax)
  301. && (point->y > ymin) && (point->y < ymax)) {
  302. ind = data_inter->n_points++;
  303. data_inter->points[ind].x = point->x;
  304. data_inter->points[ind].y = point->y;
  305. data_inter->points[ind].z = point->z;
  306. data_inter->points[ind].sm = point->sm;
  307. l = l + 1;
  308. }
  309. }
  310. n = l;
  311. return (n);
  312. }