spindex.c 13 KB

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