spindex.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035
  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. RTreeDestroyTree(Plus->Node_spidx);
  212. /* Line spidx */
  213. RTreeDestroyTree(Plus->Line_spidx);
  214. /* Area spidx */
  215. RTreeDestroyTree(Plus->Area_spidx);
  216. /* Isle spidx */
  217. RTreeDestroyTree(Plus->Isle_spidx);
  218. /* 3D future : */
  219. /* Face spidx */
  220. /* Volume spidx */
  221. /* Hole spidx */
  222. }
  223. /*!
  224. \brief Add new node to spatial index
  225. \param Plus pointer to Plus_head structure
  226. \param node node id
  227. \param x,y,z node coordinates
  228. \return 1 OK
  229. \return 0 on error
  230. */
  231. int
  232. dig_spidx_add_node(struct Plus_head *Plus, int node,
  233. double x, double y, double z)
  234. {
  235. static struct RTree_Rect rect;
  236. static int rect_init = 0;
  237. if (!rect_init) {
  238. /* always 6 sides for 3D */
  239. rect.boundary = G_malloc(6 * sizeof(RectReal));
  240. rect_init = 6;
  241. }
  242. G_debug(3, "dig_spidx_add_node(): node = %d, x,y,z = %f, %f, %f", node, x,
  243. y, z);
  244. rect.boundary[0] = x;
  245. rect.boundary[1] = y;
  246. rect.boundary[2] = z;
  247. rect.boundary[3] = x;
  248. rect.boundary[4] = y;
  249. rect.boundary[5] = z;
  250. RTreeInsertRect(&rect, node, Plus->Node_spidx);
  251. return 1;
  252. }
  253. /*!
  254. \brief Add new line to spatial index
  255. \param Plus pointer to Plus_head structure
  256. \param line line id
  257. \param box bounding box
  258. \return 0
  259. */
  260. int dig_spidx_add_line(struct Plus_head *Plus, int line,
  261. const struct bound_box *box)
  262. {
  263. static struct RTree_Rect rect;
  264. static int rect_init = 0;
  265. if (!rect_init) {
  266. /* always 6 sides for 3D */
  267. rect.boundary = G_malloc(6 * sizeof(RectReal));
  268. rect_init = 6;
  269. }
  270. G_debug(3, "dig_spidx_add_line(): line = %d", line);
  271. rect.boundary[0] = box->W;
  272. rect.boundary[1] = box->S;
  273. rect.boundary[2] = box->B;
  274. rect.boundary[3] = box->E;
  275. rect.boundary[4] = box->N;
  276. rect.boundary[5] = box->T;
  277. RTreeInsertRect(&rect, line, Plus->Line_spidx);
  278. return 0;
  279. }
  280. /*!
  281. \brief Add new area to spatial index
  282. \param Plus pointer to Plus_head structure
  283. \param area area id
  284. \param box bounding box
  285. \return 0
  286. */
  287. int dig_spidx_add_area(struct Plus_head *Plus, int area,
  288. const struct bound_box *box)
  289. {
  290. static struct RTree_Rect rect;
  291. static int rect_init = 0;
  292. if (!rect_init) {
  293. /* always 6 sides for 3D */
  294. rect.boundary = G_malloc(6 * sizeof(RectReal));
  295. rect_init = 6;
  296. }
  297. G_debug(3, "dig_spidx_add_area(): area = %d", area);
  298. rect.boundary[0] = box->W;
  299. rect.boundary[1] = box->S;
  300. rect.boundary[2] = box->B;
  301. rect.boundary[3] = box->E;
  302. rect.boundary[4] = box->N;
  303. rect.boundary[5] = box->T;
  304. RTreeInsertRect(&rect, area, Plus->Area_spidx);
  305. return 0;
  306. }
  307. /*!
  308. \brief Add new island to spatial index
  309. \param Plus pointer to Plus_head structure
  310. \param isle isle id
  311. \param box bounding box
  312. \return 0
  313. */
  314. int dig_spidx_add_isle(struct Plus_head *Plus, int isle,
  315. const struct bound_box *box)
  316. {
  317. static struct RTree_Rect rect;
  318. static int rect_init = 0;
  319. if (!rect_init) {
  320. /* always 6 sides for 3D */
  321. rect.boundary = G_malloc(6 * sizeof(RectReal));
  322. rect_init = 6;
  323. }
  324. G_debug(3, "dig_spidx_add_isle(): isle = %d", isle);
  325. rect.boundary[0] = box->W;
  326. rect.boundary[1] = box->S;
  327. rect.boundary[2] = box->B;
  328. rect.boundary[3] = box->E;
  329. rect.boundary[4] = box->N;
  330. rect.boundary[5] = box->T;
  331. RTreeInsertRect(&rect, isle, Plus->Isle_spidx);
  332. return 0;
  333. }
  334. /*!
  335. \brief Delete node from spatial index
  336. G_fatal_error() called on error.
  337. \param Plus pointer to Plus_head structure
  338. \param node node id
  339. \return 0
  340. */
  341. int dig_spidx_del_node(struct Plus_head *Plus, int node)
  342. {
  343. int ret;
  344. struct P_node *Node;
  345. static struct RTree_Rect rect;
  346. static int rect_init = 0;
  347. if (!rect_init) {
  348. /* always 6 sides for 3D */
  349. rect.boundary = G_malloc(6 * sizeof(RectReal));
  350. rect_init = 6;
  351. }
  352. G_debug(3, "dig_spidx_del_node(): node = %d", node);
  353. Node = Plus->Node[node];
  354. rect.boundary[0] = Node->x;
  355. rect.boundary[1] = Node->y;
  356. rect.boundary[2] = Node->z;
  357. rect.boundary[3] = Node->x;
  358. rect.boundary[4] = Node->y;
  359. rect.boundary[5] = Node->z;
  360. ret = RTreeDeleteRect(&rect, node, Plus->Node_spidx);
  361. if (ret)
  362. G_fatal_error(_("Unable to delete node %d from spatial index"), node);
  363. return 0;
  364. }
  365. /*!
  366. \brief Delete line from spatial index
  367. G_fatal_error() called on error.
  368. \param Plus pointer to Plus_head structure
  369. \param line line id
  370. \param x,y,z coordinates
  371. \return 0
  372. */
  373. int dig_spidx_del_line(struct Plus_head *Plus, int line,
  374. double x, double y, double z)
  375. {
  376. int ret;
  377. static struct RTree_Rect rect;
  378. static int rect_init = 0;
  379. if (!rect_init) {
  380. /* always 6 sides for 3D */
  381. rect.boundary = G_malloc(6 * sizeof(RectReal));
  382. rect_init = 6;
  383. }
  384. G_debug(3, "dig_spidx_del_line(): line = %d", line);
  385. rect.boundary[0] = x;
  386. rect.boundary[1] = y;
  387. rect.boundary[2] = z;
  388. rect.boundary[3] = x;
  389. rect.boundary[4] = y;
  390. rect.boundary[5] = z;
  391. ret = RTreeDeleteRect(&rect, line, Plus->Line_spidx);
  392. G_debug(3, " ret = %d", ret);
  393. if (ret)
  394. G_fatal_error(_("Unable to delete line %d from spatial index"), line);
  395. return 0;
  396. }
  397. /*!
  398. \brief Delete area from spatial index
  399. G_fatal_error() called on error.
  400. \param Plus pointer to Plus_head structure
  401. \param area area id
  402. \return 0
  403. */
  404. int dig_spidx_del_area(struct Plus_head *Plus, int area)
  405. {
  406. int ret;
  407. struct P_area *Area;
  408. struct P_line *Line;
  409. struct P_node *Node;
  410. struct P_topo_b *topo;
  411. static struct RTree_Rect rect;
  412. static int rect_init = 0;
  413. if (!rect_init) {
  414. /* always 6 sides for 3D */
  415. rect.boundary = G_malloc(6 * sizeof(RectReal));
  416. rect_init = 6;
  417. }
  418. G_debug(3, "dig_spidx_del_area(): area = %d", area);
  419. Area = Plus->Area[area];
  420. if (Area == NULL) {
  421. G_fatal_error(_("Attempt to delete sidx for dead area"));
  422. }
  423. Line = Plus->Line[abs(Area->lines[0])];
  424. topo = (struct P_topo_b *)Line->topo;
  425. Node = Plus->Node[topo->N1];
  426. rect.boundary[0] = Node->x;
  427. rect.boundary[1] = Node->y;
  428. rect.boundary[2] = Node->z;
  429. rect.boundary[3] = Node->x;
  430. rect.boundary[4] = Node->y;
  431. rect.boundary[5] = Node->z;
  432. ret = RTreeDeleteRect(&rect, area, Plus->Area_spidx);
  433. if (ret)
  434. G_fatal_error(_("Unable to delete area %d from spatial index"), area);
  435. return 0;
  436. }
  437. /*!
  438. \brief Delete isle from spatial index
  439. G_fatal_error() called on error.
  440. \param Plus pointer to Plus_head structure
  441. \param isle isle id
  442. \return 0
  443. */
  444. int dig_spidx_del_isle(struct Plus_head *Plus, int isle)
  445. {
  446. int ret;
  447. struct P_isle *Isle;
  448. struct P_line *Line;
  449. struct P_node *Node;
  450. struct P_topo_b *topo;
  451. static struct RTree_Rect rect;
  452. static int rect_init = 0;
  453. if (!rect_init) {
  454. /* always 6 sides for 3D */
  455. rect.boundary = G_malloc(6 * sizeof(RectReal));
  456. rect_init = 6;
  457. }
  458. G_debug(3, "dig_spidx_del_isle(): isle = %d", isle);
  459. Isle = Plus->Isle[isle];
  460. Line = Plus->Line[abs(Isle->lines[0])];
  461. topo = (struct P_topo_b *)Line->topo;
  462. Node = Plus->Node[topo->N1];
  463. rect.boundary[0] = Node->x;
  464. rect.boundary[1] = Node->y;
  465. rect.boundary[2] = Node->z;
  466. rect.boundary[3] = Node->x;
  467. rect.boundary[4] = Node->y;
  468. rect.boundary[5] = Node->z;
  469. ret = RTreeDeleteRect(&rect, isle, Plus->Isle_spidx);
  470. if (ret)
  471. G_fatal_error(_("Unable to delete isle %d from spatial index"), isle);
  472. return 0;
  473. }
  474. /* This function is called by RTreeSearch() to add selected node/line/area/isle to the list */
  475. static int _add_item(int id, const struct RTree_Rect *rect,
  476. struct ilist *list)
  477. {
  478. G_ilist_add(list, id);
  479. return 1;
  480. }
  481. /* This function is called by RTreeSearch() to add
  482. * selected node/line/area/isle to the box list */
  483. static int _add_item_with_box(int id, const struct RTree_Rect *rect,
  484. struct boxlist *list)
  485. {
  486. struct bound_box box;
  487. box.W = rect->boundary[0];
  488. box.S = rect->boundary[1];
  489. box.B = rect->boundary[2];
  490. box.E = rect->boundary[3];
  491. box.N = rect->boundary[4];
  492. box.T = rect->boundary[5];
  493. dig_boxlist_add(list, id, &box);
  494. return 1;
  495. }
  496. struct boxid
  497. {
  498. int id;
  499. struct bound_box *box;
  500. };
  501. /* This function is called by RTreeSearch() to add
  502. * selected node/line/area/isle to the box list */
  503. static int _set_item_box(int id, const struct RTree_Rect *rect,
  504. struct boxid *box_id)
  505. {
  506. if (id == box_id->id) {
  507. box_id->box->W = rect->boundary[0];
  508. box_id->box->S = rect->boundary[1];
  509. box_id->box->B = rect->boundary[2];
  510. box_id->box->E = rect->boundary[3];
  511. box_id->box->N = rect->boundary[4];
  512. box_id->box->T = rect->boundary[5];
  513. return 0;
  514. }
  515. return 1;
  516. }
  517. /*!
  518. \brief Select nodes by bbox
  519. \param Plus pointer to Plus_head structure
  520. \param box bounding box
  521. \param list list of selected lines
  522. \return number of selected nodes
  523. \return -1 on error
  524. */
  525. int
  526. dig_select_nodes(struct Plus_head *Plus, const struct bound_box * box,
  527. struct ilist *list)
  528. {
  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_select_nodes()");
  537. list->n_values = 0;
  538. rect.boundary[0] = box->W;
  539. rect.boundary[1] = box->S;
  540. rect.boundary[2] = box->B;
  541. rect.boundary[3] = box->E;
  542. rect.boundary[4] = box->N;
  543. rect.boundary[5] = box->T;
  544. if (Plus->Spidx_new)
  545. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_item, list);
  546. else
  547. rtree_search(Plus->Node_spidx, &rect, (void *)_add_item, list, Plus);
  548. return (list->n_values);
  549. }
  550. /* This function is called by RTreeSearch() for nodes to find the node id */
  551. static int _add_node(int id, const struct RTree_Rect *rect, int *node)
  552. {
  553. *node = id;
  554. return 0;
  555. }
  556. /*!
  557. \brief Find one node by coordinates
  558. \param Plus pointer to Plus_head structure
  559. \param x,y,z coordinates
  560. \return number of node
  561. \return 0 not found
  562. */
  563. int dig_find_node(struct Plus_head *Plus, double x, double y, double z)
  564. {
  565. int node;
  566. static struct RTree_Rect rect;
  567. static int rect_init = 0;
  568. if (!rect_init) {
  569. /* always 6 sides for 3D */
  570. rect.boundary = G_malloc(6 * sizeof(RectReal));
  571. rect_init = 6;
  572. }
  573. G_debug(3, "dig_find_node()");
  574. rect.boundary[0] = x;
  575. rect.boundary[1] = y;
  576. rect.boundary[2] = z;
  577. rect.boundary[3] = x;
  578. rect.boundary[4] = y;
  579. rect.boundary[5] = z;
  580. node = 0;
  581. if (Plus->Spidx_new)
  582. RTreeSearch(Plus->Node_spidx, &rect, (void *)_add_node, &node);
  583. else
  584. rtree_search(Plus->Node_spidx, &rect, (void *)_add_node, &node, Plus);
  585. return node;
  586. }
  587. /*!
  588. \brief Select lines with boxes by box
  589. \param Plus pointer to Plus_head structure
  590. \param box bounding box
  591. \param list boxlist of selected lines
  592. \return number of selected lines
  593. \return 0 not found
  594. */
  595. int dig_select_lines(struct Plus_head *Plus, const struct bound_box *box,
  596. struct boxlist *list)
  597. {
  598. static struct RTree_Rect rect;
  599. static int rect_init = 0;
  600. if (!rect_init) {
  601. /* always 6 sides for 3D */
  602. rect.boundary = G_malloc(6 * sizeof(RectReal));
  603. rect_init = 6;
  604. }
  605. G_debug(3, "dig_select_lines_with_box()");
  606. list->n_values = 0;
  607. rect.boundary[0] = box->W;
  608. rect.boundary[1] = box->S;
  609. rect.boundary[2] = box->B;
  610. rect.boundary[3] = box->E;
  611. rect.boundary[4] = box->N;
  612. rect.boundary[5] = box->T;
  613. if (Plus->Spidx_new)
  614. RTreeSearch(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list);
  615. else
  616. rtree_search(Plus->Line_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  617. return (list->n_values);
  618. }
  619. /*!
  620. \brief Find box for line
  621. \param Plus pointer to Plus_head structure
  622. \param line line id
  623. \param[out] box bounding box
  624. \return > 0 bounding box for line found
  625. \return 0 not found
  626. */
  627. int dig_find_line_box(struct Plus_head *Plus, int line,
  628. struct bound_box *box)
  629. {
  630. int ret, type;
  631. struct P_line *Line;
  632. struct boxid box_id;
  633. static struct RTree_Rect rect;
  634. static int rect_init = 0;
  635. G_debug(3, "dig_find_line_box()");
  636. if (!rect_init) {
  637. /* always 6 sides for 3D */
  638. rect.boundary = G_malloc(6 * sizeof(RectReal));
  639. rect_init = 6;
  640. }
  641. Line = Plus->Line[line];
  642. type = Line->type;
  643. /* GV_LINES: retrieve box from spatial index */
  644. if (type & GV_LINES) {
  645. struct P_node *Node = NULL;
  646. if (type == GV_LINE) {
  647. struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
  648. Node = Plus->Node[topo->N1];
  649. }
  650. else if (type == GV_BOUNDARY) {
  651. struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
  652. Node = Plus->Node[topo->N1];
  653. }
  654. rect.boundary[0] = Node->x;
  655. rect.boundary[1] = Node->y;
  656. rect.boundary[2] = Node->z;
  657. rect.boundary[3] = Node->x;
  658. rect.boundary[4] = Node->y;
  659. rect.boundary[5] = Node->z;
  660. box_id.id = line;
  661. box_id.box = box;
  662. if (Plus->Spidx_new)
  663. ret = RTreeSearch(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id);
  664. else
  665. ret = rtree_search(Plus->Line_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  666. return ret;
  667. }
  668. /* do not translate this error because
  669. * 1. this error is not supposed to happen
  670. * 2. the maintainer at which this message is directed prefers english */
  671. G_fatal_error("Bug in vector lib: dig_find_line_box() may only be used for lines and boundaries.");
  672. return 0;
  673. }
  674. /*!
  675. \brief Select areas with boxes by box
  676. \param Plus pointer to Plus_head structure
  677. \param box bounding box
  678. \param list boxlist of selected areas
  679. \return number of selected areas
  680. */
  681. int
  682. dig_select_areas(struct Plus_head *Plus, const struct bound_box *box,
  683. struct boxlist *list)
  684. {
  685. static struct RTree_Rect rect;
  686. static int rect_init = 0;
  687. if (!rect_init) {
  688. /* always 6 sides for 3D */
  689. rect.boundary = G_malloc(6 * sizeof(RectReal));
  690. rect_init = 6;
  691. }
  692. G_debug(3, "dig_select_areas_with_box()");
  693. list->n_values = 0;
  694. rect.boundary[0] = box->W;
  695. rect.boundary[1] = box->S;
  696. rect.boundary[2] = box->B;
  697. rect.boundary[3] = box->E;
  698. rect.boundary[4] = box->N;
  699. rect.boundary[5] = box->T;
  700. if (Plus->Spidx_new)
  701. RTreeSearch(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list);
  702. else
  703. rtree_search(Plus->Area_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  704. return (list->n_values);
  705. }
  706. /*!
  707. \brief Find bounding box for given area
  708. \param Plus pointer to Plus_head structure
  709. \param area area id
  710. \param[out] box bounding box
  711. \return > 0 bounding box for area found
  712. \return 0 not found
  713. */
  714. int dig_find_area_box(struct Plus_head *Plus, int area,
  715. struct bound_box *box)
  716. {
  717. int ret;
  718. struct boxid box_id;
  719. struct P_area *Area;
  720. struct P_line *Line;
  721. struct P_node *Node;
  722. struct P_topo_b *topo;
  723. static struct RTree_Rect rect;
  724. static int rect_init = 0;
  725. G_debug(3, "dig_find_area_box()");
  726. if (!rect_init) {
  727. /* always 6 sides for 3D */
  728. rect.boundary = G_malloc(6 * sizeof(RectReal));
  729. rect_init = 6;
  730. }
  731. Area = Plus->Area[area];
  732. Line = Plus->Line[abs(Area->lines[0])];
  733. topo = (struct P_topo_b *)Line->topo;
  734. Node = Plus->Node[topo->N1];
  735. rect.boundary[0] = Node->x;
  736. rect.boundary[1] = Node->y;
  737. rect.boundary[2] = Node->z;
  738. rect.boundary[3] = Node->x;
  739. rect.boundary[4] = Node->y;
  740. rect.boundary[5] = Node->z;
  741. box_id.id = area;
  742. box_id.box = box;
  743. if (Plus->Spidx_new)
  744. ret = RTreeSearch(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id);
  745. else
  746. ret = rtree_search(Plus->Area_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  747. return ret;
  748. }
  749. /*!
  750. \brief Select isles with boxes by box
  751. \param Plus pointer to Plus_head structure
  752. \param box bounding box
  753. \param list boxlist of selected isles
  754. \return number of selected isles
  755. */
  756. int
  757. dig_select_isles(struct Plus_head *Plus, const struct bound_box * box,
  758. struct boxlist *list)
  759. {
  760. static struct RTree_Rect rect;
  761. static int rect_init = 0;
  762. if (!rect_init) {
  763. /* always 6 sides for 3D */
  764. rect.boundary = G_malloc(6 * sizeof(RectReal));
  765. rect_init = 6;
  766. }
  767. G_debug(3, "dig_select_areas_with_box()");
  768. list->n_values = 0;
  769. rect.boundary[0] = box->W;
  770. rect.boundary[1] = box->S;
  771. rect.boundary[2] = box->B;
  772. rect.boundary[3] = box->E;
  773. rect.boundary[4] = box->N;
  774. rect.boundary[5] = box->T;
  775. if (Plus->Spidx_new)
  776. RTreeSearch(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list);
  777. else
  778. rtree_search(Plus->Isle_spidx, &rect, (void *)_add_item_with_box, list, Plus);
  779. return (list->n_values);
  780. }
  781. /*!
  782. \brief Find box for isle
  783. \param Plus pointer to Plus_head structure
  784. \param isle isle id
  785. \param[out] box bounding box
  786. \return > 0 bounding box for isle found
  787. \return 0 not found
  788. */
  789. int dig_find_isle_box(struct Plus_head *Plus, int isle,
  790. struct bound_box *box)
  791. {
  792. int ret;
  793. struct boxid box_id;
  794. struct P_isle *Isle;
  795. struct P_line *Line;
  796. struct P_node *Node;
  797. struct P_topo_b *topo;
  798. static struct RTree_Rect rect;
  799. static int rect_init = 0;
  800. G_debug(3, "dig_find_isle_box()");
  801. if (!rect_init) {
  802. /* always 6 sides for 3D */
  803. rect.boundary = G_malloc(6 * sizeof(RectReal));
  804. rect_init = 6;
  805. }
  806. Isle = Plus->Isle[isle];
  807. Line = Plus->Line[abs(Isle->lines[0])];
  808. topo = (struct P_topo_b *)Line->topo;
  809. Node = Plus->Node[topo->N1];
  810. rect.boundary[0] = Node->x;
  811. rect.boundary[1] = Node->y;
  812. rect.boundary[2] = Node->z;
  813. rect.boundary[3] = Node->x;
  814. rect.boundary[4] = Node->y;
  815. rect.boundary[5] = Node->z;
  816. box_id.id = isle;
  817. box_id.box = box;
  818. if (Plus->Spidx_new)
  819. ret = RTreeSearch(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id);
  820. else
  821. ret = rtree_search(Plus->Isle_spidx, &rect, (void *)_set_item_box, &box_id, Plus);
  822. return ret;
  823. }