area.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*!
  2. \file area.c
  3. \brief Vector library - area feature related fns
  4. Higher level functions for reading/writing/manipulating vectors.
  5. (C) 2001-2008 by the GRASS Development Team
  6. This program is free software under the
  7. GNU General Public License (>=v2).
  8. Read the file COPYING that comes with GRASS
  9. for details.
  10. \author Original author CERL, probably Dave Gerdes or Mike Higgins.
  11. Update to GRASS 5.7 Radim Blazek and David D. Gray.
  12. \date 2001-2008
  13. */
  14. #include <stdlib.h>
  15. #include <grass/gis.h>
  16. #include <grass/Vect.h>
  17. #include <grass/glocale.h>
  18. /*!
  19. \brief Returns the polygon array of points in BPoints
  20. \param Map vector map
  21. \param area area id
  22. \param[out] BPoints points array
  23. \return number of points
  24. \return -1 on error
  25. */
  26. int
  27. Vect_get_area_points(struct Map_info *Map,
  28. int area, struct line_pnts *BPoints)
  29. {
  30. int i, line, aline, dir;
  31. struct Plus_head *Plus;
  32. P_AREA *Area;
  33. static int first_time = 1;
  34. static struct line_pnts *Points;
  35. G_debug(3, "Vect_get_area_points(): area = %d", area);
  36. BPoints->n_points = 0;
  37. Plus = &(Map->plus);
  38. Area = Plus->Area[area];
  39. if (Area == NULL) { /* dead area */
  40. G_warning(_("Attempt to read points of nonexistent area"));
  41. return -1; /* error , because we should not read dead areas */
  42. }
  43. if (first_time == 1) {
  44. Points = Vect_new_line_struct();
  45. first_time = 0;
  46. }
  47. G_debug(3, " n_lines = %d", Area->n_lines);
  48. for (i = 0; i < Area->n_lines; i++) {
  49. line = Area->lines[i];
  50. aline = abs(line);
  51. G_debug(3, " append line(%d) = %d", i, line);
  52. if (0 > Vect_read_line(Map, Points, NULL, aline)) {
  53. G_fatal_error("Cannot read line %d", aline);
  54. }
  55. G_debug(3, " line n_points = %d", Points->n_points);
  56. if (line > 0)
  57. dir = GV_FORWARD;
  58. else
  59. dir = GV_BACKWARD;
  60. Vect_append_points(BPoints, Points, dir);
  61. if (i != (Area->n_lines - 1)) /* all but not last */
  62. BPoints->n_points--;
  63. G_debug(3, " area n_points = %d", BPoints->n_points);
  64. }
  65. return (BPoints->n_points);
  66. }
  67. /*!
  68. \brief Returns the polygon array of points in BPoints
  69. \param Map vector map
  70. \param isle island id
  71. \param[out] BPoints points array
  72. \return number of points or -1 on error
  73. */
  74. int
  75. Vect_get_isle_points(struct Map_info *Map,
  76. int isle, struct line_pnts *BPoints)
  77. {
  78. int i, line, aline, dir;
  79. struct Plus_head *Plus;
  80. P_ISLE *Isle;
  81. static int first_time = 1;
  82. static struct line_pnts *Points;
  83. G_debug(3, "Vect_get_isle_points(): isle = %d", isle);
  84. BPoints->n_points = 0;
  85. Plus = &(Map->plus);
  86. Isle = Plus->Isle[isle];
  87. if (first_time == 1) {
  88. Points = Vect_new_line_struct();
  89. first_time = 0;
  90. }
  91. G_debug(3, " n_lines = %d", Isle->n_lines);
  92. for (i = 0; i < Isle->n_lines; i++) {
  93. line = Isle->lines[i];
  94. aline = abs(line);
  95. G_debug(3, " append line(%d) = %d", i, line);
  96. if (0 > Vect_read_line(Map, Points, NULL, aline)) {
  97. G_fatal_error(_("Unable to read line %d"), aline);
  98. }
  99. G_debug(3, " line n_points = %d", Points->n_points);
  100. if (line > 0)
  101. dir = GV_FORWARD;
  102. else
  103. dir = GV_BACKWARD;
  104. Vect_append_points(BPoints, Points, dir);
  105. if (i != (Isle->n_lines - 1)) /* all but not last */
  106. BPoints->n_points--;
  107. G_debug(3, " isle n_points = %d", BPoints->n_points);
  108. }
  109. return (BPoints->n_points);
  110. }
  111. /*!
  112. \brief Returns centroid number of area
  113. \param Map vector map
  114. \param area area id
  115. \return centroid number of area
  116. \return 0 if no centroid found
  117. */
  118. int Vect_get_area_centroid(struct Map_info *Map, int area)
  119. {
  120. struct Plus_head *Plus;
  121. P_AREA *Area;
  122. G_debug(3, "Vect_get_area_centroid(): area = %d", area);
  123. Plus = &(Map->plus);
  124. Area = Plus->Area[area];
  125. if (Area == NULL)
  126. G_fatal_error(_("Attempt to read topo for dead area (%d)"), area);
  127. return (Area->centroid);
  128. }
  129. /*!
  130. \brief Creates list of boundaries for area
  131. \param Map vector map
  132. \param area area id
  133. \param List pointer to list of boundaries
  134. \return number of boundaries
  135. */
  136. int
  137. Vect_get_area_boundaries(struct Map_info *Map, int area, struct ilist *List)
  138. {
  139. int i, line;
  140. struct Plus_head *Plus;
  141. P_AREA *Area;
  142. G_debug(3, "Vect_get_area_boundaries(): area = %d", area);
  143. Vect_reset_list(List);
  144. Plus = &(Map->plus);
  145. Area = Plus->Area[area];
  146. if (Area == NULL)
  147. G_fatal_error(_("Attempt to read topo for dead area (%d)"), area);
  148. for (i = 0; i < Area->n_lines; i++) {
  149. line = Area->lines[i];
  150. Vect_list_append(List, line);
  151. }
  152. return (List->n_values);
  153. }
  154. /*!
  155. \brief Creates list of boundaries for isle
  156. \param Map vector map
  157. \param isle island number
  158. \param List pointer to list where boundaries are stored
  159. \return number of boundaries
  160. */
  161. int
  162. Vect_get_isle_boundaries(struct Map_info *Map, int isle, struct ilist *List)
  163. {
  164. int i, line;
  165. struct Plus_head *Plus;
  166. P_ISLE *Isle;
  167. G_debug(3, "Vect_get_isle_boundaries(): isle = %d", isle);
  168. Vect_reset_list(List);
  169. Plus = &(Map->plus);
  170. Isle = Plus->Isle[isle];
  171. if (Isle == NULL)
  172. G_fatal_error("Attempt to read topo for dead isle (%d)", isle);
  173. for (i = 0; i < Isle->n_lines; i++) {
  174. line = Isle->lines[i];
  175. Vect_list_append(List, line);
  176. }
  177. return (List->n_values);
  178. }
  179. /*!
  180. \brief Returns number of isles for area
  181. \param Map vector map
  182. \param area area id
  183. \return number of isles for area
  184. \return 0 if area not found
  185. */
  186. int Vect_get_area_num_isles(struct Map_info *Map, int area)
  187. {
  188. struct Plus_head *Plus;
  189. P_AREA *Area;
  190. G_debug(3, "Vect_get_area_num_isles(): area = %d", area);
  191. Plus = &(Map->plus);
  192. Area = Plus->Area[area];
  193. if (Area == NULL)
  194. G_fatal_error(_("Attempt to read topo for dead area (%d)"), area);
  195. G_debug(3, " n_isles = %d", Area->n_isles);
  196. return (Area->n_isles);
  197. }
  198. /*!
  199. \brief Returns isle for area
  200. \param Map vector map
  201. \param area area id
  202. \param isle isle id
  203. \return isles for area
  204. \return 0 if no isle found
  205. */
  206. int Vect_get_area_isle(struct Map_info *Map, int area, int isle)
  207. {
  208. struct Plus_head *Plus;
  209. P_AREA *Area;
  210. G_debug(3, "Vect_get_area_isle(): area = %d isle = %d", area, isle);
  211. Plus = &(Map->plus);
  212. Area = Plus->Area[area];
  213. if (Area == NULL)
  214. G_fatal_error(_("Attempt to read topo for dead area (%d)"), area);
  215. G_debug(3, " -> isle = %d", Area->isles[isle]);
  216. return (Area->isles[isle]);
  217. }
  218. /*!
  219. \brief Returns area for isle
  220. \param Map vector
  221. \param isle island number
  222. \return area id
  223. \return 0 area not found
  224. */
  225. int Vect_get_isle_area(struct Map_info *Map, int isle)
  226. {
  227. struct Plus_head *Plus;
  228. P_ISLE *Isle;
  229. G_debug(3, "Vect_get_isle_area(): isle = %d", isle);
  230. Plus = &(Map->plus);
  231. Isle = Plus->Isle[isle];
  232. if (Isle == NULL)
  233. G_fatal_error(_("Attempt to read topo for dead isle (%d)"), isle);
  234. G_debug(3, " -> area = %d", Isle->area);
  235. return (Isle->area);
  236. }
  237. /*!
  238. \brief Calculate area perimeter
  239. \param Points list of points defining area boundary
  240. \return area perimeter
  241. */
  242. double Vect_area_perimeter(struct line_pnts *Points)
  243. {
  244. return Vect_line_length(Points);
  245. }
  246. /*!
  247. \brief Returns 1 if point is in area
  248. \param Map vector map
  249. \param area area id
  250. \param x,y point coordinates
  251. \return 1 if point is in area
  252. \return 0 if not
  253. */
  254. int Vect_point_in_area(struct Map_info *Map, int area, double x, double y)
  255. {
  256. int i, isle;
  257. struct Plus_head *Plus;
  258. P_AREA *Area;
  259. int poly;
  260. Plus = &(Map->plus);
  261. Area = Plus->Area[area];
  262. if (Area == NULL)
  263. return 0;
  264. poly = Vect_point_in_area_outer_ring(x, y, Map, area);
  265. if (poly == 0)
  266. return 0; /* includes area boundary (poly == 2), OK? */
  267. /* check if in islands */
  268. for (i = 0; i < Area->n_isles; i++) {
  269. isle = Area->isles[i];
  270. poly = Vect_point_in_island(x, y, Map, isle);
  271. if (poly >= 1)
  272. return 0; /* excludes island boundary (poly == 2), OK? */
  273. }
  274. return 1;
  275. }
  276. /*!
  277. \brief Returns area of area without areas of isles
  278. \param Map vector map
  279. \param area area id
  280. \return area of area without areas of isles
  281. */
  282. double Vect_get_area_area(struct Map_info *Map, int area)
  283. {
  284. struct Plus_head *Plus;
  285. P_AREA *Area;
  286. struct line_pnts *Points;
  287. double size;
  288. int i;
  289. static int first_time = 1;
  290. G_debug(3, "Vect_get_area_area(): area = %d", area);
  291. if (first_time == 1) {
  292. G_begin_polygon_area_calculations();
  293. first_time = 0;
  294. }
  295. Points = Vect_new_line_struct();
  296. Plus = &(Map->plus);
  297. Area = Plus->Area[area];
  298. Vect_get_area_points(Map, area, Points);
  299. size = G_area_of_polygon(Points->x, Points->y, Points->n_points);
  300. /* substructing island areas */
  301. for (i = 0; i < Area->n_isles; i++) {
  302. Vect_get_isle_points(Map, Area->isles[i], Points);
  303. size -= G_area_of_polygon(Points->x, Points->y, Points->n_points);
  304. }
  305. Vect_destroy_line_struct(Points);
  306. G_debug(3, " area = %f", size);
  307. return (size);
  308. }
  309. /*!
  310. \brief Get area categories
  311. \param Map vector map
  312. \param area area id
  313. \param[out] Cats list of categories
  314. \return 0 OK centroid found (but may be without categories)
  315. \return 1 no centroid found
  316. */
  317. int Vect_get_area_cats(struct Map_info *Map, int area, struct line_cats *Cats)
  318. {
  319. int centroid;
  320. Vect_reset_cats(Cats);
  321. centroid = Vect_get_area_centroid(Map, area);
  322. if (centroid > 0) {
  323. Vect_read_line(Map, NULL, Cats, centroid);
  324. }
  325. else {
  326. return 1; /* no centroid */
  327. }
  328. return 0;
  329. }
  330. /*!
  331. \brief Find FIRST category of given field and area
  332. \param Map vector map
  333. \param area area id
  334. \param field layer number
  335. \return first found category of given field
  336. \return -1 no centroid or no category found
  337. */
  338. int Vect_get_area_cat(struct Map_info *Map, int area, int field)
  339. {
  340. int i;
  341. static struct line_cats *Cats = NULL;
  342. if (!Cats)
  343. Cats = Vect_new_cats_struct();
  344. else
  345. Vect_reset_cats(Cats);
  346. if (Vect_get_area_cats(Map, area, Cats) == 1 || Cats->n_cats == 0) {
  347. return -1;
  348. }
  349. for (i = 0; i < Cats->n_cats; i++) {
  350. if (Cats->field[i] == field) {
  351. return Cats->cat[i];
  352. }
  353. }
  354. return -1;
  355. }