area.c 10 KB

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