spindex.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  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, const 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, const 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, const 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. static struct RTree_Rect rect;
  347. static int rect_init = 0;
  348. if (!rect_init) {
  349. /* always 6 sides for 3D */
  350. rect.boundary = G_malloc(6 * sizeof(RectReal));
  351. rect_init = 6;
  352. }
  353. G_debug(3, "dig_spidx_del_line(): line = %d", line);
  354. rect.boundary[0] = x;
  355. rect.boundary[1] = y;
  356. rect.boundary[2] = z;
  357. rect.boundary[3] = x;
  358. rect.boundary[4] = y;
  359. rect.boundary[5] = z;
  360. ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
  361. G_debug(3, " ret = %d", ret);
  362. if (ret)
  363. G_fatal_error(_("Unable to delete line %d from spatial index"), line);
  364. return 0;
  365. }
  366. /*!
  367. \brief Delete area from spatial index
  368. G_fatal_error() called on error.
  369. \param Plus pointer to Plus_head structure
  370. \param area area id
  371. \return 0
  372. */
  373. int dig_spidx_del_area(struct Plus_head *Plus, int area)
  374. {
  375. int ret;
  376. struct P_area *Area;
  377. struct P_line *Line;
  378. struct P_node *Node;
  379. struct P_topo_b *topo;
  380. static struct RTree_Rect rect;
  381. static int rect_init = 0;
  382. if (!rect_init) {
  383. /* always 6 sides for 3D */
  384. rect.boundary = G_malloc(6 * sizeof(RectReal));
  385. rect_init = 6;
  386. }
  387. G_debug(3, "dig_spidx_del_area(): area = %d", area);
  388. Area = Plus->Area[area];
  389. if (Area == NULL) {
  390. G_fatal_error(_("Attempt to delete sidx for dead area"));
  391. }
  392. Line = Plus->Line[abs(Area->lines[0])];
  393. topo = (struct P_topo_b *)Line->topo;
  394. Node = Plus->Node[topo->N1];
  395. rect.boundary[0] = Node->x;
  396. rect.boundary[1] = Node->y;
  397. rect.boundary[2] = Node->z;
  398. rect.boundary[3] = Node->x;
  399. rect.boundary[4] = Node->y;
  400. rect.boundary[5] = Node->z;
  401. ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
  402. if (ret)
  403. G_fatal_error(_("Unable to delete area %d from spatial index"), area);
  404. return 0;
  405. }
  406. /*!
  407. \brief Delete isle from spatial index
  408. G_fatal_error() called on error.
  409. \param Plus pointer to Plus_head structure
  410. \param isle isle id
  411. \return 0
  412. */
  413. int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
  414. {
  415. int ret;
  416. struct P_isle *Isle;
  417. struct P_line *Line;
  418. struct P_node *Node;
  419. struct P_topo_b *topo;
  420. static struct RTree_Rect rect;
  421. static int rect_init = 0;
  422. if (!rect_init) {
  423. /* always 6 sides for 3D */
  424. rect.boundary = G_malloc(6 * sizeof(RectReal));
  425. rect_init = 6;
  426. }
  427. G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
  428. Isle = Plus->Isle[isle];
  429. Line = Plus->Line[abs(Isle->lines[0])];
  430. topo = (struct P_topo_b *)Line->topo;
  431. Node = Plus->Node[topo->N1];
  432. rect.boundary[0] = Node->x;
  433. rect.boundary[1] = Node->y;
  434. rect.boundary[2] = Node->z;
  435. rect.boundary[3] = Node->x;
  436. rect.boundary[4] = Node->y;
  437. rect.boundary[5] = Node->z;
  438. ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
  439. if (ret)
  440. G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
  441. return 0;
  442. }
  443. /* This function is called by RTreeSearch() to add selected node/line/area/isle to the list */
  444. static int _add_item(int id, struct RTree_Rect rect, struct ilist *list)
  445. {
  446. G_ilist_add(list, id);
  447. return 1;
  448. }
  449. /* This function is called by RTreeSearch() to add
  450. * selected node/line/area/isle to the box list */
  451. static int _add_item_with_box(int id, struct RTree_Rect rect, struct boxlist *list)
  452. {
  453. struct bound_box box;
  454. box.W = rect.boundary[0];
  455. box.S = rect.boundary[1];
  456. box.B = rect.boundary[2];
  457. box.E = rect.boundary[3];
  458. box.N = rect.boundary[4];
  459. box.T = rect.boundary[5];
  460. dig_boxlist_add(list, id, box);
  461. return 1;
  462. }
  463. /* This function is called by RTreeSearch() to add
  464. * selected node/line/area/isle to the box list */
  465. static int _set_item_box(int id, struct RTree_Rect rect, struct boxlist *list)
  466. {
  467. if (id == list->id[0]) {
  468. list->box[0].W = rect.boundary[0];
  469. list->box[0].S = rect.boundary[1];
  470. list->box[0].B = rect.boundary[2];
  471. list->box[0].E = rect.boundary[3];
  472. list->box[0].N = rect.boundary[4];
  473. list->box[0].T = rect.boundary[5];
  474. return 0;
  475. }
  476. return 1;
  477. }
  478. /*!
  479. \brief Select nodes by bbox
  480. \param Plus pointer to Plus_head structure
  481. \param box bounding box
  482. \param list list of selected lines
  483. \return number of selected nodes
  484. \return -1 on error
  485. */
  486. int
  487. dig_select_nodes(struct Plus_head *Plus, const struct bound_box * box,
  488. struct ilist *list)
  489. {
  490. static struct RTree_Rect rect;
  491. static int rect_init = 0;
  492. if (!rect_init) {
  493. /* always 6 sides for 3D */
  494. rect.boundary = G_malloc(6 * sizeof(RectReal));
  495. rect_init = 6;
  496. }
  497. G_debug(3, "dig_select_nodes()");
  498. list->n_values = 0;
  499. rect.boundary[0] = box->W;
  500. rect.boundary[1] = box->S;
  501. rect.boundary[2] = box->B;
  502. rect.boundary[3] = box->E;
  503. rect.boundary[4] = box->N;
  504. rect.boundary[5] = box->T;
  505. if (Plus->Spidx_new)
  506. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
  507. else
  508. rtree_search(Plus->Node_spidx, &rect, (void *)_add_item, list, Plus);
  509. return (list->n_values);
  510. }
  511. /* This function is called by RTreeSearch() for nodes to find the node id */
  512. static int _add_node(int id, struct RTree_Rect rect, int *node)
  513. {
  514. *node = id;
  515. return 0;
  516. }
  517. /*!
  518. \brief Find one node by coordinates
  519. \param Plus pointer to Plus_head structure
  520. \param x,y,z coordinates
  521. \return number of node
  522. \return 0 not found
  523. */
  524. int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
  525. {
  526. int node;
  527. static struct RTree_Rect rect;
  528. static int rect_init = 0;
  529. if (!rect_init) {
  530. /* always 6 sides for 3D */
  531. rect.boundary = G_malloc(6 * sizeof(RectReal));
  532. rect_init = 6;
  533. }
  534. G_debug(3, "dig_find_node()");
  535. rect.boundary[0] = x;
  536. rect.boundary[1] = y;
  537. rect.boundary[2] = z;
  538. rect.boundary[3] = x;
  539. rect.boundary[4] = y;
  540. rect.boundary[5] = z;
  541. node = 0;
  542. if (Plus->Spidx_new)
  543. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
  544. else
  545. rtree_search(Plus->Node_spidx, &rect, (void *)_add_node, &node, Plus);
  546. return node;
  547. }
  548. /*!
  549. \brief Select lines with boxes by box
  550. \param Plus pointer to Plus_head structure
  551. \param box bounding box
  552. \param list boxlist of selected lines
  553. \return number of selected lines
  554. \return 0 not found
  555. */
  556. int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box,
  557. struct boxlist *list)
  558. {
  559. static struct RTree_Rect rect;
  560. static int rect_init = 0;
  561. if (!rect_init) {
  562. /* always 6 sides for 3D */
  563. rect.boundary = G_malloc(6 * sizeof(RectReal));
  564. rect_init = 6;
  565. }
  566. G_debug(3, "dig_select_lines_with_box()");
  567. list->n_values = 0;
  568. rect.boundary[0] = box->W;
  569. rect.boundary[1] = box->S;
  570. rect.boundary[2] = box->B;
  571. rect.boundary[3] = box->E;
  572. rect.boundary[4] = box->N;
  573. rect.boundary[5] = box->T;
  574. if (Plus->Spidx_new)
  575. RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list);
  576. else
  577. rtree_search(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  578. return (list->n_values);
  579. }
  580. /*!
  581. \brief Find box for line
  582. \param Plus pointer to Plus_head structure
  583. \param[in,out] list line with isle id and search box (in)/line box (out)
  584. \return number of lines found
  585. \return 0 not found
  586. */
  587. int dig_find_line_box(struct Plus_head *Plus, struct boxlist *list)
  588. {
  589. int ret;
  590. static struct RTree_Rect rect;
  591. static int rect_init = 0;
  592. if (!rect_init) {
  593. /* always 6 sides for 3D */
  594. rect.boundary = G_malloc(6 * sizeof(RectReal));
  595. rect_init = 6;
  596. }
  597. G_debug(3, "dig_find_line_box()");
  598. if (list->n_values < 1)
  599. G_fatal_error(_("No line id given"));
  600. rect.boundary[0] = list->box[0].W;
  601. rect.boundary[1] = list->box[0].S;
  602. rect.boundary[2] = list->box[0].B;
  603. rect.boundary[3] = list->box[0].E;
  604. rect.boundary[4] = list->box[0].N;
  605. rect.boundary[5] = list->box[0].T;
  606. if (Plus->Spidx_new)
  607. ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, list);
  608. else
  609. ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, list, Plus);
  610. return (ret);
  611. }
  612. /*!
  613. \brief Select areas with boxes by box
  614. \param Plus pointer to Plus_head structure
  615. \param box bounding box
  616. \param list boxlist of selected areas
  617. \return number of selected areas
  618. */
  619. int
  620. dig_select_areas(struct Plus_head *Plus, const struct bound_box * box,
  621. struct boxlist *list)
  622. {
  623. static struct RTree_Rect rect;
  624. static int rect_init = 0;
  625. if (!rect_init) {
  626. /* always 6 sides for 3D */
  627. rect.boundary = G_malloc(6 * sizeof(RectReal));
  628. rect_init = 6;
  629. }
  630. G_debug(3, "dig_select_areas_with_box()");
  631. list->n_values = 0;
  632. rect.boundary[0] = box->W;
  633. rect.boundary[1] = box->S;
  634. rect.boundary[2] = box->B;
  635. rect.boundary[3] = box->E;
  636. rect.boundary[4] = box->N;
  637. rect.boundary[5] = box->T;
  638. if (Plus->Spidx_new)
  639. RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list);
  640. else
  641. rtree_search(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  642. return (list->n_values);
  643. }
  644. /*!
  645. \brief Find bounding box for given area
  646. \param Plus pointer to Plus_head structure
  647. \param[in,out] list list with area id and search box (in)/area box (out)
  648. \return number of areas found
  649. \return 0 not found
  650. */
  651. int dig_find_area_box(struct Plus_head *Plus, struct boxlist *list)
  652. {
  653. int ret;
  654. static struct RTree_Rect rect;
  655. static int rect_init = 0;
  656. if (!rect_init) {
  657. /* always 6 sides for 3D */
  658. rect.boundary = G_malloc(6 * sizeof(RectReal));
  659. rect_init = 6;
  660. }
  661. G_debug(3, "dig_find_area_box()");
  662. if (list->n_values < 1)
  663. G_fatal_error(_("No area id given"));
  664. rect.boundary[0] = list->box[0].W;
  665. rect.boundary[1] = list->box[0].S;
  666. rect.boundary[2] = list->box[0].B;
  667. rect.boundary[3] = list->box[0].E;
  668. rect.boundary[4] = list->box[0].N;
  669. rect.boundary[5] = list->box[0].T;
  670. if (Plus->Spidx_new)
  671. ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, list);
  672. else
  673. ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, list, Plus);
  674. return ret;
  675. }
  676. /*!
  677. \brief Select isles with boxes by box
  678. \param Plus pointer to Plus_head structure
  679. \param box bounding box
  680. \param list boxlist of selected isles
  681. \return number of selected isles
  682. */
  683. int
  684. dig_select_isles(struct Plus_head *Plus, const struct bound_box * box,
  685. struct boxlist *list)
  686. {
  687. static struct RTree_Rect rect;
  688. static int rect_init = 0;
  689. if (!rect_init) {
  690. /* always 6 sides for 3D */
  691. rect.boundary = G_malloc(6 * sizeof(RectReal));
  692. rect_init = 6;
  693. }
  694. G_debug(3, "dig_select_areas_with_box()");
  695. list->n_values = 0;
  696. rect.boundary[0] = box->W;
  697. rect.boundary[1] = box->S;
  698. rect.boundary[2] = box->B;
  699. rect.boundary[3] = box->E;
  700. rect.boundary[4] = box->N;
  701. rect.boundary[5] = box->T;
  702. if (Plus->Spidx_new)
  703. RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list);
  704. else
  705. rtree_search(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  706. return (list->n_values);
  707. }
  708. /*!
  709. \brief Find box for isle
  710. \param Plus pointer to Plus_head structure
  711. \param[in,out] list list with isle id and search box (in)/isle box (out)
  712. \return number of isles found
  713. \return 0 not found
  714. */
  715. int dig_find_isle_box(struct Plus_head *Plus, struct boxlist *list)
  716. {
  717. int ret;
  718. static struct RTree_Rect rect;
  719. static int rect_init = 0;
  720. if (!rect_init) {
  721. /* always 6 sides for 3D */
  722. rect.boundary = G_malloc(6 * sizeof(RectReal));
  723. rect_init = 6;
  724. }
  725. G_debug(3, "dig_find_isle_box()");
  726. if (list->n_values < 1)
  727. G_fatal_error(_("No isle id given"));
  728. rect.boundary[0] = list->box[0].W;
  729. rect.boundary[1] = list->box[0].S;
  730. rect.boundary[2] = list->box[0].B;
  731. rect.boundary[3] = list->box[0].E;
  732. rect.boundary[4] = list->box[0].N;
  733. rect.boundary[5] = list->box[0].T;
  734. if (Plus->Spidx_new)
  735. ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, list);
  736. else
  737. ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, list, Plus);
  738. return (ret);
  739. }