spindex.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  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 <stdlib.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <fcntl.h>
  16. #include <unistd.h>
  17. #include <string.h>
  18. #include <grass/vector.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. int ndims;
  29. ndims = (Plus->with_z != 0) ? 3 : 2;
  30. Plus->spidx_with_z = (Plus->with_z != 0);
  31. G_debug(1, "dig_spidx_init(), %d dims", ndims);
  32. if (Plus->Spidx_file) {
  33. int fd;
  34. char *filename;
  35. filename = G_tempfile();
  36. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  37. Plus->Node_spidx = RTreeCreateTree(fd, 0, ndims);
  38. remove(filename);
  39. filename = G_tempfile();
  40. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  41. Plus->Line_spidx = RTreeCreateTree(fd, 0, ndims);
  42. remove(filename);
  43. filename = G_tempfile();
  44. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  45. Plus->Area_spidx = RTreeCreateTree(fd, 0, ndims);
  46. remove(filename);
  47. filename = G_tempfile();
  48. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  49. Plus->Isle_spidx = RTreeCreateTree(fd, 0, ndims);
  50. remove(filename);
  51. Plus->Face_spidx = NULL;
  52. Plus->Volume_spidx = NULL;
  53. Plus->Hole_spidx = NULL;
  54. }
  55. else {
  56. Plus->Node_spidx = RTreeCreateTree(-1, 0, ndims);
  57. Plus->Line_spidx = RTreeCreateTree(-1, 0, ndims);
  58. Plus->Area_spidx = RTreeCreateTree(-1, 0, ndims);
  59. Plus->Isle_spidx = RTreeCreateTree(-1, 0, ndims);
  60. Plus->Face_spidx = NULL;
  61. Plus->Volume_spidx = NULL;
  62. Plus->Hole_spidx = NULL;
  63. }
  64. Plus->Node_spidx_offset = 0L;
  65. Plus->Line_spidx_offset = 0L;
  66. Plus->Area_spidx_offset = 0L;
  67. Plus->Isle_spidx_offset = 0L;
  68. Plus->Face_spidx_offset = 0L;
  69. Plus->Volume_spidx_offset = 0L;
  70. Plus->Hole_spidx_offset = 0L;
  71. Plus->Spidx_built = FALSE;
  72. return 1;
  73. }
  74. /*!
  75. \brief Free spatial index for nodes
  76. \param Plus pointer to Plus_head structure
  77. */
  78. void dig_spidx_free_nodes(struct Plus_head *Plus)
  79. {
  80. int ndims;
  81. ndims = Plus->with_z ? 3 : 2;
  82. /* Node spidx */
  83. if (Plus->Node_spidx->fd > -1) {
  84. int fd;
  85. char *filename;
  86. close(Plus->Node_spidx->fd);
  87. RTreeDestroyTree(Plus->Node_spidx);
  88. filename = G_tempfile();
  89. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  90. Plus->Node_spidx = RTreeCreateTree(fd, 0, ndims);
  91. remove(filename);
  92. }
  93. else {
  94. RTreeDestroyTree(Plus->Node_spidx);
  95. Plus->Node_spidx = RTreeCreateTree(-1, 0, ndims);
  96. }
  97. }
  98. /*!
  99. \brief Free spatial index for lines
  100. \param Plus pointer to Plus_head structure
  101. */
  102. void dig_spidx_free_lines(struct Plus_head *Plus)
  103. {
  104. int ndims;
  105. ndims = Plus->with_z ? 3 : 2;
  106. /* Line spidx */
  107. if (Plus->Line_spidx->fd > -1) {
  108. int fd;
  109. char *filename;
  110. close(Plus->Line_spidx->fd);
  111. RTreeDestroyTree(Plus->Line_spidx);
  112. filename = G_tempfile();
  113. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  114. Plus->Line_spidx = RTreeCreateTree(fd, 0, ndims);
  115. remove(filename);
  116. }
  117. else {
  118. RTreeDestroyTree(Plus->Line_spidx);
  119. Plus->Line_spidx = RTreeCreateTree(-1, 0, ndims);
  120. }
  121. }
  122. /*!
  123. \brief Reset spatial index for areas
  124. \param Plus pointer to Plus_head structure
  125. */
  126. void dig_spidx_free_areas(struct Plus_head *Plus)
  127. {
  128. int ndims;
  129. ndims = Plus->with_z ? 3 : 2;
  130. /* Area spidx */
  131. if (Plus->Area_spidx->fd > -1) {
  132. int fd;
  133. char *filename;
  134. close(Plus->Area_spidx->fd);
  135. RTreeDestroyTree(Plus->Area_spidx);
  136. filename = G_tempfile();
  137. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  138. Plus->Area_spidx = RTreeCreateTree(fd, 0, ndims);
  139. remove(filename);
  140. }
  141. else {
  142. RTreeDestroyTree(Plus->Area_spidx);
  143. Plus->Area_spidx = RTreeCreateTree(-1, 0, ndims);
  144. }
  145. }
  146. /*!
  147. \brief Reset spatial index for isles
  148. \param Plus pointer to Plus_head structure
  149. */
  150. void dig_spidx_free_isles(struct Plus_head *Plus)
  151. {
  152. int ndims;
  153. ndims = Plus->with_z ? 3 : 2;
  154. /* Isle spidx */
  155. if (Plus->Isle_spidx->fd > -1) {
  156. int fd;
  157. char *filename;
  158. close(Plus->Isle_spidx->fd);
  159. RTreeDestroyTree(Plus->Isle_spidx);
  160. filename = G_tempfile();
  161. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  162. Plus->Isle_spidx = RTreeCreateTree(fd, 0, ndims);
  163. remove(filename);
  164. }
  165. else {
  166. RTreeDestroyTree(Plus->Isle_spidx);
  167. Plus->Isle_spidx = RTreeCreateTree(-1, 0, ndims);
  168. }
  169. }
  170. /*!
  171. \brief Free spatial index (nodes, lines, areas, isles)
  172. \param Plus pointer to Plus_head structure
  173. */
  174. void dig_spidx_free(struct Plus_head *Plus)
  175. {
  176. /* Node spidx */
  177. if (Plus->Node_spidx->fd > -1)
  178. close(Plus->Node_spidx->fd);
  179. RTreeDestroyTree(Plus->Node_spidx);
  180. /* Line spidx */
  181. if (Plus->Line_spidx->fd > -1)
  182. close(Plus->Line_spidx->fd);
  183. RTreeDestroyTree(Plus->Line_spidx);
  184. /* Area spidx */
  185. if (Plus->Area_spidx->fd > -1)
  186. close(Plus->Area_spidx->fd);
  187. RTreeDestroyTree(Plus->Area_spidx);
  188. /* Isle spidx */
  189. if (Plus->Isle_spidx->fd > -1)
  190. close(Plus->Isle_spidx->fd);
  191. RTreeDestroyTree(Plus->Isle_spidx);
  192. /* 3D future : */
  193. /* Face spidx */
  194. /* Volume spidx */
  195. /* Hole spidx */
  196. }
  197. /*!
  198. \brief Add new node to spatial index
  199. \param Plus pointer to Plus_head structure
  200. \param node node id
  201. \param x,y,z node coordinates
  202. \return 1 OK
  203. \return 0 on error
  204. */
  205. int
  206. dig_spidx_add_node(struct Plus_head *Plus, int node,
  207. double x, double y, double z)
  208. {
  209. static struct RTree_Rect rect;
  210. static int rect_init = 0;
  211. if (!rect_init) {
  212. /* always 6 sides for 3D */
  213. rect.boundary = G_malloc(6 * sizeof(RectReal));
  214. rect_init = 6;
  215. }
  216. G_debug(3, "dig_spidx_add_node(): node = %d, x,y,z = %f, %f, %f", node, x,
  217. y, z);
  218. rect.boundary[0] = x;
  219. rect.boundary[1] = y;
  220. rect.boundary[2] = z;
  221. rect.boundary[3] = x;
  222. rect.boundary[4] = y;
  223. rect.boundary[5] = z;
  224. RTreeInsertRect(&rect, node, Plus->Node_spidx);
  225. return 1;
  226. }
  227. /*!
  228. \brief Add new line to spatial index
  229. \param Plus pointer to Plus_head structure
  230. \param line line id
  231. \param box bounding box
  232. \return 0
  233. */
  234. int dig_spidx_add_line(struct Plus_head *Plus, int line,
  235. const struct bound_box *box)
  236. {
  237. static struct RTree_Rect rect;
  238. static int rect_init = 0;
  239. if (!rect_init) {
  240. /* always 6 sides for 3D */
  241. rect.boundary = G_malloc(6 * sizeof(RectReal));
  242. rect_init = 6;
  243. }
  244. G_debug(3, "dig_spidx_add_line(): line = %d", line);
  245. rect.boundary[0] = box->W;
  246. rect.boundary[1] = box->S;
  247. rect.boundary[2] = box->B;
  248. rect.boundary[3] = box->E;
  249. rect.boundary[4] = box->N;
  250. rect.boundary[5] = box->T;
  251. RTreeInsertRect(&rect, line, Plus->Line_spidx);
  252. return 0;
  253. }
  254. /*!
  255. \brief Add new area to spatial index
  256. \param Plus pointer to Plus_head structure
  257. \param area area id
  258. \param box bounding box
  259. \return 0
  260. */
  261. int dig_spidx_add_area(struct Plus_head *Plus, int area,
  262. const struct bound_box *box)
  263. {
  264. static struct RTree_Rect rect;
  265. static int rect_init = 0;
  266. if (!rect_init) {
  267. /* always 6 sides for 3D */
  268. rect.boundary = G_malloc(6 * sizeof(RectReal));
  269. rect_init = 6;
  270. }
  271. G_debug(3, "dig_spidx_add_area(): area = %d", area);
  272. rect.boundary[0] = box->W;
  273. rect.boundary[1] = box->S;
  274. rect.boundary[2] = box->B;
  275. rect.boundary[3] = box->E;
  276. rect.boundary[4] = box->N;
  277. rect.boundary[5] = box->T;
  278. RTreeInsertRect(&rect, area, Plus->Area_spidx);
  279. return 0;
  280. }
  281. /*!
  282. \brief Add new island to spatial index
  283. \param Plus pointer to Plus_head structure
  284. \param isle isle id
  285. \param box bounding box
  286. \return 0
  287. */
  288. int dig_spidx_add_isle(struct Plus_head *Plus, int isle,
  289. const struct bound_box *box)
  290. {
  291. static struct RTree_Rect rect;
  292. static int rect_init = 0;
  293. if (!rect_init) {
  294. /* always 6 sides for 3D */
  295. rect.boundary = G_malloc(6 * sizeof(RectReal));
  296. rect_init = 6;
  297. }
  298. G_debug(3, "dig_spidx_add_isle(): isle = %d", isle);
  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. RTreeInsertRect(&rect, isle, Plus->Isle_spidx);
  306. return 0;
  307. }
  308. /*!
  309. \brief Delete node from spatial index
  310. G_fatal_error() called on error.
  311. \param Plus pointer to Plus_head structure
  312. \param node node id
  313. \return 0
  314. */
  315. int dig_spidx_del_node(struct Plus_head *Plus, int node)
  316. {
  317. int ret;
  318. struct P_node *Node;
  319. static struct RTree_Rect rect;
  320. static int rect_init = 0;
  321. if (!rect_init) {
  322. /* always 6 sides for 3D */
  323. rect.boundary = G_malloc(6 * sizeof(RectReal));
  324. rect_init = 6;
  325. }
  326. G_debug(3, "dig_spidx_del_node(): node = %d", node);
  327. Node = Plus->Node[node];
  328. rect.boundary[0] = Node->x;
  329. rect.boundary[1] = Node->y;
  330. rect.boundary[2] = Node->z;
  331. rect.boundary[3] = Node->x;
  332. rect.boundary[4] = Node->y;
  333. rect.boundary[5] = Node->z;
  334. ret = RTreeDeleteRect(&rect, node, Plus->Node_spidx);
  335. if (ret)
  336. G_fatal_error(_("Unable to delete node %d from spatial index"), node);
  337. return 0;
  338. }
  339. /*!
  340. \brief Delete line from spatial index
  341. G_fatal_error() called on error.
  342. \param Plus pointer to Plus_head structure
  343. \param line line id
  344. \param x,y,z coordinates
  345. \return 0
  346. */
  347. int dig_spidx_del_line(struct Plus_head *Plus, int line,
  348. double x, double y, double z)
  349. {
  350. int ret;
  351. static struct RTree_Rect rect;
  352. static int rect_init = 0;
  353. if (!rect_init) {
  354. /* always 6 sides for 3D */
  355. rect.boundary = G_malloc(6 * sizeof(RectReal));
  356. rect_init = 6;
  357. }
  358. G_debug(3, "dig_spidx_del_line(): line = %d", line);
  359. rect.boundary[0] = x;
  360. rect.boundary[1] = y;
  361. rect.boundary[2] = z;
  362. rect.boundary[3] = x;
  363. rect.boundary[4] = y;
  364. rect.boundary[5] = z;
  365. ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
  366. G_debug(3, " ret = %d", ret);
  367. if (ret)
  368. G_fatal_error(_("Unable to delete line %d from spatial index"), line);
  369. return 0;
  370. }
  371. /*!
  372. \brief Delete area from spatial index
  373. G_fatal_error() called on error.
  374. \param Plus pointer to Plus_head structure
  375. \param area area id
  376. \return 0
  377. */
  378. int dig_spidx_del_area(struct Plus_head *Plus, int area)
  379. {
  380. int ret;
  381. struct P_area *Area;
  382. struct P_line *Line;
  383. struct P_node *Node;
  384. struct P_topo_b *topo;
  385. static struct RTree_Rect rect;
  386. static int rect_init = 0;
  387. if (!rect_init) {
  388. /* always 6 sides for 3D */
  389. rect.boundary = G_malloc(6 * sizeof(RectReal));
  390. rect_init = 6;
  391. }
  392. G_debug(3, "dig_spidx_del_area(): area = %d", area);
  393. Area = Plus->Area[area];
  394. if (Area == NULL) {
  395. G_fatal_error(_("Attempt to delete sidx for dead area"));
  396. }
  397. Line = Plus->Line[abs(Area->lines[0])];
  398. topo = (struct P_topo_b *)Line->topo;
  399. Node = Plus->Node[topo->N1];
  400. rect.boundary[0] = Node->x;
  401. rect.boundary[1] = Node->y;
  402. rect.boundary[2] = Node->z;
  403. rect.boundary[3] = Node->x;
  404. rect.boundary[4] = Node->y;
  405. rect.boundary[5] = Node->z;
  406. ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
  407. if (ret)
  408. G_fatal_error(_("Unable to delete area %d from spatial index"), area);
  409. return 0;
  410. }
  411. /*!
  412. \brief Delete isle from spatial index
  413. G_fatal_error() called on error.
  414. \param Plus pointer to Plus_head structure
  415. \param isle isle id
  416. \return 0
  417. */
  418. int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
  419. {
  420. int ret;
  421. struct P_isle *Isle;
  422. struct P_line *Line;
  423. struct P_node *Node;
  424. struct P_topo_b *topo;
  425. static struct RTree_Rect rect;
  426. static int rect_init = 0;
  427. if (!rect_init) {
  428. /* always 6 sides for 3D */
  429. rect.boundary = G_malloc(6 * sizeof(RectReal));
  430. rect_init = 6;
  431. }
  432. G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
  433. Isle = Plus->Isle[isle];
  434. Line = Plus->Line[abs(Isle->lines[0])];
  435. topo = (struct P_topo_b *)Line->topo;
  436. Node = Plus->Node[topo->N1];
  437. rect.boundary[0] = Node->x;
  438. rect.boundary[1] = Node->y;
  439. rect.boundary[2] = Node->z;
  440. rect.boundary[3] = Node->x;
  441. rect.boundary[4] = Node->y;
  442. rect.boundary[5] = Node->z;
  443. ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
  444. if (ret)
  445. G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
  446. return 0;
  447. }
  448. /* This function is called by RTreeSearch() to add selected node/line/area/isle to the list */
  449. static int _add_item(int id, const struct RTree_Rect *rect,
  450. struct ilist *list)
  451. {
  452. G_ilist_add(list, id);
  453. return 1;
  454. }
  455. /* This function is called by RTreeSearch() to add
  456. * selected node/line/area/isle to the box list */
  457. static int _add_item_with_box(int id, const struct RTree_Rect *rect,
  458. struct boxlist *list)
  459. {
  460. struct bound_box box;
  461. box.W = rect->boundary[0];
  462. box.S = rect->boundary[1];
  463. box.B = rect->boundary[2];
  464. box.E = rect->boundary[3];
  465. box.N = rect->boundary[4];
  466. box.T = rect->boundary[5];
  467. dig_boxlist_add(list, id, &box);
  468. return 1;
  469. }
  470. struct boxid
  471. {
  472. int id;
  473. struct bound_box *box;
  474. };
  475. /* This function is called by RTreeSearch() to add
  476. * selected node/line/area/isle to the box list */
  477. static int _set_item_box(int id, const struct RTree_Rect *rect,
  478. struct boxid *box_id)
  479. {
  480. if (id == box_id->id) {
  481. box_id->box->W = rect->boundary[0];
  482. box_id->box->S = rect->boundary[1];
  483. box_id->box->B = rect->boundary[2];
  484. box_id->box->E = rect->boundary[3];
  485. box_id->box->N = rect->boundary[4];
  486. box_id->box->T = rect->boundary[5];
  487. return 0;
  488. }
  489. return 1;
  490. }
  491. /*!
  492. \brief Select nodes by bbox
  493. \param Plus pointer to Plus_head structure
  494. \param box bounding box
  495. \param list list of selected lines
  496. \return number of selected nodes
  497. \return -1 on error
  498. */
  499. int
  500. dig_select_nodes(struct Plus_head *Plus, const struct bound_box * box,
  501. struct ilist *list)
  502. {
  503. static struct RTree_Rect rect;
  504. static int rect_init = 0;
  505. if (!rect_init) {
  506. /* always 6 sides for 3D */
  507. rect.boundary = G_malloc(6 * sizeof(RectReal));
  508. rect_init = 6;
  509. }
  510. G_debug(3, "dig_select_nodes()");
  511. list->n_values = 0;
  512. rect.boundary[0] = box->W;
  513. rect.boundary[1] = box->S;
  514. rect.boundary[2] = box->B;
  515. rect.boundary[3] = box->E;
  516. rect.boundary[4] = box->N;
  517. rect.boundary[5] = box->T;
  518. if (Plus->Spidx_new)
  519. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
  520. else
  521. rtree_search(Plus->Node_spidx, &rect, (void *)_add_item, list, Plus);
  522. return (list->n_values);
  523. }
  524. /* This function is called by RTreeSearch() for nodes to find the node id */
  525. static int _add_node(int id, const struct RTree_Rect *rect, int *node)
  526. {
  527. *node = id;
  528. return 0;
  529. }
  530. /*!
  531. \brief Find one node by coordinates
  532. \param Plus pointer to Plus_head structure
  533. \param x,y,z coordinates
  534. \return number of node
  535. \return 0 not found
  536. */
  537. int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
  538. {
  539. int node;
  540. static struct RTree_Rect rect;
  541. static int rect_init = 0;
  542. if (!rect_init) {
  543. /* always 6 sides for 3D */
  544. rect.boundary = G_malloc(6 * sizeof(RectReal));
  545. rect_init = 6;
  546. }
  547. G_debug(3, "dig_find_node()");
  548. rect.boundary[0] = x;
  549. rect.boundary[1] = y;
  550. rect.boundary[2] = z;
  551. rect.boundary[3] = x;
  552. rect.boundary[4] = y;
  553. rect.boundary[5] = z;
  554. node = 0;
  555. if (Plus->Spidx_new)
  556. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
  557. else
  558. rtree_search(Plus->Node_spidx, &rect, (void *)_add_node, &node, Plus);
  559. return node;
  560. }
  561. /*!
  562. \brief Select lines with boxes by box
  563. \param Plus pointer to Plus_head structure
  564. \param box bounding box
  565. \param list boxlist of selected lines
  566. \return number of selected lines
  567. \return 0 not found
  568. */
  569. int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box,
  570. struct boxlist *list)
  571. {
  572. static struct RTree_Rect rect;
  573. static int rect_init = 0;
  574. if (!rect_init) {
  575. /* always 6 sides for 3D */
  576. rect.boundary = G_malloc(6 * sizeof(RectReal));
  577. rect_init = 6;
  578. }
  579. G_debug(3, "dig_select_lines_with_box()");
  580. list->n_values = 0;
  581. rect.boundary[0] = box->W;
  582. rect.boundary[1] = box->S;
  583. rect.boundary[2] = box->B;
  584. rect.boundary[3] = box->E;
  585. rect.boundary[4] = box->N;
  586. rect.boundary[5] = box->T;
  587. if (Plus->Spidx_new)
  588. RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list);
  589. else
  590. rtree_search(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  591. return (list->n_values);
  592. }
  593. /*!
  594. \brief Find box for line
  595. \param Plus pointer to Plus_head structure
  596. \param line line id
  597. \param[out] box bounding box
  598. \return > 0 bounding box for line found
  599. \return 0 not found
  600. */
  601. int dig_find_line_box(struct Plus_head *Plus, int line,
  602. struct bound_box *box)
  603. {
  604. int ret, type;
  605. struct P_line *Line;
  606. struct boxid box_id;
  607. static struct RTree_Rect rect;
  608. static int rect_init = 0;
  609. G_debug(3, "dig_find_line_box()");
  610. if (!rect_init) {
  611. /* always 6 sides for 3D */
  612. rect.boundary = G_malloc(6 * sizeof(RectReal));
  613. rect_init = 6;
  614. }
  615. Line = Plus->Line[line];
  616. type = Line->type;
  617. /* GV_LINES: retrieve box from spatial index */
  618. if (type & GV_LINES) {
  619. struct P_node *Node = NULL;
  620. if (type == GV_LINE) {
  621. struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
  622. Node = Plus->Node[topo->N1];
  623. }
  624. else if (type == GV_BOUNDARY) {
  625. struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
  626. Node = Plus->Node[topo->N1];
  627. }
  628. rect.boundary[0] = Node->x;
  629. rect.boundary[1] = Node->y;
  630. rect.boundary[2] = Node->z;
  631. rect.boundary[3] = Node->x;
  632. rect.boundary[4] = Node->y;
  633. rect.boundary[5] = Node->z;
  634. box_id.id = line;
  635. box_id.box = box;
  636. if (Plus->Spidx_new)
  637. ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id);
  638. else
  639. ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  640. return ret;
  641. }
  642. /* do not translate this error because
  643. * 1. this error is not supposed to happen
  644. * 2. the maintainer at which this message is directed prefers english */
  645. G_fatal_error("Bug in vector lib: dig_find_line_box() may only be used for lines and boundaries.");
  646. return 0;
  647. }
  648. /*!
  649. \brief Select areas with boxes by box
  650. \param Plus pointer to Plus_head structure
  651. \param box bounding box
  652. \param list boxlist of selected areas
  653. \return number of selected areas
  654. */
  655. int
  656. dig_select_areas(struct Plus_head *Plus, const struct bound_box *box,
  657. struct boxlist *list)
  658. {
  659. static struct RTree_Rect rect;
  660. static int rect_init = 0;
  661. if (!rect_init) {
  662. /* always 6 sides for 3D */
  663. rect.boundary = G_malloc(6 * sizeof(RectReal));
  664. rect_init = 6;
  665. }
  666. G_debug(3, "dig_select_areas_with_box()");
  667. list->n_values = 0;
  668. rect.boundary[0] = box->W;
  669. rect.boundary[1] = box->S;
  670. rect.boundary[2] = box->B;
  671. rect.boundary[3] = box->E;
  672. rect.boundary[4] = box->N;
  673. rect.boundary[5] = box->T;
  674. if (Plus->Spidx_new)
  675. RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list);
  676. else
  677. rtree_search(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  678. return (list->n_values);
  679. }
  680. /*!
  681. \brief Find bounding box for given area
  682. \param Plus pointer to Plus_head structure
  683. \param area area id
  684. \param[out] box bounding box
  685. \return > 0 bounding box for area found
  686. \return 0 not found
  687. */
  688. int dig_find_area_box(struct Plus_head *Plus, int area,
  689. struct bound_box *box)
  690. {
  691. int ret;
  692. struct boxid box_id;
  693. struct P_area *Area;
  694. struct P_line *Line;
  695. struct P_node *Node;
  696. struct P_topo_b *topo;
  697. static struct RTree_Rect rect;
  698. static int rect_init = 0;
  699. G_debug(3, "dig_find_area_box()");
  700. if (!rect_init) {
  701. /* always 6 sides for 3D */
  702. rect.boundary = G_malloc(6 * sizeof(RectReal));
  703. rect_init = 6;
  704. }
  705. Area = Plus->Area[area];
  706. Line = Plus->Line[abs(Area->lines[0])];
  707. topo = (struct P_topo_b *)Line->topo;
  708. Node = Plus->Node[topo->N1];
  709. rect.boundary[0] = Node->x;
  710. rect.boundary[1] = Node->y;
  711. rect.boundary[2] = Node->z;
  712. rect.boundary[3] = Node->x;
  713. rect.boundary[4] = Node->y;
  714. rect.boundary[5] = Node->z;
  715. box_id.id = area;
  716. box_id.box = box;
  717. if (Plus->Spidx_new)
  718. ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id);
  719. else
  720. ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  721. return ret;
  722. }
  723. /*!
  724. \brief Select isles with boxes by box
  725. \param Plus pointer to Plus_head structure
  726. \param box bounding box
  727. \param list boxlist of selected isles
  728. \return number of selected isles
  729. */
  730. int
  731. dig_select_isles(struct Plus_head *Plus, const struct bound_box * box,
  732. struct boxlist *list)
  733. {
  734. static struct RTree_Rect rect;
  735. static int rect_init = 0;
  736. if (!rect_init) {
  737. /* always 6 sides for 3D */
  738. rect.boundary = G_malloc(6 * sizeof(RectReal));
  739. rect_init = 6;
  740. }
  741. G_debug(3, "dig_select_areas_with_box()");
  742. list->n_values = 0;
  743. rect.boundary[0] = box->W;
  744. rect.boundary[1] = box->S;
  745. rect.boundary[2] = box->B;
  746. rect.boundary[3] = box->E;
  747. rect.boundary[4] = box->N;
  748. rect.boundary[5] = box->T;
  749. if (Plus->Spidx_new)
  750. RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list);
  751. else
  752. rtree_search(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  753. return (list->n_values);
  754. }
  755. /*!
  756. \brief Find box for isle
  757. \param Plus pointer to Plus_head structure
  758. \param isle isle id
  759. \param[out] box bounding box
  760. \return > 0 bounding box for isle found
  761. \return 0 not found
  762. */
  763. int dig_find_isle_box(struct Plus_head *Plus, int isle,
  764. struct bound_box *box)
  765. {
  766. int ret;
  767. struct boxid box_id;
  768. struct P_isle *Isle;
  769. struct P_line *Line;
  770. struct P_node *Node;
  771. struct P_topo_b *topo;
  772. static struct RTree_Rect rect;
  773. static int rect_init = 0;
  774. G_debug(3, "dig_find_isle_box()");
  775. if (!rect_init) {
  776. /* always 6 sides for 3D */
  777. rect.boundary = G_malloc(6 * sizeof(RectReal));
  778. rect_init = 6;
  779. }
  780. Isle = Plus->Isle[isle];
  781. Line = Plus->Line[abs(Isle->lines[0])];
  782. topo = (struct P_topo_b *)Line->topo;
  783. Node = Plus->Node[topo->N1];
  784. rect.boundary[0] = Node->x;
  785. rect.boundary[1] = Node->y;
  786. rect.boundary[2] = Node->z;
  787. rect.boundary[3] = Node->x;
  788. rect.boundary[4] = Node->y;
  789. rect.boundary[5] = Node->z;
  790. box_id.id = isle;
  791. box_id.box = box;
  792. if (Plus->Spidx_new)
  793. ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id);
  794. else
  795. ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  796. return ret;
  797. }