spindex.c 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009
  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 = RTreeNewIndex(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 = RTreeNewIndex(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 = RTreeNewIndex(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 = RTreeNewIndex(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 = RTreeNewIndex(-1, 0, ndims);
  57. Plus->Line_spidx = RTreeNewIndex(-1, 0, ndims);
  58. Plus->Area_spidx = RTreeNewIndex(-1, 0, ndims);
  59. Plus->Isle_spidx = RTreeNewIndex(-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. RTreeFreeIndex(Plus->Node_spidx);
  88. filename = G_tempfile();
  89. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  90. Plus->Node_spidx = RTreeNewIndex(fd, 0, ndims);
  91. remove(filename);
  92. }
  93. else {
  94. RTreeFreeIndex(Plus->Node_spidx);
  95. Plus->Node_spidx = RTreeNewIndex(-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. RTreeFreeIndex(Plus->Line_spidx);
  112. filename = G_tempfile();
  113. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  114. Plus->Line_spidx = RTreeNewIndex(fd, 0, ndims);
  115. remove(filename);
  116. }
  117. else {
  118. RTreeFreeIndex(Plus->Line_spidx);
  119. Plus->Line_spidx = RTreeNewIndex(-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. RTreeFreeIndex(Plus->Area_spidx);
  136. filename = G_tempfile();
  137. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  138. Plus->Area_spidx = RTreeNewIndex(fd, 0, ndims);
  139. remove(filename);
  140. }
  141. else {
  142. RTreeFreeIndex(Plus->Area_spidx);
  143. Plus->Area_spidx = RTreeNewIndex(-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. RTreeFreeIndex(Plus->Isle_spidx);
  160. filename = G_tempfile();
  161. fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
  162. Plus->Isle_spidx = RTreeNewIndex(fd, 0, ndims);
  163. remove(filename);
  164. }
  165. else {
  166. RTreeFreeIndex(Plus->Isle_spidx);
  167. Plus->Isle_spidx = RTreeNewIndex(-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. RTreeFreeIndex(Plus->Node_spidx);
  180. /* Line spidx */
  181. if (Plus->Line_spidx->fd > -1)
  182. close(Plus->Line_spidx->fd);
  183. RTreeFreeIndex(Plus->Line_spidx);
  184. /* Area spidx */
  185. if (Plus->Area_spidx->fd > -1)
  186. close(Plus->Area_spidx->fd);
  187. RTreeFreeIndex(Plus->Area_spidx);
  188. /* Isle spidx */
  189. if (Plus->Isle_spidx->fd > -1)
  190. close(Plus->Isle_spidx->fd);
  191. RTreeFreeIndex(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. \return 0
  345. */
  346. int dig_spidx_del_line(struct Plus_head *Plus, int line,
  347. double x, double y, double z)
  348. {
  349. int ret;
  350. static struct RTree_Rect rect;
  351. static int rect_init = 0;
  352. if (!rect_init) {
  353. /* always 6 sides for 3D */
  354. rect.boundary = G_malloc(6 * sizeof(RectReal));
  355. rect_init = 6;
  356. }
  357. G_debug(3, "dig_spidx_del_line(): line = %d", line);
  358. rect.boundary[0] = x;
  359. rect.boundary[1] = y;
  360. rect.boundary[2] = z;
  361. rect.boundary[3] = x;
  362. rect.boundary[4] = y;
  363. rect.boundary[5] = z;
  364. ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
  365. G_debug(3, " ret = %d", ret);
  366. if (ret)
  367. G_fatal_error(_("Unable to delete line %d from spatial index"), line);
  368. return 0;
  369. }
  370. /*!
  371. \brief Delete area from spatial index
  372. G_fatal_error() called on error.
  373. \param Plus pointer to Plus_head structure
  374. \param area area id
  375. \return 0
  376. */
  377. int dig_spidx_del_area(struct Plus_head *Plus, int area)
  378. {
  379. int ret;
  380. struct P_area *Area;
  381. struct P_line *Line;
  382. struct P_node *Node;
  383. struct P_topo_b *topo;
  384. static struct RTree_Rect rect;
  385. static int rect_init = 0;
  386. if (!rect_init) {
  387. /* always 6 sides for 3D */
  388. rect.boundary = G_malloc(6 * sizeof(RectReal));
  389. rect_init = 6;
  390. }
  391. G_debug(3, "dig_spidx_del_area(): area = %d", area);
  392. Area = Plus->Area[area];
  393. if (Area == NULL) {
  394. G_fatal_error(_("Attempt to delete sidx for dead area"));
  395. }
  396. Line = Plus->Line[abs(Area->lines[0])];
  397. topo = (struct P_topo_b *)Line->topo;
  398. Node = Plus->Node[topo->N1];
  399. rect.boundary[0] = Node->x;
  400. rect.boundary[1] = Node->y;
  401. rect.boundary[2] = Node->z;
  402. rect.boundary[3] = Node->x;
  403. rect.boundary[4] = Node->y;
  404. rect.boundary[5] = Node->z;
  405. ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
  406. if (ret)
  407. G_fatal_error(_("Unable to delete area %d from spatial index"), area);
  408. return 0;
  409. }
  410. /*!
  411. \brief Delete isle from spatial index
  412. G_fatal_error() called on error.
  413. \param Plus pointer to Plus_head structure
  414. \param isle isle id
  415. \return 0
  416. */
  417. int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
  418. {
  419. int ret;
  420. struct P_isle *Isle;
  421. struct P_line *Line;
  422. struct P_node *Node;
  423. struct P_topo_b *topo;
  424. static struct RTree_Rect rect;
  425. static int rect_init = 0;
  426. if (!rect_init) {
  427. /* always 6 sides for 3D */
  428. rect.boundary = G_malloc(6 * sizeof(RectReal));
  429. rect_init = 6;
  430. }
  431. G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
  432. Isle = Plus->Isle[isle];
  433. Line = Plus->Line[abs(Isle->lines[0])];
  434. topo = (struct P_topo_b *)Line->topo;
  435. Node = Plus->Node[topo->N1];
  436. rect.boundary[0] = Node->x;
  437. rect.boundary[1] = Node->y;
  438. rect.boundary[2] = Node->z;
  439. rect.boundary[3] = Node->x;
  440. rect.boundary[4] = Node->y;
  441. rect.boundary[5] = Node->z;
  442. ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
  443. if (ret)
  444. G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
  445. return 0;
  446. }
  447. /* This function is called by RTreeSearch() to add selected node/line/area/isle to the list */
  448. static int _add_item(int id, const struct RTree_Rect *rect,
  449. struct ilist *list)
  450. {
  451. G_ilist_add(list, id);
  452. return 1;
  453. }
  454. /* This function is called by RTreeSearch() to add
  455. * selected node/line/area/isle to the box list */
  456. static int _add_item_with_box(int id, const struct RTree_Rect *rect,
  457. struct boxlist *list)
  458. {
  459. struct bound_box box;
  460. box.W = rect->boundary[0];
  461. box.S = rect->boundary[1];
  462. box.B = rect->boundary[2];
  463. box.E = rect->boundary[3];
  464. box.N = rect->boundary[4];
  465. box.T = rect->boundary[5];
  466. dig_boxlist_add(list, id, box);
  467. return 1;
  468. }
  469. struct boxid
  470. {
  471. int id;
  472. struct bound_box *box;
  473. };
  474. /* This function is called by RTreeSearch() to add
  475. * selected node/line/area/isle to the box list */
  476. static int _set_item_box(int id, const struct RTree_Rect *rect,
  477. struct boxid *box_id)
  478. {
  479. if (id == box_id->id) {
  480. box_id->box->W = rect->boundary[0];
  481. box_id->box->S = rect->boundary[1];
  482. box_id->box->B = rect->boundary[2];
  483. box_id->box->E = rect->boundary[3];
  484. box_id->box->N = rect->boundary[4];
  485. box_id->box->T = rect->boundary[5];
  486. return 0;
  487. }
  488. return 1;
  489. }
  490. /*!
  491. \brief Select nodes by bbox
  492. \param Plus pointer to Plus_head structure
  493. \param box bounding box
  494. \param list list of selected lines
  495. \return number of selected nodes
  496. \return -1 on error
  497. */
  498. int
  499. dig_select_nodes(struct Plus_head *Plus, const struct bound_box * box,
  500. struct ilist *list)
  501. {
  502. static struct RTree_Rect rect;
  503. static int rect_init = 0;
  504. if (!rect_init) {
  505. /* always 6 sides for 3D */
  506. rect.boundary = G_malloc(6 * sizeof(RectReal));
  507. rect_init = 6;
  508. }
  509. G_debug(3, "dig_select_nodes()");
  510. list->n_values = 0;
  511. rect.boundary[0] = box->W;
  512. rect.boundary[1] = box->S;
  513. rect.boundary[2] = box->B;
  514. rect.boundary[3] = box->E;
  515. rect.boundary[4] = box->N;
  516. rect.boundary[5] = box->T;
  517. if (Plus->Spidx_new)
  518. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
  519. else
  520. rtree_search(Plus->Node_spidx, &rect, (void *)_add_item, list, Plus);
  521. return (list->n_values);
  522. }
  523. /* This function is called by RTreeSearch() for nodes to find the node id */
  524. static int _add_node(int id, const struct RTree_Rect *rect, int *node)
  525. {
  526. *node = id;
  527. return 0;
  528. }
  529. /*!
  530. \brief Find one node by coordinates
  531. \param Plus pointer to Plus_head structure
  532. \param x,y,z coordinates
  533. \return number of node
  534. \return 0 not found
  535. */
  536. int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
  537. {
  538. int node;
  539. static struct RTree_Rect rect;
  540. static int rect_init = 0;
  541. if (!rect_init) {
  542. /* always 6 sides for 3D */
  543. rect.boundary = G_malloc(6 * sizeof(RectReal));
  544. rect_init = 6;
  545. }
  546. G_debug(3, "dig_find_node()");
  547. rect.boundary[0] = x;
  548. rect.boundary[1] = y;
  549. rect.boundary[2] = z;
  550. rect.boundary[3] = x;
  551. rect.boundary[4] = y;
  552. rect.boundary[5] = z;
  553. node = 0;
  554. if (Plus->Spidx_new)
  555. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
  556. else
  557. rtree_search(Plus->Node_spidx, &rect, (void *)_add_node, &node, Plus);
  558. return node;
  559. }
  560. /*!
  561. \brief Select lines with boxes by box
  562. \param Plus pointer to Plus_head structure
  563. \param box bounding box
  564. \param list boxlist of selected lines
  565. \return number of selected lines
  566. \return 0 not found
  567. */
  568. int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box,
  569. struct boxlist *list)
  570. {
  571. static struct RTree_Rect rect;
  572. static int rect_init = 0;
  573. if (!rect_init) {
  574. /* always 6 sides for 3D */
  575. rect.boundary = G_malloc(6 * sizeof(RectReal));
  576. rect_init = 6;
  577. }
  578. G_debug(3, "dig_select_lines_with_box()");
  579. list->n_values = 0;
  580. rect.boundary[0] = box->W;
  581. rect.boundary[1] = box->S;
  582. rect.boundary[2] = box->B;
  583. rect.boundary[3] = box->E;
  584. rect.boundary[4] = box->N;
  585. rect.boundary[5] = box->T;
  586. if (Plus->Spidx_new)
  587. RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list);
  588. else
  589. rtree_search(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  590. return (list->n_values);
  591. }
  592. /*!
  593. \brief Find box for line
  594. \param Plus pointer to Plus_head structure
  595. \param line line id
  596. \param[out] box bounding box
  597. \return > 0 bounding box for line found
  598. \return 0 not found
  599. */
  600. int dig_find_line_box(struct Plus_head *Plus, int line,
  601. struct bound_box *box)
  602. {
  603. int ret, type;
  604. struct P_line *Line;
  605. struct boxid box_id;
  606. static struct RTree_Rect rect;
  607. static int rect_init = 0;
  608. G_debug(3, "dig_find_line_box()");
  609. if (!rect_init) {
  610. /* always 6 sides for 3D */
  611. rect.boundary = G_malloc(6 * sizeof(RectReal));
  612. rect_init = 6;
  613. }
  614. Line = Plus->Line[line];
  615. type = Line->type;
  616. /* GV_LINES: retrieve box from spatial index */
  617. if (type & GV_LINES) {
  618. struct P_node *Node = NULL;
  619. if (type == GV_LINE) {
  620. struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
  621. Node = Plus->Node[topo->N1];
  622. }
  623. else if (type == GV_BOUNDARY) {
  624. struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
  625. Node = Plus->Node[topo->N1];
  626. }
  627. rect.boundary[0] = Node->x;
  628. rect.boundary[1] = Node->y;
  629. rect.boundary[2] = Node->z;
  630. rect.boundary[3] = Node->x;
  631. rect.boundary[4] = Node->y;
  632. rect.boundary[5] = Node->z;
  633. box_id.id = line;
  634. box_id.box = box;
  635. if (Plus->Spidx_new)
  636. ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id);
  637. else
  638. ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  639. return ret;
  640. }
  641. /* do not translate this error because
  642. * 1. this error is not supposed to happen
  643. * 2. the maintainer at which this message is directed prefers english */
  644. G_fatal_error("Bug in vector lib: dig_find_line_box() may only be used for lines and boundaries.");
  645. return 0;
  646. }
  647. /*!
  648. \brief Select areas with boxes by box
  649. \param Plus pointer to Plus_head structure
  650. \param box bounding box
  651. \param list boxlist of selected areas
  652. \return number of selected areas
  653. */
  654. int
  655. dig_select_areas(struct Plus_head *Plus, const struct bound_box *box,
  656. struct boxlist *list)
  657. {
  658. static struct RTree_Rect rect;
  659. static int rect_init = 0;
  660. if (!rect_init) {
  661. /* always 6 sides for 3D */
  662. rect.boundary = G_malloc(6 * sizeof(RectReal));
  663. rect_init = 6;
  664. }
  665. G_debug(3, "dig_select_areas_with_box()");
  666. list->n_values = 0;
  667. rect.boundary[0] = box->W;
  668. rect.boundary[1] = box->S;
  669. rect.boundary[2] = box->B;
  670. rect.boundary[3] = box->E;
  671. rect.boundary[4] = box->N;
  672. rect.boundary[5] = box->T;
  673. if (Plus->Spidx_new)
  674. RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list);
  675. else
  676. rtree_search(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  677. return (list->n_values);
  678. }
  679. /*!
  680. \brief Find bounding box for given area
  681. \param Plus pointer to Plus_head structure
  682. \param area area id
  683. \param[out] box bounding box
  684. \return > 0 bounding box for area found
  685. \return 0 not found
  686. */
  687. int dig_find_area_box(struct Plus_head *Plus, int area,
  688. struct bound_box *box)
  689. {
  690. int ret;
  691. struct boxid box_id;
  692. struct P_area *Area;
  693. struct P_line *Line;
  694. struct P_node *Node;
  695. struct P_topo_b *topo;
  696. static struct RTree_Rect rect;
  697. static int rect_init = 0;
  698. G_debug(3, "dig_find_area_box()");
  699. if (!rect_init) {
  700. /* always 6 sides for 3D */
  701. rect.boundary = G_malloc(6 * sizeof(RectReal));
  702. rect_init = 6;
  703. }
  704. Area = Plus->Area[area];
  705. Line = Plus->Line[abs(Area->lines[0])];
  706. topo = (struct P_topo_b *)Line->topo;
  707. Node = Plus->Node[topo->N1];
  708. rect.boundary[0] = Node->x;
  709. rect.boundary[1] = Node->y;
  710. rect.boundary[2] = Node->z;
  711. rect.boundary[3] = Node->x;
  712. rect.boundary[4] = Node->y;
  713. rect.boundary[5] = Node->z;
  714. box_id.id = area;
  715. box_id.box = box;
  716. if (Plus->Spidx_new)
  717. ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id);
  718. else
  719. ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  720. return ret;
  721. }
  722. /*!
  723. \brief Select isles with boxes by box
  724. \param Plus pointer to Plus_head structure
  725. \param box bounding box
  726. \param list boxlist of selected isles
  727. \return number of selected isles
  728. */
  729. int
  730. dig_select_isles(struct Plus_head *Plus, const struct bound_box * box,
  731. struct boxlist *list)
  732. {
  733. static struct RTree_Rect rect;
  734. static int rect_init = 0;
  735. if (!rect_init) {
  736. /* always 6 sides for 3D */
  737. rect.boundary = G_malloc(6 * sizeof(RectReal));
  738. rect_init = 6;
  739. }
  740. G_debug(3, "dig_select_areas_with_box()");
  741. list->n_values = 0;
  742. rect.boundary[0] = box->W;
  743. rect.boundary[1] = box->S;
  744. rect.boundary[2] = box->B;
  745. rect.boundary[3] = box->E;
  746. rect.boundary[4] = box->N;
  747. rect.boundary[5] = box->T;
  748. if (Plus->Spidx_new)
  749. RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list);
  750. else
  751. rtree_search(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  752. return (list->n_values);
  753. }
  754. /*!
  755. \brief Find box for isle
  756. \param Plus pointer to Plus_head structure
  757. \param isle isle id
  758. \param[out] box bounding box
  759. \return > 0 bounding box for isle found
  760. \return 0 not found
  761. */
  762. int dig_find_isle_box(struct Plus_head *Plus, int isle,
  763. struct bound_box *box)
  764. {
  765. int ret;
  766. struct boxid box_id;
  767. struct P_isle *Isle;
  768. struct P_line *Line;
  769. struct P_node *Node;
  770. struct P_topo_b *topo;
  771. static struct RTree_Rect rect;
  772. static int rect_init = 0;
  773. G_debug(3, "dig_find_isle_box()");
  774. if (!rect_init) {
  775. /* always 6 sides for 3D */
  776. rect.boundary = G_malloc(6 * sizeof(RectReal));
  777. rect_init = 6;
  778. }
  779. Isle = Plus->Isle[isle];
  780. Line = Plus->Line[abs(Isle->lines[0])];
  781. topo = (struct P_topo_b *)Line->topo;
  782. Node = Plus->Node[topo->N1];
  783. rect.boundary[0] = Node->x;
  784. rect.boundary[1] = Node->y;
  785. rect.boundary[2] = Node->z;
  786. rect.boundary[3] = Node->x;
  787. rect.boundary[4] = Node->y;
  788. rect.boundary[5] = Node->z;
  789. box_id.id = isle;
  790. box_id.box = box;
  791. if (Plus->Spidx_new)
  792. ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id);
  793. else
  794. ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  795. return ret;
  796. }