lines.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. for (line_num = 1; line_num <= nlines; line_num++) {
  69. type = Vect_read_line(Map, Points, Cats, line_num);
  70. if (!(type & options.type))
  71. continue;
  72. found = 0;
  73. /* Find left/right area cats if necessary */
  74. if (options.option == O_SIDES && type == GV_BOUNDARY) {
  75. int area_left, area_right, centroid;
  76. Vect_get_line_areas(Map, line_num, &area_left, &area_right);
  77. /* left */
  78. Vect_reset_cats(LCats);
  79. if (area_left < 0)
  80. area_left = Vect_get_isle_area(Map, abs(area_left));
  81. if (area_left > 0) {
  82. centroid = Vect_get_area_centroid(Map, area_left);
  83. if (centroid > 0) {
  84. Vect_read_line(Map, NULL, LCats, centroid);
  85. }
  86. }
  87. /* right */
  88. Vect_reset_cats(RCats);
  89. if (area_right < 0)
  90. area_right = Vect_get_isle_area(Map, abs(area_right));
  91. if (area_right > 0) {
  92. centroid = Vect_get_area_centroid(Map, area_right);
  93. if (centroid > 0) {
  94. Vect_read_line(Map, NULL, RCats, centroid);
  95. }
  96. }
  97. }
  98. for (i = 0; i < Cats->n_cats; i++) {
  99. if (Cats->field[i] == options.field) {
  100. idx = find_cat(Cats->cat[i], 1);
  101. if (options.option == O_COUNT) {
  102. Values[idx].count1++;
  103. }
  104. else if (options.option == O_LENGTH && (type & GV_LINES)) {
  105. /* Calculate line length */
  106. len = Vect_line_geodesic_length(Points);
  107. if (G_projection () != PROJECTION_LL)
  108. len = len * G_database_units_to_meters_factor();
  109. Values[idx].d1 += len;
  110. }
  111. else if (options.option == O_COOR && (type & GV_POINTS)) {
  112. /* overwrite by last one, count is used in update */
  113. Values[idx].d1 = Points->x[0];
  114. Values[idx].d2 = Points->y[0];
  115. Values[idx].d3 = Points->z[0];
  116. Values[idx].count1++;
  117. }
  118. else if (options.option == O_START && (type & GV_LINES)) {
  119. /* overwrite by last one, count is used in update */
  120. Values[idx].d1 = Points->x[0];
  121. Values[idx].d2 = Points->y[0];
  122. Values[idx].d3 = Points->z[0];
  123. Values[idx].count1++;
  124. }
  125. else if (options.option == O_END && (type & GV_LINES)) {
  126. /* overwrite by last one, count is used in update */
  127. Values[idx].d1 = Points->x[Points->n_points - 1];
  128. Values[idx].d2 = Points->y[Points->n_points - 1];
  129. Values[idx].d3 = Points->z[Points->n_points - 1];
  130. Values[idx].count1++;
  131. }
  132. else if (options.option == O_SIDES && type == GV_BOUNDARY) {
  133. read_side_cats(LCats, &(Values[idx].i1),
  134. &(Values[idx].count1));
  135. read_side_cats(RCats, &(Values[idx].i2),
  136. &(Values[idx].count2));
  137. }
  138. else if (options.option == O_SLOPE && (type & GV_LINES)) {
  139. /* Calculate line slope */
  140. len = length(Points->n_points, Points->x, Points->y);
  141. slope =
  142. (Points->z[Points->n_points - 1] -
  143. Points->z[0]) / len;
  144. Values[idx].d1 += slope;
  145. }
  146. else if (options.option == O_SINUOUS && (type & GV_LINES)) {
  147. /* Calculate line length / distance between end points */
  148. Vect_reset_line(EndPoints);
  149. Vect_append_point(EndPoints, Points->x[0], Points->y[0],
  150. Points->z[0]);
  151. Vect_append_point(EndPoints,
  152. Points->x[Points->n_points - 1],
  153. Points->y[Points->n_points - 1],
  154. Points->z[Points->n_points - 1]);
  155. len = Vect_line_geodesic_length(Points);
  156. dist = Vect_line_geodesic_length(EndPoints);
  157. Values[idx].d1 = len / dist;
  158. }
  159. else if (options.option == O_AZIMUTH && (type & GV_LINES)) {
  160. /* Calculate azimuth between line start and end points in degrees */
  161. dx = (Points->x[Points->n_points - 1] - Points->x[0]);
  162. dy = (Points->y[Points->n_points - 1] - Points->y[0]);
  163. /* If line is closed... */
  164. if (dx == 0.0 && dy == 0.0)
  165. azimuth = -1;
  166. else {
  167. azimuth = atan2(dx,dy);
  168. if (azimuth < 0) azimuth = azimuth + 2 * M_PI;
  169. }
  170. Values[idx].d1 = azimuth;
  171. }
  172. found = 1;
  173. }
  174. }
  175. if (!found) { /* Values for no category (cat = -1) are reported at the end */
  176. idx = find_cat(-1, 1);
  177. if (options.option == O_COUNT) {
  178. Values[idx].count1++;
  179. }
  180. else if (options.option == O_LENGTH && (type & GV_LINES)) {
  181. len = Vect_line_geodesic_length(Points);
  182. Values[idx].d1 += len;
  183. }
  184. else if (options.option == O_COOR && (type & GV_POINTS)) {
  185. Values[idx].d1 = Points->x[0];
  186. Values[idx].d2 = Points->y[0];
  187. Values[idx].d3 = Points->z[0];
  188. Values[idx].count1++;
  189. }
  190. else if (options.option == O_START && (type & GV_LINES)) {
  191. Values[idx].d1 = Points->x[0];
  192. Values[idx].d2 = Points->y[0];
  193. Values[idx].d3 = Points->z[0];
  194. Values[idx].count1++;
  195. }
  196. else if (options.option == O_END && (type & GV_LINES)) {
  197. Values[idx].d1 = Points->x[Points->n_points - 1];
  198. Values[idx].d2 = Points->y[Points->n_points - 1];
  199. Values[idx].d3 = Points->z[Points->n_points - 1];
  200. Values[idx].count1++;
  201. }
  202. else if (options.option == O_SIDES && type == GV_BOUNDARY) {
  203. read_side_cats(LCats, &(Values[idx].i1),
  204. &(Values[idx].count1));
  205. read_side_cats(RCats, &(Values[idx].i2),
  206. &(Values[idx].count2));
  207. }
  208. else if (options.option == O_SLOPE && (type & GV_LINES)) {
  209. /* Calculate line slope */
  210. len = length(Points->n_points, Points->x, Points->y);
  211. slope =
  212. (Points->z[Points->n_points - 1] - Points->z[0]) / len;
  213. Values[idx].d1 += slope;
  214. }
  215. else if (options.option == O_SINUOUS && (type & GV_LINES)) {
  216. /* Calculate line length / distance between end points */
  217. Vect_reset_line(EndPoints);
  218. Vect_append_point(EndPoints, Points->x[0], Points->y[0],
  219. Points->z[0]);
  220. Vect_append_point(EndPoints, Points->x[Points->n_points - 1],
  221. Points->y[Points->n_points - 1],
  222. Points->z[Points->n_points - 1]);
  223. len = Vect_line_geodesic_length(Points);
  224. dist = Vect_line_geodesic_length(EndPoints);
  225. Values[idx].d1 = len / dist;
  226. }
  227. else if (options.option == O_AZIMUTH && (type & GV_LINES)) {
  228. /* Calculate azimuth between line start and end points in degrees */
  229. dx = (Points->x[Points->n_points - 1] - Points->x[0]);
  230. dy = (Points->y[Points->n_points - 1] - Points->y[0]);
  231. /* If line is closed... */
  232. if (dx == 0.0 && dy == 0.0)
  233. azimuth = -1;
  234. else {
  235. azimuth = atan2(dx,dy);
  236. if (azimuth < 0) azimuth = azimuth + 2 * M_PI;
  237. }
  238. Values[idx].d1 = azimuth;
  239. }
  240. }
  241. G_percent(line_num, nlines, 2);
  242. }
  243. return 0;
  244. }