spindex.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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, struct bound_box * box)
  235. {
  236. static struct RTree_Rect rect;
  237. static int rect_init = 0;
  238. if (!rect_init) {
  239. /* always 6 sides for 3D */
  240. rect.boundary = G_malloc(6 * sizeof(RectReal));
  241. rect_init = 6;
  242. }
  243. G_debug(3, "dig_spidx_add_line(): line = %d", line);
  244. rect.boundary[0] = box->W;
  245. rect.boundary[1] = box->S;
  246. rect.boundary[2] = box->B;
  247. rect.boundary[3] = box->E;
  248. rect.boundary[4] = box->N;
  249. rect.boundary[5] = box->T;
  250. RTreeInsertRect(&rect, line, Plus->Line_spidx);
  251. return 0;
  252. }
  253. /*!
  254. \brief Add new area to spatial index
  255. \param Plus pointer to Plus_head structure
  256. \param area area id
  257. \param box bounding box
  258. \return 0
  259. */
  260. int dig_spidx_add_area(struct Plus_head *Plus, int area, struct bound_box * box)
  261. {
  262. static struct RTree_Rect rect;
  263. static int rect_init = 0;
  264. if (!rect_init) {
  265. /* always 6 sides for 3D */
  266. rect.boundary = G_malloc(6 * sizeof(RectReal));
  267. rect_init = 6;
  268. }
  269. G_debug(3, "dig_spidx_add_area(): area = %d", area);
  270. rect.boundary[0] = box->W;
  271. rect.boundary[1] = box->S;
  272. rect.boundary[2] = box->B;
  273. rect.boundary[3] = box->E;
  274. rect.boundary[4] = box->N;
  275. rect.boundary[5] = box->T;
  276. RTreeInsertRect(&rect, area, Plus->Area_spidx);
  277. return 0;
  278. }
  279. /*!
  280. \brief Add new island to spatial index
  281. \param Plus pointer to Plus_head structure
  282. \param isle isle id
  283. \param box bounding box
  284. \return 0
  285. */
  286. int dig_spidx_add_isle(struct Plus_head *Plus, int isle, struct bound_box * box)
  287. {
  288. static struct RTree_Rect rect;
  289. static int rect_init = 0;
  290. if (!rect_init) {
  291. /* always 6 sides for 3D */
  292. rect.boundary = G_malloc(6 * sizeof(RectReal));
  293. rect_init = 6;
  294. }
  295. G_debug(3, "dig_spidx_add_isle(): isle = %d", isle);
  296. rect.boundary[0] = box->W;
  297. rect.boundary[1] = box->S;
  298. rect.boundary[2] = box->B;
  299. rect.boundary[3] = box->E;
  300. rect.boundary[4] = box->N;
  301. rect.boundary[5] = box->T;
  302. RTreeInsertRect(&rect, isle, Plus->Isle_spidx);
  303. return 0;
  304. }
  305. /*!
  306. \brief Delete node from spatial index
  307. G_fatal_error() called on error.
  308. \param Plus pointer to Plus_head structure
  309. \param node node id
  310. \return 0
  311. */
  312. int dig_spidx_del_node(struct Plus_head *Plus, int node)
  313. {
  314. int ret;
  315. struct P_node *Node;
  316. static struct RTree_Rect rect;
  317. static int rect_init = 0;
  318. if (!rect_init) {
  319. /* always 6 sides for 3D */
  320. rect.boundary = G_malloc(6 * sizeof(RectReal));
  321. rect_init = 6;
  322. }
  323. G_debug(3, "dig_spidx_del_node(): node = %d", node);
  324. Node = Plus->Node[node];
  325. rect.boundary[0] = Node->x;
  326. rect.boundary[1] = Node->y;
  327. rect.boundary[2] = Node->z;
  328. rect.boundary[3] = Node->x;
  329. rect.boundary[4] = Node->y;
  330. rect.boundary[5] = Node->z;
  331. ret = RTreeDeleteRect(&rect, node, Plus->Node_spidx);
  332. if (ret)
  333. G_fatal_error(_("Unable to delete node %d from spatial index"), node);
  334. return 0;
  335. }
  336. /*!
  337. \brief Delete line from spatial index
  338. G_fatal_error() called on error.
  339. \param Plus pointer to Plus_head structure
  340. \param line line id
  341. \return 0
  342. */
  343. int dig_spidx_del_line(struct Plus_head *Plus, int line, double x, double y, double z)
  344. {
  345. int ret;
  346. struct P_line *Line;
  347. static struct RTree_Rect rect;
  348. static int rect_init = 0;
  349. if (!rect_init) {
  350. /* always 6 sides for 3D */
  351. rect.boundary = G_malloc(6 * sizeof(RectReal));
  352. rect_init = 6;
  353. }
  354. G_debug(3, "dig_spidx_del_line(): line = %d", line);
  355. Line = Plus->Line[line];
  356. rect.boundary[0] = x;
  357. rect.boundary[1] = y;
  358. rect.boundary[2] = z;
  359. rect.boundary[3] = x;
  360. rect.boundary[4] = y;
  361. rect.boundary[5] = z;
  362. ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
  363. G_debug(3, " ret = %d", ret);
  364. if (ret)
  365. G_fatal_error(_("Unable to delete line %d from spatial index"), line);
  366. return 0;
  367. }
  368. /*!
  369. \brief Delete area from spatial index
  370. G_fatal_error() called on error.
  371. \param Plus pointer to Plus_head structure
  372. \param area area id
  373. \return 0
  374. */
  375. int dig_spidx_del_area(struct Plus_head *Plus, int area)
  376. {
  377. int ret;
  378. struct P_area *Area;
  379. struct P_line *Line;
  380. struct P_node *Node;
  381. struct P_topo_b *topo;
  382. static struct RTree_Rect rect;
  383. static int rect_init = 0;
  384. if (!rect_init) {
  385. /* always 6 sides for 3D */
  386. rect.boundary = G_malloc(6 * sizeof(RectReal));
  387. rect_init = 6;
  388. }
  389. G_debug(3, "dig_spidx_del_area(): area = %d", area);
  390. Area = Plus->Area[area];
  391. if (Area == NULL) {
  392. G_fatal_error(_("Attempt to delete sidx for dead area"));
  393. }
  394. Line = Plus->Line[abs(Area->lines[0])];
  395. topo = (struct P_topo_b *)Line->topo;
  396. Node = Plus->Node[topo->N1];
  397. rect.boundary[0] = Node->x;
  398. rect.boundary[1] = Node->y;
  399. rect.boundary[2] = Node->z;
  400. rect.boundary[3] = Node->x;
  401. rect.boundary[4] = Node->y;
  402. rect.boundary[5] = Node->z;
  403. ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
  404. if (ret)
  405. G_fatal_error(_("Unable to delete area %d from spatial index"), area);
  406. return 0;
  407. }
  408. /*!
  409. \brief Delete isle from spatial index
  410. G_fatal_error() called on error.
  411. \param Plus pointer to Plus_head structure
  412. \param isle isle id
  413. \return 0
  414. */
  415. int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
  416. {
  417. int ret;
  418. struct P_isle *Isle;
  419. struct P_line *Line;
  420. struct P_node *Node;
  421. struct P_topo_b *topo;
  422. static struct RTree_Rect rect;
  423. static int rect_init = 0;
  424. if (!rect_init) {
  425. /* always 6 sides for 3D */
  426. rect.boundary = G_malloc(6 * sizeof(RectReal));
  427. rect_init = 6;
  428. }
  429. G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
  430. Isle = Plus->Isle[isle];
  431. Line = Plus->Line[abs(Isle->lines[0])];
  432. topo = (struct P_topo_b *)Line->topo;
  433. Node = Plus->Node[topo->N1];
  434. rect.boundary[0] = Node->x;
  435. rect.boundary[1] = Node->y;
  436. rect.boundary[2] = Node->z;
  437. rect.boundary[3] = Node->x;
  438. rect.boundary[4] = Node->y;
  439. rect.boundary[5] = Node->z;
  440. ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
  441. if (ret)
  442. G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
  443. return 0;
  444. }
  445. /* This function is called by RTreeSearch() to add selected node/line/area/isle to the list */
  446. static int _add_item(int id, struct RTree_Rect rect, struct ilist *list)
  447. {
  448. G_ilist_add(list, id);
  449. return 1;
  450. }
  451. /* This function is called by RTreeSearch() to add
  452. * selected node/line/area/isle to the box list */
  453. static int _add_item_with_box(int id, struct RTree_Rect rect, struct boxlist *list)
  454. {
  455. struct bound_box box;
  456. box.W = rect.boundary[0];
  457. box.S = rect.boundary[1];
  458. box.B = rect.boundary[2];
  459. box.E = rect.boundary[3];
  460. box.N = rect.boundary[4];
  461. box.T = rect.boundary[5];
  462. dig_boxlist_add(list, id, box);
  463. return 1;
  464. }
  465. /* This function is called by RTreeSearch() to add
  466. * selected node/line/area/isle to the box list */
  467. static int _set_item_box(int id, struct RTree_Rect rect, struct boxlist *list)
  468. {
  469. if (id == list->id[0]) {
  470. list->box[0].W = rect.boundary[0];
  471. list->box[0].S = rect.boundary[1];
  472. list->box[0].B = rect.boundary[2];
  473. list->box[0].E = rect.boundary[3];
  474. list->box[0].N = rect.boundary[4];
  475. list->box[0].T = rect.boundary[5];
  476. return 0;
  477. }
  478. return 1;
  479. }
  480. /*!
  481. \brief Select nodes by bbox
  482. \param Plus pointer to Plus_head structure
  483. \param box bounding box
  484. \param list list of selected lines
  485. \return number of selected nodes
  486. \return -1 on error
  487. */
  488. int
  489. dig_select_nodes(struct Plus_head *Plus, const struct bound_box * box,
  490. struct ilist *list)
  491. {
  492. static struct RTree_Rect rect;
  493. static int rect_init = 0;
  494. if (!rect_init) {
  495. /* always 6 sides for 3D */
  496. rect.boundary = G_malloc(6 * sizeof(RectReal));
  497. rect_init = 6;
  498. }
  499. G_debug(3, "dig_select_nodes()");
  500. list->n_values = 0;
  501. rect.boundary[0] = box->W;
  502. rect.boundary[1] = box->S;
  503. rect.boundary[2] = box->B;
  504. rect.boundary[3] = box->E;
  505. rect.boundary[4] = box->N;
  506. rect.boundary[5] = box->T;
  507. if (Plus->Spidx_new)
  508. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
  509. else
  510. rtree_search(Plus->Node_spidx, &rect, (void *)_add_item, list, Plus);
  511. return (list->n_values);
  512. }
  513. /* This function is called by RTreeSearch() for nodes to find the node id */
  514. static int _add_node(int id, struct RTree_Rect rect, int *node)
  515. {
  516. *node = id;
  517. return 0;
  518. }
  519. /*!
  520. \brief Find one node by coordinates
  521. \param Plus pointer to Plus_head structure
  522. \param x,y,z coordinates
  523. \return number of node
  524. \return 0 not found
  525. */
  526. int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
  527. {
  528. int node;
  529. static struct RTree_Rect rect;
  530. static int rect_init = 0;
  531. if (!rect_init) {
  532. /* always 6 sides for 3D */
  533. rect.boundary = G_malloc(6 * sizeof(RectReal));
  534. rect_init = 6;
  535. }
  536. G_debug(3, "dig_find_node()");
  537. rect.boundary[0] = x;
  538. rect.boundary[1] = y;
  539. rect.boundary[2] = z;
  540. rect.boundary[3] = x;
  541. rect.boundary[4] = y;
  542. rect.boundary[5] = z;
  543. node = 0;
  544. if (Plus->Spidx_new)
  545. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
  546. else
  547. rtree_search(Plus->Node_spidx, &rect, (void *)_add_node, &node, Plus);
  548. return node;
  549. }
  550. /*!
  551. \brief Select lines with boxes by box
  552. \param Plus pointer to Plus_head structure
  553. \param box bounding box
  554. \param list boxlist of selected lines
  555. \return number of selected lines
  556. \return 0 not found
  557. */
  558. int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box,
  559. struct boxlist *list)
  560. {
  561. static struct RTree_Rect rect;
  562. static int rect_init = 0;
  563. if (!rect_init) {
  564. /* always 6 sides for 3D */
  565. rect.boundary = G_malloc(6 * sizeof(RectReal));
  566. rect_init = 6;
  567. }
  568. G_debug(3, "dig_select_lines_with_box()");
  569. list->n_values = 0;
  570. rect.boundary[0] = box->W;
  571. rect.boundary[1] = box->S;
  572. rect.boundary[2] = box->B;
  573. rect.boundary[3] = box->E;
  574. rect.boundary[4] = box->N;
  575. rect.boundary[5] = box->T;
  576. if (Plus->Spidx_new)
  577. RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list);
  578. else
  579. rtree_search(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  580. return (list->n_values);
  581. }
  582. /*!
  583. \brief Find box for line
  584. \param Plus pointer to Plus_head structure
  585. \param[in,out] list line with isle id and search box (in)/line box (out)
  586. \return number of lines found
  587. \return 0 not found
  588. */
  589. int dig_find_line_box(struct Plus_head *Plus, struct boxlist *list)
  590. {
  591. int ret;
  592. static struct RTree_Rect rect;
  593. static int rect_init = 0;
  594. if (!rect_init) {
  595. /* always 6 sides for 3D */
  596. rect.boundary = G_malloc(6 * sizeof(RectReal));
  597. rect_init = 6;
  598. }
  599. G_debug(3, "dig_find_line_box()");
  600. if (list->n_values < 1)
  601. G_fatal_error(_("No line id given"));
  602. rect.boundary[0] = list->box[0].W;
  603. rect.boundary[1] = list->box[0].S;
  604. rect.boundary[2] = list->box[0].B;
  605. rect.boundary[3] = list->box[0].E;
  606. rect.boundary[4] = list->box[0].N;
  607. rect.boundary[5] = list->box[0].T;
  608. if (Plus->Spidx_new)
  609. ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, list);
  610. else
  611. ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, list, Plus);
  612. return (ret);
  613. }
  614. /*!
  615. \brief Select areas with boxes by box
  616. \param Plus pointer to Plus_head structure
  617. \param box bounding box
  618. \param list boxlist of selected areas
  619. \return number of selected areas
  620. */
  621. int
  622. dig_select_areas(struct Plus_head *Plus, const struct bound_box * box,
  623. struct boxlist *list)
  624. {
  625. static struct RTree_Rect rect;
  626. static int rect_init = 0;
  627. if (!rect_init) {
  628. /* always 6 sides for 3D */
  629. rect.boundary = G_malloc(6 * sizeof(RectReal));
  630. rect_init = 6;
  631. }
  632. G_debug(3, "dig_select_areas_with_box()");
  633. list->n_values = 0;
  634. rect.boundary[0] = box->W;
  635. rect.boundary[1] = box->S;
  636. rect.boundary[2] = box->B;
  637. rect.boundary[3] = box->E;
  638. rect.boundary[4] = box->N;
  639. rect.boundary[5] = box->T;
  640. if (Plus->Spidx_new)
  641. RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list);
  642. else
  643. rtree_search(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  644. return (list->n_values);
  645. }
  646. /*!
  647. \brief Find bounding box for given area
  648. \param Plus pointer to Plus_head structure
  649. \param[in,out] list list with area id and search box (in)/area box (out)
  650. \return number of areas found
  651. \return 0 not found
  652. */
  653. int dig_find_area_box(struct Plus_head *Plus, struct boxlist *list)
  654. {
  655. int ret;
  656. static struct RTree_Rect rect;
  657. static int rect_init = 0;
  658. if (!rect_init) {
  659. /* always 6 sides for 3D */
  660. rect.boundary = G_malloc(6 * sizeof(RectReal));
  661. rect_init = 6;
  662. }
  663. G_debug(3, "dig_find_line_box()");
  664. if (list->n_values < 1)
  665. G_fatal_error(_("Unable to get area bounding box. No feature id given."));
  666. rect.boundary[0] = list->box[0].W;
  667. rect.boundary[1] = list->box[0].S;
  668. rect.boundary[2] = list->box[0].B;
  669. rect.boundary[3] = list->box[0].E;
  670. rect.boundary[4] = list->box[0].N;
  671. rect.boundary[5] = list->box[0].T;
  672. if (Plus->Spidx_new)
  673. ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, list);
  674. else
  675. ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, list, Plus);
  676. return ret;
  677. }
  678. /*!
  679. \brief Select isles with boxes by box
  680. \param Plus pointer to Plus_head structure
  681. \param box bounding box
  682. \param list boxlist of selected isles
  683. \return number of selected isles
  684. */
  685. int
  686. dig_select_isles(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->Isle_spidx, &rect, (void *)_add_item_with_box, list);
  706. else
  707. rtree_search(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  708. return (list->n_values);
  709. }
  710. /*!
  711. \brief Find box for isle
  712. \param Plus pointer to Plus_head structure
  713. \param[in,out] list list with isle id and search box (in)/isle box (out)
  714. \return number of isles found
  715. \return 0 not found
  716. */
  717. int dig_find_isle_box(struct Plus_head *Plus, struct boxlist *list)
  718. {
  719. int ret;
  720. static struct RTree_Rect rect;
  721. static int rect_init = 0;
  722. if (!rect_init) {
  723. /* always 6 sides for 3D */
  724. rect.boundary = G_malloc(6 * sizeof(RectReal));
  725. rect_init = 6;
  726. }
  727. G_debug(3, "dig_find_line_box()");
  728. if (list->n_values < 1)
  729. G_fatal_error(_("No line id given"));
  730. rect.boundary[0] = list->box[0].W;
  731. rect.boundary[1] = list->box[0].S;
  732. rect.boundary[2] = list->box[0].B;
  733. rect.boundary[3] = list->box[0].E;
  734. rect.boundary[4] = list->box[0].N;
  735. rect.boundary[5] = list->box[0].T;
  736. if (Plus->Spidx_new)
  737. ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, list);
  738. else
  739. ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, list, Plus);
  740. return (ret);
  741. }