lines.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <grass/glocale.h>
  5. #include "global.h"
  6. /* Read area cats for one side
  7. * val - pointer where value is stored
  8. * count - pointer to count of cats read
  9. * ACats - area categories
  10. */
  11. void read_side_cats(struct line_cats *ACats, int *val, int *count)
  12. {
  13. int i, found;
  14. G_debug(4, "read_side_cats() n_cats = %d, val = %d, count = %d",
  15. ACats->n_cats, *val, *count);
  16. if (*count > 1)
  17. return; /* it doesn't make sense to read/check more cats */
  18. found = 0;
  19. for (i = 0; i < ACats->n_cats; i++) {
  20. if (ACats->field[i] == options.qfield) {
  21. found = 1;
  22. if (*count == 0) { /* first */
  23. *val = ACats->cat[i]; /* set value to first found cat */
  24. (*count)++;
  25. }
  26. else { /* *count == 1 */
  27. /* Check if it is the same category */
  28. if (*val != ACats->cat[i]) {
  29. *count = 2;
  30. break; /* no need to read more */
  31. }
  32. }
  33. }
  34. }
  35. if (!found) { /* i.e. area cat is NULL (-1) */
  36. if (*count == 0) { /* first */
  37. *val = -1;
  38. (*count)++;
  39. }
  40. else { /* *count == 1 */
  41. /* Check if it is the same category */
  42. if (*val != -1) {
  43. *count = 2;
  44. }
  45. }
  46. }
  47. }
  48. /*
  49. * Read: - points/centroids : cat,count,coor
  50. * - lines/boundaries : cat,count,length,slope,sinuous
  51. */
  52. int read_lines(struct Map_info *Map)
  53. {
  54. int i, idx, nlines, type, found;
  55. register int line_num;
  56. struct line_pnts *Points, *EndPoints;
  57. struct line_cats *Cats, *LCats, *RCats;
  58. double len, slope, dist, dx, dy, azimuth;
  59. /* Initialize the Point struct */
  60. Points = Vect_new_line_struct();
  61. EndPoints = Vect_new_line_struct();
  62. Cats = Vect_new_cats_struct();
  63. LCats = Vect_new_cats_struct();
  64. RCats = Vect_new_cats_struct();
  65. G_message(_("Reading features..."));
  66. /* Cycle through all lines */
  67. nlines = Vect_get_num_lines(Map);
  68. G_percent(0, nlines, 2);
  69. for (line_num = 1; line_num <= nlines; line_num++) {
  70. type = Vect_read_line(Map, Points, Cats, line_num);
  71. if (!(type & options.type))
  72. continue;
  73. found = 0;
  74. /* Find left/right area cats if necessary */
  75. if (options.option == O_SIDES && type == GV_BOUNDARY) {
  76. int area_left, area_right, centroid;
  77. Vect_get_line_areas(Map, line_num, &area_left, &area_right);
  78. /* left */
  79. Vect_reset_cats(LCats);
  80. if (area_left < 0)
  81. area_left = Vect_get_isle_area(Map, abs(area_left));
  82. if (area_left > 0) {
  83. centroid = Vect_get_area_centroid(Map, area_left);
  84. if (centroid > 0) {
  85. Vect_read_line(Map, NULL, LCats, centroid);
  86. }
  87. }
  88. /* right */
  89. Vect_reset_cats(RCats);
  90. if (area_right < 0)
  91. area_right = Vect_get_isle_area(Map, abs(area_right));
  92. if (area_right > 0) {
  93. centroid = Vect_get_area_centroid(Map, area_right);
  94. if (centroid > 0) {
  95. Vect_read_line(Map, NULL, RCats, centroid);
  96. }
  97. }
  98. }
  99. for (i = 0; i < Cats->n_cats; i++) {
  100. if (Cats->field[i] == options.field) {
  101. idx = find_cat(Cats->cat[i], 1);
  102. if (options.option == O_COUNT) {
  103. Values[idx].count1++;
  104. }
  105. else if (options.option == O_LENGTH && (type & GV_LINES)) {
  106. /* Calculate line length */
  107. len = Vect_line_geodesic_length(Points);
  108. if (G_projection () != PROJECTION_LL)
  109. len = len * G_database_units_to_meters_factor();
  110. Values[idx].d1 += len;
  111. }
  112. else if (options.option == O_COOR && (type & GV_POINTS)) {
  113. /* overwrite by last one, count is used in update */
  114. Values[idx].d1 = Points->x[0];
  115. Values[idx].d2 = Points->y[0];
  116. Values[idx].d3 = Points->z[0];
  117. Values[idx].count1++;
  118. }
  119. else if (options.option == O_START && (type & GV_LINES)) {
  120. /* overwrite by last one, count is used in update */
  121. Values[idx].d1 = Points->x[0];
  122. Values[idx].d2 = Points->y[0];
  123. Values[idx].d3 = Points->z[0];
  124. Values[idx].count1++;
  125. }
  126. else if (options.option == O_END && (type & GV_LINES)) {
  127. /* overwrite by last one, count is used in update */
  128. Values[idx].d1 = Points->x[Points->n_points - 1];
  129. Values[idx].d2 = Points->y[Points->n_points - 1];
  130. Values[idx].d3 = Points->z[Points->n_points - 1];
  131. Values[idx].count1++;
  132. }
  133. else if (options.option == O_SIDES && type == GV_BOUNDARY) {
  134. read_side_cats(LCats, &(Values[idx].i1),
  135. &(Values[idx].count1));
  136. read_side_cats(RCats, &(Values[idx].i2),
  137. &(Values[idx].count2));
  138. }
  139. else if (options.option == O_SLOPE && (type & GV_LINES)) {
  140. /* Calculate line slope */
  141. len = length(Points->n_points, Points->x, Points->y);
  142. slope =
  143. (Points->z[Points->n_points - 1] -
  144. Points->z[0]) / len;
  145. Values[idx].d1 += slope;
  146. }
  147. else if (options.option == O_SINUOUS && (type & GV_LINES)) {
  148. /* Calculate line length / distance between end points */
  149. Vect_reset_line(EndPoints);
  150. Vect_append_point(EndPoints, Points->x[0], Points->y[0],
  151. Points->z[0]);
  152. Vect_append_point(EndPoints,
  153. Points->x[Points->n_points - 1],
  154. Points->y[Points->n_points - 1],
  155. Points->z[Points->n_points - 1]);
  156. len = Vect_line_geodesic_length(Points);
  157. dist = Vect_line_geodesic_length(EndPoints);
  158. Values[idx].d1 = len / dist;
  159. }
  160. else if (options.option == O_AZIMUTH && (type & GV_LINES)) {
  161. /* Calculate azimuth between line start and end points in degrees */
  162. dx = (Points->x[Points->n_points - 1] - Points->x[0]);
  163. dy = (Points->y[Points->n_points - 1] - Points->y[0]);
  164. /* If line is closed... */
  165. if (dx == 0.0 && dy == 0.0)
  166. azimuth = -1;
  167. else {
  168. azimuth = atan2(dx,dy);
  169. if (azimuth < 0) azimuth = azimuth + 2 * M_PI;
  170. }
  171. Values[idx].d1 = azimuth;
  172. }
  173. found = 1;
  174. }
  175. }
  176. if (!found) { /* Values for no category (cat = -1) are reported at the end */
  177. idx = find_cat(-1, 1);
  178. if (options.option == O_COUNT) {
  179. Values[idx].count1++;
  180. }
  181. else if (options.option == O_LENGTH && (type & GV_LINES)) {
  182. len = Vect_line_geodesic_length(Points);
  183. Values[idx].d1 += len;
  184. }
  185. else if (options.option == O_COOR && (type & GV_POINTS)) {
  186. Values[idx].d1 = Points->x[0];
  187. Values[idx].d2 = Points->y[0];
  188. Values[idx].d3 = Points->z[0];
  189. Values[idx].count1++;
  190. }
  191. else if (options.option == O_START && (type & GV_LINES)) {
  192. Values[idx].d1 = Points->x[0];
  193. Values[idx].d2 = Points->y[0];
  194. Values[idx].d3 = Points->z[0];
  195. Values[idx].count1++;
  196. }
  197. else if (options.option == O_END && (type & GV_LINES)) {
  198. Values[idx].d1 = Points->x[Points->n_points - 1];
  199. Values[idx].d2 = Points->y[Points->n_points - 1];
  200. Values[idx].d3 = Points->z[Points->n_points - 1];
  201. Values[idx].count1++;
  202. }
  203. else if (options.option == O_SIDES && type == GV_BOUNDARY) {
  204. read_side_cats(LCats, &(Values[idx].i1),
  205. &(Values[idx].count1));
  206. read_side_cats(RCats, &(Values[idx].i2),
  207. &(Values[idx].count2));
  208. }
  209. else if (options.option == O_SLOPE && (type & GV_LINES)) {
  210. /* Calculate line slope */
  211. len = length(Points->n_points, Points->x, Points->y);
  212. slope =
  213. (Points->z[Points->n_points - 1] - Points->z[0]) / len;
  214. Values[idx].d1 += slope;
  215. }
  216. else if (options.option == O_SINUOUS && (type & GV_LINES)) {
  217. /* Calculate line length / distance between end points */
  218. Vect_reset_line(EndPoints);
  219. Vect_append_point(EndPoints, Points->x[0], Points->y[0],
  220. Points->z[0]);
  221. Vect_append_point(EndPoints, Points->x[Points->n_points - 1],
  222. Points->y[Points->n_points - 1],
  223. Points->z[Points->n_points - 1]);
  224. len = Vect_line_geodesic_length(Points);
  225. dist = Vect_line_geodesic_length(EndPoints);
  226. Values[idx].d1 = len / dist;
  227. }
  228. else if (options.option == O_AZIMUTH && (type & GV_LINES)) {
  229. /* Calculate azimuth between line start and end points in degrees */
  230. dx = (Points->x[Points->n_points - 1] - Points->x[0]);
  231. dy = (Points->y[Points->n_points - 1] - Points->y[0]);
  232. /* If line is closed... */
  233. if (dx == 0.0 && dy == 0.0)
  234. azimuth = -1;
  235. else {
  236. azimuth = atan2(dx,dy);
  237. if (azimuth < 0) azimuth = azimuth + 2 * M_PI;
  238. }
  239. Values[idx].d1 = azimuth;
  240. }
  241. }
  242. G_percent(line_num, nlines, 2);
  243. }
  244. return 0;
  245. }