displacement.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /****************************************************************
  2. *
  3. * MODULE: v.generalize
  4. *
  5. * AUTHOR(S): Daniel Bundala
  6. *
  7. * PURPOSE: Methods for displacement
  8. *
  9. * COPYRIGHT: (C) 2002-2005 by the GRASS Development Team
  10. *
  11. * This program is free software under the
  12. * GNU General Public License (>=v2).
  13. * Read the file COPYING that comes with GRASS
  14. * for details.
  15. *
  16. ****************************************************************/
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <math.h>
  20. #include <grass/gis.h>
  21. #include <grass/vector.h>
  22. #include <grass/glocale.h>
  23. #include "point.h"
  24. #include "matrix.h"
  25. /* snakes method modified for displacement.
  26. * Function returns something. This function affects only the
  27. * lines specified in varray (or all lines if varray is null).
  28. Other lines are copied */
  29. int snakes_displacement(struct Map_info *In, struct Map_info *Out,
  30. double threshold, double alpha, double beta,
  31. double gama, double delta, int iterations,
  32. struct cat_list *cat_list, int layer)
  33. {
  34. int n_points;
  35. int n_lines;
  36. int i, j, index, pindex, iter, type;
  37. int with_z = 0;
  38. struct line_pnts *Points;
  39. struct line_cats *Cats;
  40. MATRIX k, dx, dy, fx, fy, kinv, dx_old, dy_old;
  41. POINT *parray;
  42. POINT *pset;
  43. int *point_index;
  44. int *first, *line_index, *need, *sel, *tmp_index;
  45. double threshold2;
  46. int selected;
  47. /* initialize structrures and read the number of points */
  48. Points = Vect_new_line_struct();
  49. Cats = Vect_new_cats_struct();
  50. n_lines = Vect_get_num_lines(In);
  51. n_points = 0;
  52. for (i = 1; i <= n_lines; i++) {
  53. type = Vect_read_line(In, Points, Cats, i);
  54. if (layer > 0 && !Vect_cats_in_constraint(Cats, layer, cat_list))
  55. continue;
  56. if (type & GV_LINE)
  57. n_points += Points->n_points;
  58. }
  59. parray = (POINT *) G_calloc(n_points, sizeof(POINT));
  60. pset = (POINT *) G_calloc(n_points, sizeof(POINT));
  61. point_index = (int *)G_calloc(n_points, sizeof(int));
  62. first = (int *)G_calloc(n_points, sizeof(int));
  63. line_index = (int *)G_calloc(n_points, sizeof(int));
  64. need = (int *)G_calloc(n_points, sizeof(int));
  65. sel = (int *)G_calloc(n_points, sizeof(int));
  66. tmp_index = (int *)G_calloc(n_points, sizeof(int));
  67. /* read points
  68. * TODO: some better/faster method for determining whether two points are the same */
  69. G_percent_reset();
  70. G_message(_("Reading data..."));
  71. index = 0;
  72. pindex = 0;
  73. for (i = 1; i <= n_lines; i++) {
  74. G_percent(i, n_lines, 1);
  75. type = Vect_read_line(In, Points, Cats, i);
  76. if (type != GV_LINE)
  77. continue;
  78. if (layer > 0 && !Vect_cats_in_constraint(Cats, layer, cat_list))
  79. continue;
  80. for (j = 0; j < Points->n_points; j++) {
  81. int q, findex;
  82. POINT cur;
  83. point_assign(Points, j, with_z, &cur, 0);
  84. /* check whether we alerady have point with the same
  85. * coordinates */
  86. findex = pindex;
  87. for (q = 0; q < pindex; q++)
  88. if (point_dist_square(cur, pset[q]) < 0.5) {
  89. findex = q;
  90. break;
  91. }
  92. point_index[index] = findex;
  93. if (findex == pindex) {
  94. point_assign(Points, j, with_z, &pset[pindex], 0);
  95. pindex++;
  96. }
  97. first[index] = (j == 0);
  98. line_index[index] = i;
  99. point_assign(Points, j, with_z, &parray[index], 0);
  100. index++;
  101. }
  102. }
  103. threshold2 = threshold * threshold;
  104. /*select only the points which need to be displaced */
  105. for (i = 0; i < index; i++) {
  106. if (need[point_index[i]])
  107. continue;
  108. for (j = 1; j < index; j++) {
  109. if (line_index[i] == line_index[j] || first[j] ||
  110. point_index[i] == point_index[j] ||
  111. point_index[i] == point_index[j - 1])
  112. continue;
  113. double d =
  114. point_dist_segment_square(parray[i], parray[j], parray[j - 1],
  115. with_z);
  116. if (d < 4 * threshold2)
  117. need[point_index[i]] = 1;
  118. }
  119. }
  120. /* then for each selected point ensure that the neighbours to the both
  121. * sides are selected as well */
  122. for (i = 0; i < index; i++) {
  123. int l = line_index[i];
  124. tmp_index[i] = -1;
  125. if (!need[point_index[i]])
  126. continue;
  127. for (j = -2; j <= 2; j++)
  128. if (i + j >= 0 && i + j < index && line_index[i + j] == l)
  129. sel[point_index[i + j]] = 1;
  130. }
  131. /* finally, recalculate indices */
  132. selected = 0;
  133. for (i = 0; i < pindex; i++)
  134. if (sel[i])
  135. tmp_index[i] = selected++;
  136. for (i = 0; i < index; i++)
  137. point_index[i] = tmp_index[point_index[i]];
  138. pindex = selected;
  139. G_debug(3, "Number of conflicting points: %d", pindex);
  140. /* initialize matrices */
  141. matrix_init(pindex, pindex, &k);
  142. matrix_init(pindex, 1, &dx);
  143. matrix_init(pindex, 1, &dy);
  144. matrix_init(pindex, 1, &fx);
  145. matrix_init(pindex, 1, &fy);
  146. matrix_init(pindex, 1, &dx_old);
  147. matrix_init(pindex, 1, &dy_old);
  148. matrix_mult_scalar(0.0, &k);
  149. double a = 2.0 * alpha + 6.0 * beta;
  150. double b = -alpha - 4.0 * beta;
  151. double c = beta;
  152. /* build matrix */
  153. for (i = 0; i < index; i++) {
  154. int r = point_index[i];
  155. int l = line_index[i];
  156. if (r == -1)
  157. continue;
  158. k.a[r][r] += a;
  159. if (i + 1 < index && line_index[i + 1] == l &&
  160. point_index[i + 1] != -1)
  161. k.a[r][point_index[i + 1]] += b;
  162. if (i + 2 < index && line_index[i + 2] == l &&
  163. point_index[i + 2] != -1)
  164. k.a[r][point_index[i + 2]] += c;
  165. if (i >= 1 && line_index[i - 1] == l && point_index[i - 1] != -1)
  166. k.a[r][point_index[i - 1]] += b;
  167. if (i >= 2 && line_index[i - 2] == l && point_index[i - 2] != -1)
  168. k.a[r][point_index[i - 2]] += c;
  169. }
  170. matrix_add_identity(gama, &k);
  171. matrix_mult_scalar(0.0, &dx);
  172. matrix_mult_scalar(0.0, &dy);
  173. /*calculate the inverse */
  174. G_message(_("Inverting matrix..."));
  175. if (!matrix_inverse(&k, &kinv, 1))
  176. G_fatal_error(_("Unable to calculate the inverse matrix"));
  177. G_percent_reset();
  178. G_message(_("Resolving conflicts..."));
  179. for (iter = 0; iter < iterations; iter++) {
  180. int conflicts = 0;
  181. G_percent(iter, iterations, 1);
  182. matrix_mult_scalar(0.0, &fx);
  183. matrix_mult_scalar(0.0, &fy);
  184. matrix_mult_scalar(0.0, &dx_old);
  185. matrix_mult_scalar(0.0, &dy_old);
  186. matrix_add(&dx_old, &dx, &dx_old);
  187. matrix_add(&dy_old, &dy, &dy_old);
  188. /* calculate force vectors */
  189. for (i = 0; i < index; i++) {
  190. double cx, cy, f;
  191. if (point_index[i] == -1)
  192. continue;
  193. cx = dx.a[point_index[i]][0];
  194. cy = dy.a[point_index[i]][0];
  195. f = sqrt(cx * cx + cy * cy) * alpha;
  196. f /= threshold2;
  197. fx.a[point_index[i]][0] -= cx * f;
  198. fy.a[point_index[i]][0] -= cy * f;
  199. for (j = 1; j < index; j++) {
  200. if (line_index[i] == line_index[j] || first[j] ||
  201. point_index[i] == point_index[j] ||
  202. point_index[i] == point_index[j - 1])
  203. continue;
  204. /* if ith point is close to some segment then
  205. * apply force to ith point. If the distance
  206. * is zero, do not move the points */
  207. double d, pdist;
  208. POINT in;
  209. int status;
  210. d = dig_distance2_point_to_line(parray[i].x, parray[i].y,
  211. parray[i].z, parray[j].x,
  212. parray[j].y, parray[j].z,
  213. parray[j - 1].x,
  214. parray[j - 1].y,
  215. parray[j - 1].z, with_z,
  216. &in.x, &in.y, &in.z, &pdist,
  217. &status);
  218. POINT dir;
  219. if (d == 0.0 || d > threshold2)
  220. continue;
  221. d = sqrt(d);
  222. point_subtract(parray[i], in, &dir);
  223. point_scalar(dir, 1.0 / d, &dir);
  224. point_scalar(dir, 1.0 - d / threshold, &dir);
  225. fx.a[point_index[i]][0] += dir.x;
  226. fy.a[point_index[i]][0] += dir.y;
  227. conflicts++;
  228. }
  229. }
  230. /* calculate new displacement */
  231. matrix_mult_scalar(delta, &fx);
  232. matrix_mult_scalar(delta, &fy);
  233. matrix_mult_scalar(gama, &dx);
  234. matrix_mult_scalar(gama, &dy);
  235. matrix_add(&dx, &fx, &fx);
  236. matrix_add(&dy, &fy, &fy);
  237. matrix_mult(&kinv, &fx, &dx);
  238. matrix_mult(&kinv, &fy, &dy);
  239. for (i = 0; i < index; i++) {
  240. if (point_index[i] == -1)
  241. continue;
  242. parray[i].x +=
  243. dx.a[point_index[i]][0] - dx_old.a[point_index[i]][0];
  244. parray[i].y +=
  245. dy.a[point_index[i]][0] - dy_old.a[point_index[i]][0];
  246. }
  247. }
  248. index = 0;
  249. for (i = 1; i <= n_lines; i++) {
  250. type = Vect_read_line(In, Points, Cats, i);
  251. if (type != GV_LINE ||
  252. (layer > 0 && !Vect_cats_in_constraint(Cats, layer, cat_list))) {
  253. Vect_write_line(Out, type, Points, Cats);
  254. continue;
  255. }
  256. for (j = 0; j < Points->n_points; j++) {
  257. Points->x[j] = parray[index].x;
  258. Points->y[j] = parray[index].y;
  259. index++;
  260. }
  261. Vect_write_line(Out, type, Points, Cats);
  262. }
  263. G_free(parray);
  264. G_free(pset);
  265. G_free(point_index);
  266. G_free(first);
  267. G_free(line_index);
  268. G_free(need);
  269. G_free(sel);
  270. G_free(tmp_index);
  271. matrix_free(&k);
  272. matrix_free(&kinv);
  273. matrix_free(&dx);
  274. matrix_free(&dy);
  275. matrix_free(&fx);
  276. matrix_free(&fy);
  277. matrix_free(&dx_old);
  278. matrix_free(&dy_old);
  279. return 0;
  280. }