spindex.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /**
  2. * \file spindex.c
  3. *
  4. * \brief Vector library - spatial index (lower level functions)
  5. *
  6. * Lower level functions for reading/writing/manipulating vectors.
  7. *
  8. * (C) 2001 by the GRASS Development Team
  9. *
  10. * This program is free software under the GNU General Public License
  11. * (>=v2). Read the file COPYING that comes with GRASS for details.
  12. *
  13. * \author CERL (probably Dave Gerdes), Radim Blazek
  14. */
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <grass/gis.h>
  18. #include <grass/Vect.h>
  19. #include <grass/glocale.h>
  20. /*!
  21. \brief Initit spatial index (nodes, lines, areas, isles)
  22. \param Plus pointer to Plus_head structure
  23. \return 1 OK
  24. \return 0 on error
  25. */
  26. int dig_spidx_init(struct Plus_head *Plus)
  27. {
  28. G_debug(1, "dig_spidx_init()");
  29. Plus->Node_spidx = RTreeNewIndex();
  30. Plus->Line_spidx = RTreeNewIndex();
  31. Plus->Area_spidx = RTreeNewIndex();
  32. Plus->Isle_spidx = RTreeNewIndex();
  33. Plus->Node_spidx_offset = 0L;
  34. Plus->Edge_spidx_offset = 0L;
  35. Plus->Line_spidx_offset = 0L;
  36. Plus->Area_spidx_offset = 0L;
  37. Plus->Isle_spidx_offset = 0L;
  38. Plus->Volume_spidx_offset = 0L;
  39. Plus->Hole_spidx_offset = 0L;
  40. return 1;
  41. }
  42. /*!
  43. \brief Free spatial index for nodes
  44. \param Plus pointer to Plus_head structure
  45. */
  46. void dig_spidx_free_nodes(struct Plus_head *Plus)
  47. {
  48. RTreeDestroyNode(Plus->Node_spidx);
  49. Plus->Node_spidx = RTreeNewIndex();
  50. }
  51. /*!
  52. \brief Free spatial index for lines
  53. \param Plus pointer to Plus_head structure
  54. */
  55. void dig_spidx_free_lines(struct Plus_head *Plus)
  56. {
  57. RTreeDestroyNode(Plus->Line_spidx);
  58. Plus->Line_spidx = RTreeNewIndex();
  59. }
  60. /*!
  61. \brief Free spatial index for areas
  62. \param Plus pointer to Plus_head structure
  63. */
  64. void dig_spidx_free_areas(struct Plus_head *Plus)
  65. {
  66. RTreeDestroyNode(Plus->Area_spidx);
  67. Plus->Area_spidx = RTreeNewIndex();
  68. }
  69. /*!
  70. \brief Free spatial index for isles
  71. \param Plus pointer to Plus_head structure
  72. */
  73. void dig_spidx_free_isles(struct Plus_head *Plus)
  74. {
  75. RTreeDestroyNode(Plus->Isle_spidx);
  76. Plus->Isle_spidx = RTreeNewIndex();
  77. }
  78. /*!
  79. \brief Free spatial index (nodes, lines, areas, isles)
  80. \param Plus pointer to Plus_head structure
  81. */
  82. void dig_spidx_free(struct Plus_head *Plus)
  83. {
  84. dig_spidx_free_nodes(Plus);
  85. dig_spidx_free_lines(Plus);
  86. dig_spidx_free_areas(Plus);
  87. dig_spidx_free_isles(Plus);
  88. }
  89. /*!
  90. \brief Add new node to spatial index
  91. \param Plus pointer to Plus_head structure
  92. \param node node id
  93. \param x,y,z node coordinates
  94. \return 1 OK
  95. \return 0 on error
  96. */
  97. int
  98. dig_spidx_add_node(struct Plus_head *Plus, int node,
  99. double x, double y, double z)
  100. {
  101. struct Rect rect;
  102. G_debug(3, "dig_spidx_add_node(): node = %d, x,y,z = %f, %f, %f", node, x,
  103. y, z);
  104. rect.boundary[0] = x;
  105. rect.boundary[1] = y;
  106. rect.boundary[2] = z;
  107. rect.boundary[3] = x;
  108. rect.boundary[4] = y;
  109. rect.boundary[5] = z;
  110. RTreeInsertRect(&rect, node, &(Plus->Node_spidx), 0);
  111. return 1;
  112. }
  113. /*!
  114. \brief Add new line to spatial index
  115. \param Plus pointer to Plus_head structure
  116. \param line line id
  117. \param box bounding box
  118. \return 0
  119. */
  120. int dig_spidx_add_line(struct Plus_head *Plus, int line, BOUND_BOX * box)
  121. {
  122. struct Rect rect;
  123. G_debug(3, "dig_spidx_add_line(): line = %d", line);
  124. rect.boundary[0] = box->W;
  125. rect.boundary[1] = box->S;
  126. rect.boundary[2] = box->B;
  127. rect.boundary[3] = box->E;
  128. rect.boundary[4] = box->N;
  129. rect.boundary[5] = box->T;
  130. RTreeInsertRect(&rect, line, &(Plus->Line_spidx), 0);
  131. return 0;
  132. }
  133. /*!
  134. \brief Add new area to spatial index
  135. \param Plus pointer to Plus_head structure
  136. \param area area id
  137. \param box bounding box
  138. \return 0
  139. */
  140. int dig_spidx_add_area(struct Plus_head *Plus, int area, BOUND_BOX * box)
  141. {
  142. struct Rect rect;
  143. G_debug(3, "dig_spidx_add_area(): area = %d", area);
  144. rect.boundary[0] = box->W;
  145. rect.boundary[1] = box->S;
  146. rect.boundary[2] = box->B;
  147. rect.boundary[3] = box->E;
  148. rect.boundary[4] = box->N;
  149. rect.boundary[5] = box->T;
  150. RTreeInsertRect(&rect, area, &(Plus->Area_spidx), 0);
  151. return 0;
  152. }
  153. /*!
  154. \brief Add new island to spatial index
  155. \param Plus pointer to Plus_head structure
  156. \param isle isle id
  157. \param box bounding box
  158. \return 0
  159. */
  160. int dig_spidx_add_isle(struct Plus_head *Plus, int isle, BOUND_BOX * box)
  161. {
  162. struct Rect rect;
  163. G_debug(3, "dig_spidx_add_isle(): isle = %d", isle);
  164. rect.boundary[0] = box->W;
  165. rect.boundary[1] = box->S;
  166. rect.boundary[2] = box->B;
  167. rect.boundary[3] = box->E;
  168. rect.boundary[4] = box->N;
  169. rect.boundary[5] = box->T;
  170. RTreeInsertRect(&rect, isle, &(Plus->Isle_spidx), 0);
  171. return 0;
  172. }
  173. /*!
  174. \brief Delete node from spatial index
  175. G_fatal_error() called on error.
  176. \param Plus pointer to Plus_head structure
  177. \param node node id
  178. \return 0
  179. */
  180. int dig_spidx_del_node(struct Plus_head *Plus, int node)
  181. {
  182. int ret;
  183. P_NODE *Node;
  184. struct Rect rect;
  185. G_debug(3, "dig_spidx_del_node(): node = %d", node);
  186. Node = Plus->Node[node];
  187. rect.boundary[0] = Node->x;
  188. rect.boundary[1] = Node->y;
  189. rect.boundary[2] = Node->z;
  190. rect.boundary[3] = Node->x;
  191. rect.boundary[4] = Node->y;
  192. rect.boundary[5] = Node->z;
  193. ret = RTreeDeleteRect(&rect, node, &(Plus->Node_spidx));
  194. if (ret)
  195. G_fatal_error(_("Unable to delete node %d from spatial index"), node);
  196. return 0;
  197. }
  198. /*!
  199. \brief Delete line from spatial index
  200. G_fatal_error() called on error.
  201. \param Plus pointer to Plus_head structure
  202. \param line line id
  203. \return 0
  204. */
  205. int dig_spidx_del_line(struct Plus_head *Plus, int line)
  206. {
  207. P_LINE *Line;
  208. struct Rect rect;
  209. int ret;
  210. G_debug(3, "dig_spidx_del_line(): line = %d", line);
  211. Line = Plus->Line[line];
  212. G_debug(3, " box(x1,y1,z1,x2,y2,z2): %f %f %f %f %f %f", Line->W,
  213. Line->S, Line->B, Line->E, Line->N, Line->T);
  214. rect.boundary[0] = Line->W;
  215. rect.boundary[1] = Line->S;
  216. rect.boundary[2] = Line->B;
  217. rect.boundary[3] = Line->E;
  218. rect.boundary[4] = Line->N;
  219. rect.boundary[5] = Line->T;
  220. ret = RTreeDeleteRect(&rect, line, &(Plus->Line_spidx));
  221. G_debug(3, " ret = %d", ret);
  222. if (ret)
  223. G_fatal_error(_("Unable to delete line %d from spatial index"), line);
  224. return 0;
  225. }
  226. /*!
  227. \brief Delete area from spatial index
  228. G_fatal_error() called on error.
  229. \param Plus pointer to Plus_head structure
  230. \param area area id
  231. \return 0
  232. */
  233. int dig_spidx_del_area(struct Plus_head *Plus, int area)
  234. {
  235. int ret;
  236. P_AREA *Area;
  237. struct Rect rect;
  238. G_debug(3, "dig_spidx_del_area(): area = %d", area);
  239. Area = Plus->Area[area];
  240. if (Area == NULL) {
  241. G_fatal_error(_("Attempt to delete sidx for dead area"));
  242. }
  243. rect.boundary[0] = Area->W;
  244. rect.boundary[1] = Area->S;
  245. rect.boundary[2] = Area->B;
  246. rect.boundary[3] = Area->E;
  247. rect.boundary[4] = Area->N;
  248. rect.boundary[5] = Area->T;
  249. ret = RTreeDeleteRect(&rect, area, &(Plus->Area_spidx));
  250. if (ret)
  251. G_fatal_error(_("Unable to delete area %d from spatial index"), area);
  252. return 0;
  253. }
  254. /*!
  255. \brief Delete isle from spatial index
  256. G_fatal_error() called on error.
  257. \param Plus pointer to Plus_head structure
  258. \param isle isle id
  259. \return 0
  260. */
  261. int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
  262. {
  263. int ret;
  264. P_ISLE *Isle;
  265. struct Rect rect;
  266. G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
  267. Isle = Plus->Isle[isle];
  268. rect.boundary[0] = Isle->W;
  269. rect.boundary[1] = Isle->S;
  270. rect.boundary[2] = Isle->B;
  271. rect.boundary[3] = Isle->E;
  272. rect.boundary[4] = Isle->N;
  273. rect.boundary[5] = Isle->T;
  274. ret = RTreeDeleteRect(&rect, isle, &(Plus->Isle_spidx));
  275. if (ret)
  276. G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
  277. return 0;
  278. }
  279. /* This function is called by RTreeSearch() to add selected node/line/area/isle to thelist */
  280. static int _add_item(int id, struct ilist *list)
  281. {
  282. dig_list_add(list, id);
  283. return 1;
  284. }
  285. /*!
  286. \brief Select nodes by bbox
  287. \param Plus pointer to Plus_head structure
  288. \param box bounding box
  289. \param list list of selected lines
  290. \return number of selected nodes
  291. \return -1 on error
  292. */
  293. int
  294. dig_select_nodes(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  295. {
  296. struct Rect rect;
  297. G_debug(3, "dig_select_nodes()");
  298. list->n_values = 0;
  299. rect.boundary[0] = box->W;
  300. rect.boundary[1] = box->S;
  301. rect.boundary[2] = box->B;
  302. rect.boundary[3] = box->E;
  303. rect.boundary[4] = box->N;
  304. rect.boundary[5] = box->T;
  305. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
  306. return (list->n_values);
  307. }
  308. /* This function is called by RTreeSearch() for nodes to add selected node to list */
  309. static int _add_node(int id, int *node)
  310. {
  311. *node = id;
  312. return 0;
  313. }
  314. /*!
  315. \brief Find one node by coordinates
  316. \param Plus pointer to Plus_head structure
  317. \param x,y,z coordinates
  318. \return number of node
  319. \return 0 not found
  320. */
  321. int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
  322. {
  323. struct Rect rect;
  324. struct ilist list;
  325. int node;
  326. G_debug(3, "dig_find_node()");
  327. dig_init_list(&list);
  328. rect.boundary[0] = x;
  329. rect.boundary[1] = y;
  330. rect.boundary[2] = z;
  331. rect.boundary[3] = x;
  332. rect.boundary[4] = y;
  333. rect.boundary[5] = z;
  334. node = 0;
  335. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
  336. return node;
  337. }
  338. /*!
  339. \brief Select lines by box
  340. \param Plus pointer to Plus_head structure
  341. \param box bounding box
  342. \param list list of selected lines
  343. \return number of selected lines
  344. */
  345. int
  346. dig_select_lines(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  347. {
  348. struct Rect rect;
  349. G_debug(3, "dig_select_lines()");
  350. list->n_values = 0;
  351. rect.boundary[0] = box->W;
  352. rect.boundary[1] = box->S;
  353. rect.boundary[2] = box->B;
  354. rect.boundary[3] = box->E;
  355. rect.boundary[4] = box->N;
  356. rect.boundary[5] = box->T;
  357. RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item, list);
  358. return (list->n_values);
  359. }
  360. /*!
  361. \brief Select areas by box
  362. \param Plus pointer to Plus_head structure
  363. \param box bounding box
  364. \param list list of selected lines
  365. \return number of selected areas
  366. */
  367. int
  368. dig_select_areas(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  369. {
  370. struct Rect rect;
  371. G_debug(3, "dig_select_areas()");
  372. list->n_values = 0;
  373. rect.boundary[0] = box->W;
  374. rect.boundary[1] = box->S;
  375. rect.boundary[2] = box->B;
  376. rect.boundary[3] = box->E;
  377. rect.boundary[4] = box->N;
  378. rect.boundary[5] = box->T;
  379. RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item, list);
  380. return (list->n_values);
  381. }
  382. /*!
  383. \brief Select isles by box
  384. \param Plus pointer to Plus_head structure
  385. \param box bounding box
  386. \param list list of selected lines
  387. \return number of selected isles
  388. */
  389. int
  390. dig_select_isles(struct Plus_head *Plus, const BOUND_BOX * box, struct ilist *list)
  391. {
  392. struct Rect rect;
  393. G_debug(3, "dig_select_isles()");
  394. list->n_values = 0;
  395. rect.boundary[0] = box->W;
  396. rect.boundary[1] = box->S;
  397. rect.boundary[2] = box->B;
  398. rect.boundary[3] = box->E;
  399. rect.boundary[4] = box->N;
  400. rect.boundary[5] = box->T;
  401. RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item, list);
  402. return (list->n_values);
  403. }