box.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. /*!
  2. \file lib/vector/Vlib/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 <stdlib.h>
  13. #include <grass/vector.h>
  14. #include <grass/glocale.h>
  15. /*!
  16. \brief Tests for point in box
  17. \param x,y,z coordinates
  18. \param Box boundary box
  19. \return 1 point is in box
  20. \return 0 point is not in box
  21. */
  22. int Vect_point_in_box(double x, double y, double z, const struct bound_box * Box)
  23. {
  24. if (x >= Box->W && x <= Box->E &&
  25. y >= Box->S && y <= Box->N && z >= Box->B && z <= Box->T) {
  26. return 1;
  27. }
  28. return 0;
  29. }
  30. /*!
  31. \brief Tests for overlap of two boxes
  32. \param A boundary box A
  33. \param B boundary box B
  34. \return 1 boxes overlap
  35. \return 0 boxes do not overlap
  36. */
  37. int Vect_box_overlap(const struct bound_box * A, const struct bound_box * B)
  38. {
  39. if (A->E < B->W || A->W > B->E ||
  40. A->N < B->S || A->S > B->N || A->T < B->B || A->B > B->T) {
  41. return 0;
  42. }
  43. return 1;
  44. }
  45. /*!
  46. \brief Copy box B to box A
  47. \param A boundary A
  48. \param B boundary B
  49. \return 1
  50. */
  51. int Vect_box_copy(struct bound_box * A, const struct bound_box * B)
  52. {
  53. A->N = B->N;
  54. A->S = B->S;
  55. A->E = B->E;
  56. A->W = B->W;
  57. A->T = B->T;
  58. A->B = B->B;
  59. return 1;
  60. }
  61. /*!
  62. \brief Extend box A by box B
  63. \param A boundary A
  64. \param B boundary B
  65. \return 1
  66. */
  67. int Vect_box_extend(struct bound_box * A, const struct bound_box * B)
  68. {
  69. if (B->N > A->N)
  70. A->N = B->N;
  71. if (B->S < A->S)
  72. A->S = B->S;
  73. if (B->E > A->E)
  74. A->E = B->E;
  75. if (B->W < A->W)
  76. A->W = B->W;
  77. if (B->T > A->T)
  78. A->T = B->T;
  79. if (B->B < A->B)
  80. A->B = B->B;
  81. return 1;
  82. }
  83. /*!
  84. * \brief Clip coordinates to box, if necessary, lines extending outside of a box.
  85. *
  86. * A line represented by the coordinates <em>x, y</em> and <em>c_x, c_y</em> is clipped to
  87. * the window defined by <em>s</em> (south), <em>n</em> (north), <em>w</em>
  88. * (west), and <em>e</em> (east). Note that the following constraints must be
  89. * true:
  90. * w <e
  91. * s <n
  92. * The <em>x</em> and <em>c_x</em> are values to be compared to <em>w</em> and
  93. * <em>e.</em> The <em>y</em> and <em>c_y</em> are values to be compared to
  94. * <em>s</em> and <em>n.</em>
  95. * The <em>x</em> and <em>c_x</em> values returned lie between <em>w</em> and
  96. * <em>e.</em> The <em>y</em> and <em>c_y</em> values returned lie between
  97. * <em>s</em> and <em>n.</em>
  98. *
  99. * \param x, y coordinates (w, e)
  100. * \param c_x,c_y coordinates (s, n)
  101. * \param Box boundary box
  102. *
  103. * \return 1 if any clipping occured
  104. * \return 0 otherwise
  105. */
  106. int
  107. Vect_box_clip(double *x, double *y, double *c_x, double *c_y, const struct bound_box * Box)
  108. {
  109. int mod;
  110. mod = 0;
  111. if (*x < Box->W) {
  112. if (*c_x != *x)
  113. *y = *y + (Box->W - *x) / (*c_x - *x) * (*c_y - *y);
  114. *x = Box->W;
  115. mod = 1;
  116. }
  117. if (*x > Box->E) {
  118. if (*c_x != *x)
  119. *y = *y + (Box->E - *x) / (*c_x - *x) * (*c_y - *y);
  120. *x = Box->E;
  121. mod = 1;
  122. }
  123. if (*c_x < Box->W) {
  124. if (*c_x != *x)
  125. *c_y = *c_y + (Box->W - *c_x) / (*x - *c_x) * (*y - *c_y);
  126. *c_x = Box->W;
  127. mod = 1;
  128. }
  129. if (*c_x > Box->E) {
  130. if (*c_x != *x)
  131. *c_y = *c_y + (Box->E - *c_x) / (*x - *c_x) * (*y - *c_y);
  132. *c_x = Box->E;
  133. mod = 1;
  134. }
  135. if (*y < Box->S) {
  136. if (*c_y != *y)
  137. *x = *x + (Box->S - *y) / (*c_y - *y) * (*c_x - *x);
  138. *y = Box->S;
  139. mod = 1;
  140. }
  141. if (*y > Box->N) {
  142. if (*c_y != *y)
  143. *x = *x + (Box->N - *y) / (*c_y - *y) * (*c_x - *x);
  144. *y = Box->N;
  145. mod = 1;
  146. }
  147. if (*c_y < Box->S) {
  148. if (*c_y != *y)
  149. *c_x = *c_x + (Box->S - *c_y) / (*y - *c_y) * (*x - *c_x);
  150. *c_y = Box->S;
  151. mod = 1;
  152. }
  153. if (*c_y > Box->N) {
  154. if (*c_y != *y)
  155. *c_x = *c_x + (Box->N - *c_y) / (*y - *c_y) * (*x - *c_x);
  156. *c_y = Box->N;
  157. mod = 1;
  158. }
  159. return (mod);
  160. }
  161. /*!
  162. \brief Get bounding box of given feature
  163. \param Map vector map
  164. \param line feature id
  165. \param[out] Box bounding box
  166. \return 1 on success
  167. \return 0 line is dead
  168. */
  169. int Vect_get_line_box(const struct Map_info *Map, int line, struct bound_box * Box)
  170. {
  171. struct Plus_head *Plus;
  172. struct P_line *Line;
  173. static struct line_pnts *Points = NULL;
  174. static struct boxlist *list = NULL;
  175. Plus = (struct Plus_head *)&(Map->plus);
  176. Line = Plus->Line[line];
  177. if (Line == NULL) { /* dead */
  178. G_zero(Box, sizeof(struct bound_box));
  179. return 0;
  180. }
  181. else {
  182. int type = Line->type;
  183. /* GV_POINTS: read line */
  184. if (type & GV_POINTS) {
  185. if (Points == NULL)
  186. Points = Vect_new_line_struct();
  187. Vect_read_line(Map, Points, NULL, line);
  188. dig_line_box(Points, Box);
  189. }
  190. /* all other: retrieve box from spatial index */
  191. else {
  192. int node = 0;
  193. struct bound_box bbox;
  194. if (type == GV_LINE) {
  195. struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
  196. node = topo->N1;
  197. }
  198. else if (type == GV_BOUNDARY) {
  199. struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
  200. node = topo->N1;
  201. }
  202. if (list == NULL) {
  203. list = Vect_new_boxlist(1);
  204. }
  205. Vect_reset_boxlist(list);
  206. bbox.N = Plus->Node[node]->y;
  207. bbox.S = Plus->Node[node]->y;
  208. bbox.E = Plus->Node[node]->x;
  209. bbox.W = Plus->Node[node]->x;
  210. bbox.T = Plus->Node[node]->z;
  211. bbox.B = Plus->Node[node]->z;
  212. dig_boxlist_add(list, line, bbox);
  213. if (dig_find_line_box(Plus, list) == 0)
  214. G_fatal_error(_("Unable to find bbox for featured %d"), line);
  215. Box->N = list->box[0].N;
  216. Box->S = list->box[0].S;
  217. Box->E = list->box[0].E;
  218. Box->W = list->box[0].W;
  219. Box->T = list->box[0].T;
  220. Box->B = list->box[0].B;
  221. }
  222. }
  223. if (!Vect_is_3d(Map)) {
  224. Box->T = PORT_DOUBLE_MAX;
  225. Box->B = -PORT_DOUBLE_MAX;
  226. }
  227. return 1;
  228. }
  229. /*!
  230. \brief Get bounding box of area
  231. \param Map vector map
  232. \param area area id
  233. \param[out] Box bounding box
  234. \return 1 on success
  235. \return 0 area is dead
  236. */
  237. int Vect_get_area_box(const struct Map_info *Map, int area, struct bound_box * Box)
  238. {
  239. struct Plus_head *Plus;
  240. struct P_area *Area;
  241. struct P_line *Line;
  242. struct P_node *Node;
  243. static struct boxlist *list = NULL;
  244. struct bound_box bbox;
  245. struct P_topo_b *topo;
  246. Plus = (struct Plus_head *)&(Map->plus);
  247. Area = Plus->Area[area];
  248. if (Area == NULL) { /* dead */
  249. G_zero(Box, sizeof(struct bound_box));
  250. return 0;
  251. }
  252. else {
  253. Line = Plus->Line[abs(Area->lines[0])];
  254. topo = (struct P_topo_b *)Line->topo;
  255. Node = Plus->Node[topo->N1];
  256. if (list == NULL) {
  257. list = Vect_new_boxlist(TRUE);
  258. }
  259. Vect_reset_boxlist(list);
  260. bbox.N = Node->y;
  261. bbox.S = Node->y;
  262. bbox.E = Node->x;
  263. bbox.W = Node->x;
  264. bbox.T = Node->z;
  265. bbox.B = Node->z;
  266. dig_boxlist_add(list, area, bbox);
  267. if (dig_find_area_box(Plus, list) == 0)
  268. G_fatal_error(_("Unable to get bounding box for area %d"), area);
  269. Box->N = list->box[0].N;
  270. Box->S = list->box[0].S;
  271. Box->E = list->box[0].E;
  272. Box->W = list->box[0].W;
  273. Box->T = list->box[0].T;
  274. Box->B = list->box[0].B;
  275. }
  276. return 1;
  277. }
  278. /*!
  279. \brief Get bounding box of isle
  280. \param Map vector map
  281. \param isle isle id
  282. \param[out] Box bounding box
  283. \return 1 on success
  284. \return 0 isle is dead
  285. */
  286. int Vect_get_isle_box(const struct Map_info *Map, int isle, struct bound_box * Box)
  287. {
  288. struct Plus_head *Plus;
  289. struct P_isle *Isle;
  290. struct P_line *Line;
  291. struct P_node *Node;
  292. static struct boxlist *list = NULL;
  293. struct bound_box bbox;
  294. struct P_topo_b *topo;
  295. Plus = (struct Plus_head *)&(Map->plus);
  296. Isle = Plus->Isle[isle];
  297. if (Isle == NULL) { /* dead */
  298. Box->N = 0;
  299. Box->S = 0;
  300. Box->E = 0;
  301. Box->W = 0;
  302. Box->T = 0;
  303. Box->B = 0;
  304. return 0;
  305. }
  306. else {
  307. Line = Plus->Line[abs(Isle->lines[0])];
  308. topo = (struct P_topo_b *)Line->topo;
  309. Node = Plus->Node[topo->N1];
  310. if (list == NULL) {
  311. list = Vect_new_boxlist(1);
  312. }
  313. Vect_reset_boxlist(list);
  314. bbox.N = Node->y;
  315. bbox.S = Node->y;
  316. bbox.E = Node->x;
  317. bbox.W = Node->x;
  318. bbox.T = Node->z;
  319. bbox.B = Node->z;
  320. dig_boxlist_add(list, isle, bbox);
  321. if (dig_find_isle_box(Plus, list) == 0)
  322. G_fatal_error(_("Could not find area box"));
  323. Box->N = list->box[0].N;
  324. Box->S = list->box[0].S;
  325. Box->E = list->box[0].E;
  326. Box->W = list->box[0].W;
  327. Box->T = list->box[0].T;
  328. Box->B = list->box[0].B;
  329. }
  330. return 1;
  331. }
  332. /*!
  333. \brief Get bounding box of map (all features in the map)
  334. \param Map vector map
  335. \param[out] Box bouding box
  336. \return 1 on success
  337. \return 0 on error
  338. */
  339. int Vect_get_map_box(const struct Map_info *Map, struct bound_box * Box)
  340. {
  341. const struct Plus_head *Plus;
  342. Plus = &(Map->plus);
  343. Box->N = Plus->box.N;
  344. Box->S = Plus->box.S;
  345. Box->E = Plus->box.E;
  346. Box->W = Plus->box.W;
  347. Box->T = Plus->box.T;
  348. Box->B = Plus->box.B;
  349. return 1;
  350. }
  351. /*!
  352. \brief Copy region window to bounding box
  353. \param Window region structure (raster-based)
  354. \param[out] Box boundary box (vector-based)
  355. \return 1 on success
  356. \return 0 on error
  357. */
  358. int Vect_region_box(const struct Cell_head *Window, struct bound_box * Box)
  359. {
  360. Box->N = Window->north;
  361. Box->S = Window->south;
  362. Box->E = Window->east;
  363. Box->W = Window->west;
  364. Box->T = PORT_DOUBLE_MAX;
  365. Box->B = -PORT_DOUBLE_MAX;
  366. return 1;
  367. }