spindex_rw.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /*!
  2. \file diglib/spindex.c
  3. \brief Vector library - spatial index - read/write (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 <grass/config.h>
  13. #include <sys/types.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <assert.h>
  17. #include <grass/gis.h>
  18. #include <grass/vector.h>
  19. #include <grass/glocale.h>
  20. struct FBranch /* branch for file based index */
  21. {
  22. struct Rect rect;
  23. off_t child; /* position of child node in file */
  24. };
  25. struct FNode /* node for file based index */
  26. {
  27. int count; /* number of branches */
  28. int level; /* 0 is leaf, others positive */
  29. struct FBranch branch[MAXCARD];
  30. };
  31. /*!
  32. \brief Write spatial index header to file
  33. \param[in,out] fp pointer to struct gvfile
  34. \param ptr pointer to Plus_head structure
  35. \return 0 on success
  36. \return -1 on error
  37. */
  38. int dig_Wr_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
  39. {
  40. unsigned char buf[6];
  41. long length = 81; /* header length in bytes */
  42. struct RTree *t;
  43. size_t size;
  44. dig_rewind(fp);
  45. dig_set_cur_port(&(ptr->spidx_port));
  46. /* use ptr->off_t_size = 4 if possible */
  47. if (sizeof(off_t) > 4) {
  48. size = ptr->Node_spidx->n_nodes * ptr->Node_spidx->nodesize;
  49. size += ptr->Line_spidx->n_nodes * ptr->Line_spidx->nodesize;
  50. size += ptr->Area_spidx->n_nodes * ptr->Area_spidx->nodesize;
  51. size += ptr->Isle_spidx->n_nodes * ptr->Isle_spidx->nodesize;
  52. if (size < PORT_INT_MAX)
  53. ptr->spidx_port.off_t_size = 4;
  54. else
  55. ptr->spidx_port.off_t_size = 8;
  56. }
  57. else
  58. ptr->spidx_port.off_t_size = 4;
  59. /* bytes 1 - 6 */
  60. buf[0] = GV_SIDX_VER_MAJOR;
  61. buf[1] = GV_SIDX_VER_MINOR;
  62. buf[2] = GV_SIDX_EARLIEST_MAJOR;
  63. buf[3] = GV_SIDX_EARLIEST_MINOR;
  64. buf[4] = ptr->spidx_port.byte_order;
  65. buf[5] = (unsigned char)ptr->spidx_port.off_t_size;
  66. if (0 >= dig__fwrite_port_C((const char *)buf, 6, fp))
  67. return (-1);
  68. /* adjust header size for large files */
  69. if (ptr->spidx_port.off_t_size == 4) {
  70. if (ptr->off_t_size == 4)
  71. length = 113;
  72. else if (ptr->off_t_size == 8)
  73. length = 117;
  74. else
  75. G_fatal_error("topo must be written before sidx");
  76. }
  77. else if (ptr->spidx_port.off_t_size == 8) {
  78. if (ptr->off_t_size == 4)
  79. length = 141;
  80. else if (ptr->off_t_size == 8)
  81. length = 145;
  82. else
  83. G_fatal_error("topo must be written before sidx");
  84. }
  85. /* bytes 7 - 10 : header size */
  86. if (0 >= dig__fwrite_port_L(&length, 1, fp))
  87. return (0);
  88. ptr->spidx_head_size = length;
  89. /* byte 11 : dimension 2D or 3D */
  90. buf[0] = ptr->spidx_with_z;
  91. if (0 >= dig__fwrite_port_C((const char *)buf, 1, fp))
  92. return (-1);
  93. /* identical for all spatial indices: */
  94. t = ptr->Node_spidx;
  95. /* byte 12 : n dimensions */
  96. if (0 >= dig__fwrite_port_C(&(t->ndims), 1, fp))
  97. return (-1);
  98. /* byte 13 : n sides */
  99. if (0 >= dig__fwrite_port_C(&(t->nsides), 1, fp))
  100. return (-1);
  101. /* bytes 14 - 17 : nodesize */
  102. if (0 >= dig__fwrite_port_I(&(t->nodesize), 1, fp))
  103. return (-1);
  104. /* bytes 18 - 21 : nodecard */
  105. if (0 >= dig__fwrite_port_I(&(t->nodecard), 1, fp))
  106. return (-1);
  107. /* bytes 22 - 25 : leafcard */
  108. if (0 >= dig__fwrite_port_I(&(t->leafcard), 1, fp))
  109. return (-1);
  110. /* bytes 26 - 29 : min node fill */
  111. if (0 >= dig__fwrite_port_I(&(t->min_node_fill), 1, fp))
  112. return (-1);
  113. /* bytes 30 - 33 : min leaf fill */
  114. if (0 >= dig__fwrite_port_I(&(t->min_leaf_fill), 1, fp))
  115. return (-1);
  116. /* for each spatial index : */
  117. /* Node spatial index */
  118. /* bytes 34 - 37 : n nodes */
  119. if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
  120. return (-1);
  121. /* bytes 38 - 41 : n leafs */
  122. if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
  123. return (-1);
  124. /* bytes 42 - 45 : n levels */
  125. if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
  126. return (-1);
  127. /* bytes 46 - 49 (LFS 53) : root node offset */
  128. if (0 >=
  129. dig__fwrite_port_O(&(ptr->Node_spidx_offset), 1, fp,
  130. ptr->spidx_port.off_t_size))
  131. return (-1);
  132. /* Line spatial index */
  133. t = ptr->Line_spidx;
  134. /* bytes 50 - 53 (LFS 54 - 57) : n nodes */
  135. if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
  136. return (-1);
  137. /* bytes 54 - 57 (LFS 58 - 61) : n leafs */
  138. if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
  139. return (-1);
  140. /* bytes 58 - 61 (LFS 62 - 65) : n levels */
  141. if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
  142. return (-1);
  143. /* bytes 62 - 65 (LFS 66 - 73) : root node offset */
  144. if (0 >=
  145. dig__fwrite_port_O(&(ptr->Line_spidx_offset), 1, fp,
  146. ptr->spidx_port.off_t_size))
  147. return (-1);
  148. /* Area spatial index */
  149. t = ptr->Area_spidx;
  150. /* bytes 66 - 69 (LFS 74 - 77) : n nodes */
  151. if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
  152. return (-1);
  153. /* bytes 70 - 73 (LFS 78 - 81) : n leafs */
  154. if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
  155. return (-1);
  156. /* bytes 74 - 77 (LFS 82 - 85) : n levels */
  157. if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
  158. return (-1);
  159. /* bytes 78 - 81 (LFS 86 - 93) : root node offset */
  160. if (0 >=
  161. dig__fwrite_port_O(&(ptr->Area_spidx_offset), 1, fp,
  162. ptr->spidx_port.off_t_size))
  163. return (-1);
  164. /* Isle spatial index */
  165. t = ptr->Isle_spidx;
  166. /* bytes 82 - 85 (LFS 94 - 97) : n nodes */
  167. if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
  168. return (-1);
  169. /* bytes 86 - 89 (LFS 98 - 101) : n leafs */
  170. if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
  171. return (-1);
  172. /* bytes 90 - 93 (LFS 102 - 105) : n levels */
  173. if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
  174. return (-1);
  175. /* bytes 94 - 97 (LFS 106 - 113) : root node offset */
  176. if (0 >=
  177. dig__fwrite_port_O(&(ptr->Isle_spidx_offset), 1, fp,
  178. ptr->spidx_port.off_t_size))
  179. return (-1);
  180. /* 3D future : */
  181. /* Face spatial index */
  182. /* bytes 98 - 101 (LFS 114 - 121) : root node offset */
  183. if (0 >=
  184. dig__fwrite_port_O(&(ptr->Face_spidx_offset), 1, fp,
  185. ptr->spidx_port.off_t_size))
  186. return (-1);
  187. /* ptr->Face_spidx->rootpos = ptr->Face_spidx_offset; */
  188. /* Volume spatial index */
  189. /* bytes 102 - 105 (LFS 122 - 129) : root node offset */
  190. if (0 >=
  191. dig__fwrite_port_O(&(ptr->Volume_spidx_offset), 1, fp,
  192. ptr->spidx_port.off_t_size))
  193. return (-1);
  194. /* ptr->Volume_spidx->rootpos = ptr->Volume_spidx_offset; */
  195. /* Hole spatial index */
  196. /* bytes 106 - 109 (LFS 130 - 137) : root node offset */
  197. if (0 >=
  198. dig__fwrite_port_O(&(ptr->Hole_spidx_offset), 1, fp,
  199. ptr->spidx_port.off_t_size))
  200. return (-1);
  201. /* ptr->Hole_spidx->rootpos = ptr->Hole_spidx_offset; */
  202. G_debug(3, "spidx offset node = %lu line = %lu, area = %lu isle = %lu",
  203. (long unsigned)ptr->Node_spidx_offset,
  204. (long unsigned)ptr->Line_spidx_offset,
  205. (long unsigned)ptr->Area_spidx_offset,
  206. (long unsigned)ptr->Isle_spidx_offset);
  207. /* coor file size : bytes 110 - 113 (117) (LFS: 138 - 141 (145)) */
  208. if (0 >= dig__fwrite_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
  209. return (-1);
  210. length = (long unsigned)dig_ftell(fp);
  211. G_debug(1, "spidx body offset %lu", length);
  212. if (ptr->spidx_head_size != length)
  213. G_fatal_error("wrong sidx head length %ld", ptr->spidx_head_size);
  214. return (0);
  215. }
  216. /*!
  217. \brief Read spatial index header from sidx file
  218. \param fp pointer to struct gvfile
  219. \param[in,out] ptr pointer to Plus_head structure
  220. \return 0 on success
  221. \return -1 on error
  222. */
  223. int dig_Rd_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
  224. {
  225. unsigned char buf[6];
  226. int byte_order;
  227. struct RTree *t;
  228. dig_rewind(fp);
  229. /* bytes 1 - 6 */
  230. if (0 >= dig__fread_port_C((char *)buf, 6, fp))
  231. return (-1);
  232. ptr->spidx_Version_Major = buf[0];
  233. ptr->spidx_Version_Minor = buf[1];
  234. ptr->spidx_Back_Major = buf[2];
  235. ptr->spidx_Back_Minor = buf[3];
  236. byte_order = buf[4];
  237. ptr->spidx_port.off_t_size = buf[5];
  238. G_debug(2,
  239. "Spidx header: file version %d.%d , supported from GRASS version %d.%d",
  240. ptr->spidx_Version_Major, ptr->spidx_Version_Minor,
  241. ptr->spidx_Back_Major, ptr->spidx_Back_Minor);
  242. G_debug(2, " byte order %d", byte_order);
  243. /* check version numbers */
  244. if (ptr->spidx_Version_Major > GV_SIDX_VER_MAJOR ||
  245. ptr->spidx_Version_Minor > GV_SIDX_VER_MINOR) {
  246. /* The file was created by GRASS library with higher version than this one */
  247. if (ptr->spidx_Back_Major > GV_SIDX_VER_MAJOR ||
  248. ptr->spidx_Back_Minor > GV_SIDX_VER_MINOR) {
  249. /* This version of GRASS lib is lower than the oldest which can read this format */
  250. G_fatal_error(_("Spatial index format version %d.%d is not "
  251. "supported by this release."
  252. " Try to rebuild topology or upgrade GRASS."),
  253. ptr->spidx_Version_Major, ptr->spidx_Version_Minor);
  254. return (-1);
  255. }
  256. G_warning(_("Your GRASS version does not fully support "
  257. "spatial index format %d.%d of the vector."
  258. " Consider to rebuild topology or upgrade GRASS."),
  259. ptr->spidx_Version_Major, ptr->spidx_Version_Minor);
  260. }
  261. if (ptr->spidx_Version_Major < GV_SIDX_VER_MAJOR ||
  262. (ptr->spidx_Version_Major == GV_SIDX_VER_MAJOR &&
  263. ptr->spidx_Version_Minor < GV_SIDX_VER_MINOR)) {
  264. /* The file was created by GRASS library with lower version than this one */
  265. G_fatal_error(_("Spatial index format version %d.%d is not "
  266. "supported by this release."
  267. " Please rebuild topology."),
  268. ptr->spidx_Version_Major, ptr->spidx_Version_Minor);
  269. return (-1);
  270. }
  271. /* can this library read the sidx file ? */
  272. if (ptr->spidx_port.off_t_size > (int)sizeof(off_t)) {
  273. G_fatal_error("Spatial index was written with LFS but this "
  274. "GRASS version does not support LFS. "
  275. "Please get a GRASS version with LFS support.");
  276. }
  277. dig_init_portable(&(ptr->spidx_port), byte_order);
  278. dig_set_cur_port(&(ptr->spidx_port));
  279. /* bytes 7 - 10 : header size */
  280. if (0 >= dig__fread_port_L(&(ptr->spidx_head_size), 1, fp))
  281. return (-1);
  282. G_debug(2, " header size %ld", ptr->spidx_head_size);
  283. /* byte 11 : dimension 2D or 3D */
  284. if (0 >= dig__fread_port_C((char *)buf, 1, fp))
  285. return (-1);
  286. ptr->spidx_with_z = buf[0];
  287. G_debug(2, " with_z %d", ptr->spidx_with_z);
  288. /* identical for all spatial indices: */
  289. t = ptr->Node_spidx;
  290. /* byte 12 : n dimensions */
  291. if (0 >= dig__fread_port_C(&(t->ndims), 1, fp))
  292. return (-1);
  293. ptr->Line_spidx->ndims = t->ndims;
  294. ptr->Area_spidx->ndims = t->ndims;
  295. ptr->Isle_spidx->ndims = t->ndims;
  296. /* byte 13 : n sides */
  297. if (0 >= dig__fread_port_C(&(t->nsides), 1, fp))
  298. return (-1);
  299. ptr->Line_spidx->nsides = t->nsides;
  300. ptr->Area_spidx->nsides = t->nsides;
  301. ptr->Isle_spidx->nsides = t->nsides;
  302. /* bytes 14 - 17 : nodesize */
  303. if (0 >= dig__fread_port_I(&(t->nodesize), 1, fp))
  304. return (-1);
  305. ptr->Line_spidx->nodesize = t->nodesize;
  306. ptr->Area_spidx->nodesize = t->nodesize;
  307. ptr->Isle_spidx->nodesize = t->nodesize;
  308. /* bytes 18 - 21 : nodecard */
  309. if (0 >= dig__fread_port_I(&(t->nodecard), 1, fp))
  310. return (-1);
  311. ptr->Line_spidx->nodecard = t->nodecard;
  312. ptr->Area_spidx->nodecard = t->nodecard;
  313. ptr->Isle_spidx->nodecard = t->nodecard;
  314. /* bytes 22 - 25 : leafcard */
  315. if (0 >= dig__fread_port_I(&(t->leafcard), 1, fp))
  316. return (-1);
  317. ptr->Line_spidx->leafcard = t->leafcard;
  318. ptr->Area_spidx->leafcard = t->leafcard;
  319. ptr->Isle_spidx->leafcard = t->leafcard;
  320. /* bytes 26 - 29 : min node fill */
  321. if (0 >= dig__fread_port_I(&(t->min_node_fill), 1, fp))
  322. return (-1);
  323. ptr->Line_spidx->min_node_fill = t->min_node_fill;
  324. ptr->Area_spidx->min_node_fill = t->min_node_fill;
  325. ptr->Isle_spidx->min_node_fill = t->min_node_fill;
  326. /* bytes 30 - 33 : min leaf fill */
  327. if (0 >= dig__fread_port_I(&(t->min_leaf_fill), 1, fp))
  328. return (-1);
  329. ptr->Line_spidx->min_leaf_fill = t->min_leaf_fill;
  330. ptr->Area_spidx->min_leaf_fill = t->min_leaf_fill;
  331. ptr->Isle_spidx->min_leaf_fill = t->min_leaf_fill;
  332. /* for each spatial index : */
  333. /* Node spatial index */
  334. /* bytes 34 - 37 : n nodes */
  335. if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
  336. return (-1);
  337. /* bytes 38 - 41 : n leafs */
  338. if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
  339. return (-1);
  340. /* bytes 42 - 45 : n levels */
  341. if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
  342. return (-1);
  343. /* bytes 46 - 49 (LFS 53) : root node offset */
  344. if (0 >=
  345. dig__fread_port_O(&(ptr->Node_spidx_offset), 1, fp,
  346. ptr->spidx_port.off_t_size))
  347. return (-1);
  348. t->rootpos = ptr->Node_spidx_offset;
  349. /* Line spatial index */
  350. t = ptr->Line_spidx;
  351. /* bytes 50 - 53 (LFS 54 - 57) : n nodes */
  352. if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
  353. return (-1);
  354. /* bytes 54 - 57 (LFS 58 - 61) : n leafs */
  355. if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
  356. return (-1);
  357. /* bytes 58 - 61 (LFS 62 - 65) : n levels */
  358. if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
  359. return (-1);
  360. /* bytes 62 - 65 (LFS 66 - 73) : root node offset */
  361. if (0 >=
  362. dig__fread_port_O(&(ptr->Line_spidx_offset), 1, fp,
  363. ptr->spidx_port.off_t_size))
  364. return (-1);
  365. ptr->Line_spidx->rootpos = ptr->Line_spidx_offset;
  366. /* Area spatial index */
  367. t = ptr->Area_spidx;
  368. /* bytes 66 - 69 (LFS 74 - 77) : n nodes */
  369. if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
  370. return (-1);
  371. /* bytes 70 - 73 (LFS 78 - 81) : n leafs */
  372. if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
  373. return (-1);
  374. /* bytes 74 - 77 (LFS 82 - 85) : n levels */
  375. if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
  376. return (-1);
  377. /* bytes 78 - 81 (LFS 86 - 93) : root node offset */
  378. if (0 >=
  379. dig__fread_port_O(&(ptr->Area_spidx_offset), 1, fp,
  380. ptr->spidx_port.off_t_size))
  381. return (-1);
  382. ptr->Area_spidx->rootpos = ptr->Area_spidx_offset;
  383. /* Isle spatial index */
  384. t = ptr->Isle_spidx;
  385. /* bytes 82 - 85 (LFS 94 - 97) : n nodes */
  386. if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
  387. return (-1);
  388. /* bytes 86 - 89 (LFS 98 - 101) : n leafs */
  389. if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
  390. return (-1);
  391. /* bytes 90 - 93 (LFS 102 - 105) : n levels */
  392. if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
  393. return (-1);
  394. /* bytes 94 - 97 (LFS 106 - 113) : root node offset */
  395. if (0 >=
  396. dig__fread_port_O(&(ptr->Isle_spidx_offset), 1, fp,
  397. ptr->spidx_port.off_t_size))
  398. return (-1);
  399. ptr->Isle_spidx->rootpos = ptr->Isle_spidx_offset;
  400. /* 3D future : */
  401. /* Face spatial index */
  402. /* bytes 98 - 101 (LFS 114 - 121) : root node offset */
  403. if (0 >=
  404. dig__fread_port_O(&(ptr->Face_spidx_offset), 1, fp,
  405. ptr->spidx_port.off_t_size))
  406. return (-1);
  407. /* ptr->Face_spidx->rootpos = ptr->Face_spidx_offset; */
  408. /* Volume spatial index */
  409. /* bytes 102 - 105 (LFS 122 - 129) : root node offset */
  410. if (0 >=
  411. dig__fread_port_O(&(ptr->Volume_spidx_offset), 1, fp,
  412. ptr->spidx_port.off_t_size))
  413. return (-1);
  414. /* ptr->Volume_spidx->rootpos = ptr->Volume_spidx_offset; */
  415. /* Hole spatial index */
  416. /* bytes 106 - 109 (LFS 130 - 137) : root node offset */
  417. if (0 >=
  418. dig__fread_port_O(&(ptr->Hole_spidx_offset), 1, fp,
  419. ptr->spidx_port.off_t_size))
  420. return (-1);
  421. /* ptr->Hole_spidx->rootpos = ptr->Hole_spidx_offset; */
  422. /* coor file size : bytes 110 - 113 (117) (LFS: 138 - 145) */
  423. if (0 >= dig__fread_port_O(&(ptr->coor_size), 1, fp, ptr->off_t_size))
  424. return (-1);
  425. G_debug(2, " coor size %lu", (long unsigned)ptr->coor_size);
  426. dig_fseek(fp, ptr->spidx_head_size, SEEK_SET);
  427. return (0);
  428. }
  429. static int rtree_dump_node(FILE *, struct Node *n, int);
  430. /*!
  431. \brief Dump R-tree branch to the file
  432. \param fp pointer to FILE
  433. \param b pointer to Branch structure
  434. \param with_z non-zero value for 3D vector data
  435. \param level level value
  436. \return 0
  437. */
  438. static int rtree_dump_branch(FILE * fp, struct Branch *b, int with_z,
  439. int level)
  440. {
  441. const struct Rect *r;
  442. r = &(b->rect);
  443. if (level == 0)
  444. fprintf(fp, " id = %d ", b->child.id);
  445. fprintf(fp, " %f %f %f %f %f %f\n", r->boundary[0], r->boundary[1],
  446. r->boundary[2], r->boundary[3], r->boundary[4], r->boundary[5]);
  447. if (level > 0) {
  448. rtree_dump_node(fp, b->child.ptr, with_z);
  449. }
  450. return 0;
  451. }
  452. /*!
  453. \brief Dump R-tree node to the file
  454. \param fp pointer to FILE
  455. \param n pointer to Node structure
  456. \param with_z non-zero value for 3D vector data
  457. \return 0
  458. */
  459. int rtree_dump_node(FILE * fp, struct Node *n, int with_z)
  460. {
  461. int i;
  462. /* recursive nearly-but-a-bit-messy depth-first pre-order traversal
  463. * potentially filling up memory */
  464. /* TODO: change to non-recursive depth-first post-order traversal */
  465. /* left for comparison with GRASS6.x */
  466. fprintf(fp, "Node level=%d count=%d\n", n->level, n->count);
  467. if (n->level > 0)
  468. for (i = 0; i < NODECARD; i++) {
  469. if (n->branch[i].child.ptr) {
  470. fprintf(fp, " Branch %d", i);
  471. rtree_dump_branch(fp, &n->branch[i], with_z, n->level);
  472. }
  473. }
  474. else
  475. for (i = 0; i < LEAFCARD; i++) {
  476. if (n->branch[i].child.id) {
  477. fprintf(fp, " Branch %d", i);
  478. rtree_dump_branch(fp, &n->branch[i], with_z, n->level);
  479. }
  480. }
  481. return 0;
  482. }
  483. /*
  484. * all following methods to transfer spatial indices (rtrees) are based
  485. * on the same idea
  486. * do a postorder depth-first non-recursive traversal of the rtree
  487. * a leaf node is transfered first
  488. * the root node is transfered last
  489. *
  490. * this applies to all four scenarios
  491. * - from intermediate file to sidx file
  492. * - from sidx file to intermediate file
  493. * - from memory to sidx file
  494. * - from sidx file to memory
  495. *
  496. * I could not think of one function that's good for all four scenarios,
  497. * but that doesn't mean there is none...
  498. *
  499. * maybe something like V2_read_line_array and Write_line_array
  500. * in Vlib/read.c and Vlib/write.c, at least for transferring from sidx
  501. * and transferrring to sidx?
  502. */
  503. /*!
  504. \brief Write RTree body from memory to sidx file
  505. Must be called when new or updated vector is closed
  506. \param[out] fp pointer to struct gvfile
  507. \param startpos offset to struct gvfile where to start writing out
  508. \param t pointer to RTree
  509. \param off_t_size size of off_t used to write struct gvfile
  510. \return -1 on error
  511. \return offset to root node on success
  512. */
  513. static off_t rtree_write_to_sidx(struct gvfile * fp, off_t startpos,
  514. struct RTree *t, int off_t_size)
  515. {
  516. off_t nextfreepos = startpos;
  517. int sidx_nodesize;
  518. struct Node *n;
  519. int i, j, writeout;
  520. struct spidxstack
  521. {
  522. off_t pos[MAXCARD]; /* file position of child node, object ID on level 0 */
  523. struct Node *sn; /* stack node */
  524. int branch_id; /* branch no to follow down */
  525. } s[50];
  526. int top = 0;
  527. /* should be foolproof */
  528. sidx_nodesize =
  529. (int)(2 * PORT_INT + MAXCARD * (off_t_size + NUMSIDES * PORT_DOUBLE));
  530. /* stack size of t->n_levels + 1 would be enough because of
  531. * depth-first post-order traversal:
  532. * only one node per level on stack at any given time */
  533. /* add root node position to stack */
  534. s[top].branch_id = i = 0;
  535. s[top].sn = t->root;
  536. /* depth-first postorder traversal
  537. * all children of a node are visitied and written out first
  538. * when a child is written out, its position in file is stored in pos[] for
  539. * the parent node and written out with the parent node */
  540. /* root node is written out last and its position returned */
  541. while (top >= 0) {
  542. n = s[top].sn;
  543. writeout = 1;
  544. /* this is an internal node in the RTree
  545. * all its children are processed first,
  546. * before it is written out to the sidx file */
  547. if (s[top].sn->level > 0) {
  548. for (i = s[top].branch_id; i < t->nodecard; i++) {
  549. s[top].pos[i] = 0;
  550. if (n->branch[i].child.ptr != NULL) {
  551. s[top++].branch_id = i + 1;
  552. s[top].sn = n->branch[i].child.ptr;
  553. s[top].branch_id = 0;
  554. writeout = 0;
  555. break;
  556. }
  557. }
  558. if (writeout) {
  559. /* nothing else found, ready to write out */
  560. s[top].branch_id = t->nodecard;
  561. }
  562. }
  563. if (writeout) {
  564. /* write node to sidx file */
  565. if (G_ftell(fp->file) != nextfreepos)
  566. G_fatal_error("write sidx: wrong node position in file");
  567. /* write with dig__fwrite_port_* fns */
  568. dig__fwrite_port_I(&(s[top].sn->count), 1, fp);
  569. dig__fwrite_port_I(&(s[top].sn->level), 1, fp);
  570. for (j = 0; j < MAXCARD; j++) {
  571. dig__fwrite_port_D(s[top].sn->branch[j].rect.boundary,
  572. NUMSIDES, fp);
  573. /* leaf node: vector object IDs are stored in child.id */
  574. if (s[top].sn->level == 0)
  575. s[top].pos[j] = (off_t) s[top].sn->branch[j].child.id;
  576. dig__fwrite_port_O(&(s[top].pos[j]), 1, fp, off_t_size);
  577. }
  578. top--;
  579. /* update corresponding child position of parent node
  580. * this node is only updated if its level is > 0, i.e.
  581. * this is an internal node
  582. * children of internal nodes do not have an ID, instead
  583. * they hold the position in file of the next nodes down the tree */
  584. if (top >= 0) {
  585. s[top].pos[s[top].branch_id - 1] = nextfreepos;
  586. nextfreepos += sidx_nodesize;
  587. }
  588. }
  589. }
  590. return nextfreepos;
  591. }
  592. /*!
  593. \brief Load RTree body from sidx file to memory
  594. Must be called when old vector is opened in update mode
  595. \param fp pointer to struct gvfile
  596. \param rootpos position of root node in file
  597. \param t pointer to RTree
  598. \param off_t_size size of off_t used to read struct gvfile
  599. \return pointer to root node on success
  600. */
  601. struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
  602. struct RTree *t, int off_t_size)
  603. {
  604. struct Node *newnode = NULL;
  605. int i, j, loadnode;
  606. struct spidxstack
  607. {
  608. off_t childpos[MAXCARD];
  609. off_t pos; /* file position of child node */
  610. struct Node sn; /* stack node */
  611. int branch_id; /* branch no to follow down */
  612. } s[50], *last;
  613. int top = 0;
  614. /* stack size of t->n_levels + 1 would be enough because of
  615. * depth-first postorder traversal:
  616. * only one node per level on stack at any given time */
  617. /* add root node position to stack */
  618. last = &(s[top]);
  619. G_fseek(fp->file, rootpos, SEEK_SET);
  620. /* read with dig__fread_port_* fns */
  621. dig__fread_port_I(&(s[top].sn.count), 1, fp);
  622. dig__fread_port_I(&(s[top].sn.level), 1, fp);
  623. for (j = 0; j < MAXCARD; j++) {
  624. dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES, fp);
  625. dig__fread_port_O(&(s[top].childpos[j]), 1, fp, off_t_size);
  626. /* leaf node: vector object IDs are stored in child.id */
  627. if (s[top].sn.level == 0) {
  628. if (s[top].childpos[j]) {
  629. s[top].sn.branch[j].child.id =
  630. (int)s[top].childpos[j];
  631. }
  632. else
  633. s[top].sn.branch[j].child.id = 0;
  634. }
  635. else {
  636. s[top].sn.branch[j].child.ptr = NULL;
  637. }
  638. }
  639. s[top].branch_id = i = 0;
  640. /* some sort of postorder traversal */
  641. /* root node is loaded last and returned */
  642. while (top >= 0) {
  643. last = &(s[top]);
  644. loadnode = 1;
  645. /* this is an internal node in the RTree
  646. * all its children are read first,
  647. * before it is transfered to the RTree in memory */
  648. if (s[top].sn.level > 0) {
  649. for (i = s[top].branch_id; i < t->nodecard; i++) {
  650. if (s[top].childpos[i] > 0) {
  651. s[top++].branch_id = i + 1;
  652. s[top].pos = last->childpos[i];
  653. G_fseek(fp->file, s[top].pos, SEEK_SET);
  654. /* read with dig__fread_port_* fns */
  655. dig__fread_port_I(&(s[top].sn.count), 1, fp);
  656. dig__fread_port_I(&(s[top].sn.level), 1, fp);
  657. for (j = 0; j < MAXCARD; j++) {
  658. dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
  659. NUMSIDES, fp);
  660. dig__fread_port_O(&(s[top].childpos[j]), 1, fp,
  661. off_t_size);
  662. /* leaf node
  663. * vector object IDs are stored in file as
  664. * off_t but always fit into an int, see dig_structs.h
  665. * vector object IDs are transfered to child.id */
  666. if (s[top].sn.level == 0) {
  667. if (s[top].childpos[j]) {
  668. s[top].sn.branch[j].child.id =
  669. (int)s[top].childpos[j];
  670. }
  671. else
  672. s[top].sn.branch[j].child.id = 0;
  673. }
  674. else {
  675. s[top].sn.branch[j].child.ptr = NULL;
  676. }
  677. }
  678. s[top].branch_id = 0;
  679. loadnode = 0;
  680. break;
  681. }
  682. else if (last->childpos[i] < 0)
  683. G_fatal_error("corrupt spatial index");
  684. }
  685. if (loadnode) {
  686. /* nothing else found, ready to load */
  687. s[top].branch_id = t->nodecard;
  688. }
  689. }
  690. if (loadnode) {
  691. /* ready to load node to memory */
  692. newnode = RTreeNewNode(t, s[top].sn.level);
  693. /* copy from stack node */
  694. newnode->level = s[top].sn.level;
  695. newnode->count = s[top].sn.count;
  696. for (j = 0; j < MAXCARD; j++) {
  697. newnode->branch[j].rect = s[top].sn.branch[j].rect;
  698. newnode->branch[j].child = s[top].sn.branch[j].child;
  699. }
  700. top--;
  701. /* update child of parent node
  702. * this node is only updated if its level is > 0, i.e.
  703. * this is an internal node
  704. * children of internal nodes do not have an ID, instead
  705. * they point to the next nodes down the tree */
  706. if (top >= 0) {
  707. s[top].sn.branch[s[top].branch_id - 1].child.ptr = newnode;
  708. }
  709. }
  710. }
  711. return newnode;
  712. }
  713. /*!
  714. \brief Write spatial index to file
  715. \param[out] fp pointer to struct gvfile
  716. \param Plus pointer to Plus_head structure
  717. \return 0
  718. */
  719. int dig_Wr_spidx(struct gvfile * fp, struct Plus_head *Plus)
  720. {
  721. G_debug(1, "dig_Wr_spidx()");
  722. dig_set_cur_port(&(Plus->spidx_port));
  723. dig_rewind(fp);
  724. dig_Wr_spidx_head(fp, Plus);
  725. /* Nodes */
  726. Plus->Node_spidx_offset =
  727. rtree_write_to_sidx(fp, dig_ftell(fp), Plus->Node_spidx,
  728. Plus->spidx_port.off_t_size);
  729. /* Lines */
  730. Plus->Line_spidx_offset =
  731. rtree_write_to_sidx(fp, dig_ftell(fp), Plus->Line_spidx,
  732. Plus->spidx_port.off_t_size);
  733. /* Areas */
  734. Plus->Area_spidx_offset =
  735. rtree_write_to_sidx(fp, dig_ftell(fp), Plus->Area_spidx,
  736. Plus->spidx_port.off_t_size);
  737. /* Isles */
  738. Plus->Isle_spidx_offset =
  739. rtree_write_to_sidx(fp, dig_ftell(fp), Plus->Isle_spidx,
  740. Plus->spidx_port.off_t_size);
  741. /* 3D future : */
  742. /* Faces */
  743. /* Volumes */
  744. /* Holes */
  745. dig_rewind(fp);
  746. dig_Wr_spidx_head(fp, Plus); /* rewrite with offsets */
  747. dig_fflush(fp);
  748. return 0;
  749. }
  750. /*!
  751. \brief Read spatial index from sidx file
  752. Only needed when old vector is opened in update mode
  753. \param fp pointer to struct gvfile
  754. \param[in,out] Plus pointer to Plus_head structure
  755. \return 0
  756. */
  757. int dig_Rd_spidx(struct gvfile * fp, struct Plus_head *Plus)
  758. {
  759. G_debug(1, "dig_read_spindx()");
  760. /* free old trees, init new trees */
  761. dig_spidx_free(Plus);
  762. dig_spidx_init(Plus);
  763. dig_rewind(fp);
  764. dig_Rd_spidx_head(fp, Plus);
  765. dig_set_cur_port(&(Plus->spidx_port));
  766. /* Nodes */
  767. Plus->Node_spidx->root =
  768. rtree_load_from_sidx(fp, Plus->Node_spidx_offset,
  769. Plus->Node_spidx, Plus->spidx_port.off_t_size);
  770. /* Lines */
  771. Plus->Line_spidx->root =
  772. rtree_load_from_sidx(fp, Plus->Line_spidx_offset,
  773. Plus->Line_spidx, Plus->spidx_port.off_t_size);
  774. /* Areas */
  775. Plus->Area_spidx->root =
  776. rtree_load_from_sidx(fp, Plus->Area_spidx_offset,
  777. Plus->Area_spidx, Plus->spidx_port.off_t_size);
  778. /* Isles */
  779. Plus->Isle_spidx->root =
  780. rtree_load_from_sidx(fp, Plus->Isle_spidx_offset,
  781. Plus->Isle_spidx, Plus->spidx_port.off_t_size);
  782. /* 3D future : */
  783. /* Faces */
  784. /* Volumes */
  785. /* Holes */
  786. return 0;
  787. }
  788. /*!
  789. \brief Dump spatial index
  790. \param[out] fp pointer to FILE
  791. \param Plus pointer to Plus_head structure
  792. \return 0
  793. */
  794. int dig_dump_spidx(FILE * fp, const struct Plus_head *Plus)
  795. {
  796. fprintf(fp, "Nodes\n");
  797. rtree_dump_node(fp, Plus->Node_spidx->root, Plus->with_z);
  798. fprintf(fp, "Lines\n");
  799. rtree_dump_node(fp, Plus->Line_spidx->root, Plus->with_z);
  800. fprintf(fp, "Areas\n");
  801. rtree_dump_node(fp, Plus->Area_spidx->root, Plus->with_z);
  802. fprintf(fp, "Isles\n");
  803. rtree_dump_node(fp, Plus->Isle_spidx->root, Plus->with_z);
  804. return 0;
  805. }
  806. /*!
  807. \brief Search spatial index file
  808. Can't use regular RTreeSearch() here because sidx must be read
  809. with dig__fread_port_*() functions
  810. \param t pointer to RTree
  811. \param r search rectangle
  812. \param shcb user-provided callback
  813. \param cbarg argument for shcb
  814. \param Plus pointer to Plus_head structure
  815. \return number of qualifying rectangles
  816. */
  817. int rtree_search(struct RTree *t, struct Rect *r, SearchHitCallback shcb,
  818. void *cbarg, struct Plus_head *Plus)
  819. {
  820. struct FNode *n;
  821. int hitCount = 0, found;
  822. int i, j;
  823. struct spidxstack
  824. {
  825. off_t pos; /* file position of stack node */
  826. struct FNode sn; /* stack node */
  827. int branch_id; /* branch no to follow down */
  828. } s[50];
  829. int top = 0;
  830. assert(r);
  831. assert(t);
  832. /* stack size of t->n_levels + 1 is enough because of depth first search */
  833. /* only one node per level on stack at any given time */
  834. dig_set_cur_port(&(Plus->spidx_port));
  835. /* add root node position to stack */
  836. dig_fseek(&(Plus->spidx_fp), t->rootpos, SEEK_SET);
  837. /* read with dig__fread_port_* fns */
  838. dig__fread_port_I(&(s[top].sn.count), 1, &(Plus->spidx_fp));
  839. dig__fread_port_I(&(s[top].sn.level), 1, &(Plus->spidx_fp));
  840. for (j = 0; j < MAXCARD; j++) {
  841. dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES,
  842. &(Plus->spidx_fp));
  843. dig__fread_port_O(&(s[top].sn.branch[j].child), 1, &(Plus->spidx_fp),
  844. Plus->spidx_port.off_t_size);
  845. }
  846. s[top].pos = t->rootpos;
  847. s[top].branch_id = i = 0;
  848. n = &(s[top].sn);
  849. while (top >= 0) {
  850. n = &(s[top].sn);
  851. if (s[top].sn.level > 0) { /* this is an internal node in the tree */
  852. found = 1;
  853. for (i = s[top].branch_id; i < t->nodecard; i++) {
  854. if (s[top].sn.branch[i].child &&
  855. RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
  856. s[top++].branch_id = i + 1;
  857. s[top].pos = n->branch[i].child;
  858. dig_fseek(&(Plus->spidx_fp), s[top].pos, SEEK_SET);
  859. /* read with dig__fread_port_* fns */
  860. dig__fread_port_I(&(s[top].sn.count), 1,
  861. &(Plus->spidx_fp));
  862. dig__fread_port_I(&(s[top].sn.level), 1,
  863. &(Plus->spidx_fp));
  864. for (j = 0; j < MAXCARD; j++) {
  865. dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
  866. NUMSIDES, &(Plus->spidx_fp));
  867. dig__fread_port_O(&(s[top].sn.branch[j].child), 1,
  868. &(Plus->spidx_fp),
  869. Plus->spidx_port.off_t_size);
  870. }
  871. s[top].branch_id = 0;
  872. found = 0;
  873. break;
  874. }
  875. }
  876. if (found) {
  877. /* nothing else found, go back up */
  878. s[top].branch_id = t->nodecard;
  879. top--;
  880. }
  881. }
  882. else { /* this is a leaf node */
  883. for (i = 0; i < t->leafcard; i++) {
  884. if (s[top].sn.branch[i].child &&
  885. RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
  886. hitCount++;
  887. if (shcb) { /* call the user-provided callback */
  888. if (!shcb((int)s[top].sn.branch[i].child, cbarg)) {
  889. /* callback wants to terminate search early */
  890. return hitCount;
  891. }
  892. }
  893. }
  894. }
  895. top--;
  896. }
  897. }
  898. return hitCount;
  899. }