box.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. /*!
  2. \file box.c
  3. \brief Vector library - bounding box
  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 Radim Blazek
  11. */
  12. #include <grass/config.h>
  13. #include <stdlib.h>
  14. #include <grass/gis.h>
  15. #include <grass/vector.h>
  16. /*!
  17. \brief Tests for point in box
  18. \param x,y,z coordinates
  19. \param Box boundary box
  20. \return 1 point is in box
  21. \return 0 point is not in box
  22. */
  23. int Vect_point_in_box(double x, double y, double z, const BOUND_BOX * Box)
  24. {
  25. if (x >= Box->W && x <= Box->E &&
  26. y >= Box->S && y <= Box->N && z >= Box->B && z <= Box->T) {
  27. return 1;
  28. }
  29. return 0;
  30. }
  31. /*!
  32. \brief Tests for overlap of two boxes
  33. \param A boundary box A
  34. \param B boundary box B
  35. \return 1 boxes overlap
  36. \return 0 boxes do not overlap
  37. */
  38. int Vect_box_overlap(const BOUND_BOX * A, const BOUND_BOX * B)
  39. {
  40. if (A->E < B->W || A->W > B->E ||
  41. A->N < B->S || A->S > B->N || A->T < B->B || A->B > B->T) {
  42. return 0;
  43. }
  44. return 1;
  45. }
  46. /*!
  47. \brief Copy box B to box A
  48. \param A boundary A
  49. \param B boundary B
  50. \return 1
  51. */
  52. int Vect_box_copy(BOUND_BOX * A, const BOUND_BOX * B)
  53. {
  54. A->N = B->N;
  55. A->S = B->S;
  56. A->E = B->E;
  57. A->W = B->W;
  58. A->T = B->T;
  59. A->B = B->B;
  60. return 1;
  61. }
  62. /*!
  63. \brief Extend box A by box B
  64. \param A boundary A
  65. \param B boundary B
  66. \return 1
  67. */
  68. int Vect_box_extend(BOUND_BOX * A, const BOUND_BOX * B)
  69. {
  70. if (B->N > A->N)
  71. A->N = B->N;
  72. if (B->S < A->S)
  73. A->S = B->S;
  74. if (B->E > A->E)
  75. A->E = B->E;
  76. if (B->W < A->W)
  77. A->W = B->W;
  78. if (B->T > A->T)
  79. A->T = B->T;
  80. if (B->B < A->B)
  81. A->B = B->B;
  82. return 1;
  83. }
  84. /*!
  85. * \brief Clip coordinates to box, if necessary, lines extending outside of a box.
  86. *
  87. * A line represented by the coordinates <em>x, y</em> and <em>c_x, c_y</em> is clipped to
  88. * the window defined by <em>s</em> (south), <em>n</em> (north), <em>w</em>
  89. * (west), and <em>e</em> (east). Note that the following constraints must be
  90. * true:
  91. * w <e
  92. * s <n
  93. * The <em>x</em> and <em>c_x</em> are values to be compared to <em>w</em> and
  94. * <em>e.</em> The <em>y</em> and <em>c_y</em> are values to be compared to
  95. * <em>s</em> and <em>n.</em>
  96. * The <em>x</em> and <em>c_x</em> values returned lie between <em>w</em> and
  97. * <em>e.</em> The <em>y</em> and <em>c_y</em> values returned lie between
  98. * <em>s</em> and <em>n.</em>
  99. *
  100. * \param x, y coordinates (w, e)
  101. * \param c_x,c_y coordinates (s, n)
  102. * \param Box boundary box
  103. *
  104. * \return 1 if any clipping occured
  105. * \return 0 otherwise
  106. */
  107. int
  108. Vect_box_clip(double *x, double *y, double *c_x, double *c_y, const BOUND_BOX * Box)
  109. {
  110. int mod;
  111. mod = 0;
  112. if (*x < Box->W) {
  113. if (*c_x != *x)
  114. *y = *y + (Box->W - *x) / (*c_x - *x) * (*c_y - *y);
  115. *x = Box->W;
  116. mod = 1;
  117. }
  118. if (*x > Box->E) {
  119. if (*c_x != *x)
  120. *y = *y + (Box->E - *x) / (*c_x - *x) * (*c_y - *y);
  121. *x = Box->E;
  122. mod = 1;
  123. }
  124. if (*c_x < Box->W) {
  125. if (*c_x != *x)
  126. *c_y = *c_y + (Box->W - *c_x) / (*x - *c_x) * (*y - *c_y);
  127. *c_x = Box->W;
  128. mod = 1;
  129. }
  130. if (*c_x > Box->E) {
  131. if (*c_x != *x)
  132. *c_y = *c_y + (Box->E - *c_x) / (*x - *c_x) * (*y - *c_y);
  133. *c_x = Box->E;
  134. mod = 1;
  135. }
  136. if (*y < Box->S) {
  137. if (*c_y != *y)
  138. *x = *x + (Box->S - *y) / (*c_y - *y) * (*c_x - *x);
  139. *y = Box->S;
  140. mod = 1;
  141. }
  142. if (*y > Box->N) {
  143. if (*c_y != *y)
  144. *x = *x + (Box->N - *y) / (*c_y - *y) * (*c_x - *x);
  145. *y = Box->N;
  146. mod = 1;
  147. }
  148. if (*c_y < Box->S) {
  149. if (*c_y != *y)
  150. *c_x = *c_x + (Box->S - *c_y) / (*y - *c_y) * (*x - *c_x);
  151. *c_y = Box->S;
  152. mod = 1;
  153. }
  154. if (*c_y > Box->N) {
  155. if (*c_y != *y)
  156. *c_x = *c_x + (Box->N - *c_y) / (*y - *c_y) * (*x - *c_x);
  157. *c_y = Box->N;
  158. mod = 1;
  159. }
  160. return (mod);
  161. }
  162. /*!
  163. \brief Get bounding box of given feature
  164. \param Map vector map
  165. \param line feature id
  166. \param[out] Box bounding box
  167. \return 1 on success
  168. \return 0 line is dead
  169. */
  170. int Vect_get_line_box(const struct Map_info *Map, int line, BOUND_BOX * Box)
  171. {
  172. const struct Plus_head *Plus;
  173. P_LINE *Line;
  174. Plus = &(Map->plus);
  175. Line = Plus->Line[line];
  176. if (Line == NULL) { /* dead */
  177. Box->N = 0;
  178. Box->S = 0;
  179. Box->E = 0;
  180. Box->W = 0;
  181. Box->T = 0;
  182. Box->B = 0;
  183. return 0;
  184. }
  185. else {
  186. Box->N = Line->N;
  187. Box->S = Line->S;
  188. Box->E = Line->E;
  189. Box->W = Line->W;
  190. Box->T = Line->T;
  191. Box->B = Line->B;
  192. }
  193. return 1;
  194. }
  195. /*!
  196. \brief Get bounding box of area
  197. \param Map vector map
  198. \param area area id
  199. \param[out] Box bounding box
  200. \return 1 on success
  201. \return 0 area is dead
  202. */
  203. int Vect_get_area_box(const struct Map_info *Map, int area, BOUND_BOX * Box)
  204. {
  205. const struct Plus_head *Plus;
  206. P_AREA *Area;
  207. Plus = &(Map->plus);
  208. Area = Plus->Area[area];
  209. if (Area == NULL) { /* dead */
  210. Box->N = 0;
  211. Box->S = 0;
  212. Box->E = 0;
  213. Box->W = 0;
  214. Box->T = 0;
  215. Box->B = 0;
  216. return 0;
  217. }
  218. else {
  219. Box->N = Area->N;
  220. Box->S = Area->S;
  221. Box->E = Area->E;
  222. Box->W = Area->W;
  223. Box->T = Area->T;
  224. Box->B = Area->B;
  225. }
  226. return 1;
  227. }
  228. /*!
  229. \brief Get bounding box of isle
  230. \param Map vector map
  231. \param isle isle id
  232. \param[out] Box bounding box
  233. \return 1 on success
  234. \return 0 isle is dead
  235. */
  236. int Vect_get_isle_box(const struct Map_info *Map, int isle, BOUND_BOX * Box)
  237. {
  238. const struct Plus_head *Plus;
  239. P_ISLE *Isle;
  240. Plus = &(Map->plus);
  241. Isle = Plus->Isle[isle];
  242. if (Isle == NULL) { /* dead */
  243. Box->N = 0;
  244. Box->S = 0;
  245. Box->E = 0;
  246. Box->W = 0;
  247. Box->T = 0;
  248. Box->B = 0;
  249. return 0;
  250. }
  251. else {
  252. Box->N = Isle->N;
  253. Box->S = Isle->S;
  254. Box->E = Isle->E;
  255. Box->W = Isle->W;
  256. Box->T = Isle->T;
  257. Box->B = Isle->B;
  258. }
  259. return 1;
  260. }
  261. /*!
  262. \brief Get bounding box of map (all features in the map)
  263. \param Map vector map
  264. \param[out] Box bouding box
  265. \return 1 on success
  266. \return 0 on error
  267. */
  268. int Vect_get_map_box(const struct Map_info *Map, BOUND_BOX * Box)
  269. {
  270. const struct Plus_head *Plus;
  271. Plus = &(Map->plus);
  272. Box->N = Plus->box.N;
  273. Box->S = Plus->box.S;
  274. Box->E = Plus->box.E;
  275. Box->W = Plus->box.W;
  276. Box->T = Plus->box.T;
  277. Box->B = Plus->box.B;
  278. return 1;
  279. }
  280. /*!
  281. \brief Copy region window to bounding box
  282. \param Window region structure (raster-based)
  283. \param[out] Box boundary box (vector-based)
  284. \return 1 on success
  285. \return 0 on error
  286. */
  287. int Vect_region_box(const struct Cell_head *Window, BOUND_BOX * Box)
  288. {
  289. Box->N = Window->north;
  290. Box->S = Window->south;
  291. Box->E = Window->east;
  292. Box->W = Window->west;
  293. Box->T = PORT_DOUBLE_MAX;
  294. Box->B = -PORT_DOUBLE_MAX;
  295. return 1;
  296. }