spindex.c 24 KB

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