read_nat.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. /*!
  2. \file lib/vector/Vlib/read_nat.c
  3. \brief Vector library - reading features (native format)
  4. Higher level functions for reading/writing/manipulating vectors.
  5. (C) 2001-2009, 2011-2012 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 or Mike Higgins.
  9. \author Update to GRASS 5.7 by Radim Blazek and David D. Gray.
  10. \author Update to GRASS 7 by Martin Landa <landa.martin gmail.com>
  11. */
  12. #include <sys/types.h>
  13. #include <grass/vector.h>
  14. #include <grass/glocale.h>
  15. static int read_line_nat(struct Map_info *,
  16. struct line_pnts *, struct line_cats *, off_t);
  17. /*! \brief Read vector feature on non-topological level (level 1) -
  18. native format - internal use only
  19. This function implements random access for native format,
  20. constraints are ignored!
  21. \param Map pointer to Map_info struct
  22. \param[out] Points container used to store line points within
  23. (pointer to line_pnts struct)
  24. \param[out] Cats container used to store line categories within
  25. (pointer to line_cats struct)
  26. \param offset given offset
  27. \return feature type (GV_POINT, GV_LINE, ...)
  28. \return 0 dead line
  29. \return -2 nothing to read
  30. \return -1 on failure
  31. */
  32. int V1_read_line_nat(struct Map_info *Map,
  33. struct line_pnts *Points,
  34. struct line_cats *Cats, off_t offset)
  35. {
  36. return read_line_nat(Map, Points, Cats, offset);
  37. }
  38. /*! \brief Read next vector feature on non-topological level (level
  39. 1) - native format - internal use only.
  40. This function implements sequential access, constraints are
  41. reflected, see Vect_set_constraint_region(),
  42. Vect_set_constraint_type(), or Vect_set_constraint_field().
  43. Dead features are skipped.
  44. Vect_rewind() can be used to reset reading.
  45. \param Map pointer to Map_info struct
  46. \param[out] line_p container used to store line points within
  47. (pointer to line_pnts struct)
  48. \param[out] line_c container used to store line categories within
  49. (pointer to line_cats struct)
  50. \return feature type (GV_POINT, GV_LINE, ...)
  51. \return 0 dead line
  52. \return -2 nothing to read
  53. \return -1 on failure
  54. */
  55. int V1_read_next_line_nat(struct Map_info *Map,
  56. struct line_pnts *line_p, struct line_cats *line_c)
  57. {
  58. int itype;
  59. off_t offset;
  60. struct bound_box lbox, mbox;
  61. G_debug(3, "V1_read_next_line_nat()");
  62. if (Map->constraint.region_flag)
  63. Vect_get_constraint_box(Map, &mbox);
  64. while (TRUE) {
  65. offset = dig_ftell(&(Map->dig_fp));
  66. itype = read_line_nat(Map, line_p, line_c, offset);
  67. if (itype < 0)
  68. return itype; /* nothing to read or failure */
  69. if (itype == 0) /* skip dead line */
  70. continue;
  71. if (Map->constraint.type_flag) {
  72. /* skip feature by type */
  73. if (!(itype & Map->constraint.type))
  74. continue;
  75. }
  76. if (line_p && Map->constraint.region_flag) {
  77. /* skip feature by region */
  78. Vect_line_box(line_p, &lbox);
  79. if (!Vect_box_overlap(&lbox, &mbox))
  80. continue;
  81. }
  82. if (line_c && Map->constraint.field_flag) {
  83. /* skip feature by field */
  84. if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
  85. continue;
  86. }
  87. return itype;
  88. }
  89. return -1; /* NOTREACHED */
  90. }
  91. /*! \brief Read vector feature on topological level (level 2) -
  92. native format - internal use only
  93. This function implements random access for native format,
  94. constraints are ignored!
  95. Note: Topology must be built at level >= GV_BUILD_BASE
  96. \param Map pointer to Map_info struct
  97. \param[out] Points container used to store line points within (pointer to line_pnts struct)
  98. \param[out] Cats container used to store line categories within (pointer to line_cats struct)
  99. \param line feature id to read (starts at 1)
  100. \return feature type (GV_POINT, GV_LINE, ...)
  101. \return -2 nothing to read
  102. \return -1 on failure
  103. */
  104. int V2_read_line_nat(struct Map_info *Map,
  105. struct line_pnts *line_p, struct line_cats *line_c, int line)
  106. {
  107. struct P_line *Line;
  108. G_debug(3, "V2_read_line_nat(): line = %d", line);
  109. if (line < 1 || line > Map->plus.n_lines) {
  110. G_warning(_("Attempt to access feature with invalid id (%d)"), line);
  111. return -1;
  112. }
  113. Line = Map->plus.Line[line];
  114. if (Line == NULL) {
  115. G_warning(_("Attempt to access dead feature %d"), line);
  116. return -1;
  117. }
  118. return read_line_nat(Map, line_p, line_c, Line->offset);
  119. }
  120. /*! \brief Read next vector feature on topological level (level 2) -
  121. native format - internal use only.
  122. This function implements sequential access, constraints are
  123. reflected, see Vect_set_constraint_region(),
  124. Vect_set_constraint_type(), or Vect_set_constraint_field().
  125. Use Vect_rewind() to reset reading.
  126. Dead feature are skipped.
  127. \param Map pointer to Map_info struct
  128. \param[out] line_p container used to store line points within
  129. (pointer to line_pnts struct)
  130. \param[out] line_c container used to store line categories within
  131. (pointer to line_cats struct)
  132. \return feature type (GV_POINT, GV_LINE, ...)
  133. \return -2 nothing to read
  134. \return -1 on error
  135. */
  136. int V2_read_next_line_nat(struct Map_info *Map,
  137. struct line_pnts *line_p, struct line_cats *line_c)
  138. {
  139. int line, ret;
  140. struct P_line *Line;
  141. struct bound_box lbox, mbox;
  142. G_debug(3, "V2_read_next_line_nat()");
  143. if (Map->constraint.region_flag)
  144. Vect_get_constraint_box(Map, &mbox);
  145. while (TRUE) {
  146. line = Map->next_line;
  147. if (line > Map->plus.n_lines)
  148. return -2; /* nothing to read */
  149. Line = Map->plus.Line[line];
  150. if (Line == NULL) {
  151. /* skip dead line */
  152. Map->next_line++;
  153. continue;
  154. }
  155. if (Map->constraint.type_flag) {
  156. /* skip feature by type */
  157. if (!(Line->type & Map->constraint.type)) {
  158. Map->next_line++;
  159. continue;
  160. }
  161. }
  162. Map->next_line++;
  163. ret = read_line_nat(Map, line_p, line_c, Line->offset);
  164. if (ret < 0)
  165. return ret;
  166. if (line_p && Map->constraint.region_flag) {
  167. /* skip feature by bbox */
  168. Vect_line_box(line_p, &lbox);
  169. if (!Vect_box_overlap(&lbox, &mbox))
  170. continue;
  171. }
  172. if (line_c && Map->constraint.field_flag) {
  173. /* skip feature by field */
  174. if (Vect_cat_get(line_c, Map->constraint.field, NULL) == 0)
  175. continue;
  176. }
  177. return ret;
  178. }
  179. return -1; /* NOTREACHED */
  180. }
  181. /*!
  182. \brief Read line from coor file
  183. \param Map vector map layer
  184. \param[out] p container used to store line points within
  185. \param[out] c container used to store line categories within
  186. \param offset given offset
  187. \return line type ( > 0 )
  188. \return 0 dead line
  189. \return -1 out of memory
  190. \return -2 end of file
  191. */
  192. int read_line_nat(struct Map_info *Map,
  193. struct line_pnts *p, struct line_cats *c, off_t offset)
  194. {
  195. register int i, dead = 0;
  196. int n_points;
  197. off_t size;
  198. int n_cats, do_cats;
  199. int type;
  200. char rhead, nc;
  201. short field;
  202. G_debug(3, "Vect__Read_line_nat: offset = %lu", (unsigned long) offset);
  203. Map->head.last_offset = offset;
  204. /* reads must set in_head, but writes use default */
  205. dig_set_cur_port(&(Map->head.port));
  206. dig_fseek(&(Map->dig_fp), offset, 0);
  207. if (0 >= dig__fread_port_C(&rhead, 1, &(Map->dig_fp)))
  208. return (-2);
  209. if (!(rhead & 0x01)) /* dead line */
  210. dead = 1;
  211. if (rhead & 0x02) /* categories exists */
  212. do_cats = 1; /* do not return here let file offset moves forward to next */
  213. else /* line */
  214. do_cats = 0;
  215. rhead >>= 2;
  216. type = dig_type_from_store((int)rhead);
  217. G_debug(3, " type = %d, do_cats = %d dead = %d", type, do_cats, dead);
  218. if (c != NULL)
  219. c->n_cats = 0;
  220. if (do_cats) {
  221. if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
  222. if (0 >= dig__fread_port_I(&n_cats, 1, &(Map->dig_fp)))
  223. return (-2);
  224. }
  225. else { /* coor format 5.0 */
  226. if (0 >= dig__fread_port_C(&nc, 1, &(Map->dig_fp)))
  227. return (-2);
  228. n_cats = (int)nc;
  229. }
  230. G_debug(3, " n_cats = %d", n_cats);
  231. if (c != NULL) {
  232. c->n_cats = n_cats;
  233. if (n_cats > 0) {
  234. if (0 > dig_alloc_cats(c, (int)n_cats + 1))
  235. return -1;
  236. if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
  237. if (0 >=
  238. dig__fread_port_I(c->field, n_cats, &(Map->dig_fp)))
  239. return (-2);
  240. }
  241. else { /* coor format 5.0 */
  242. for (i = 0; i < n_cats; i++) {
  243. if (0 >= dig__fread_port_S(&field, 1, &(Map->dig_fp)))
  244. return (-2);
  245. c->field[i] = (int)field;
  246. }
  247. }
  248. if (0 >= dig__fread_port_I(c->cat, n_cats, &(Map->dig_fp)))
  249. return (-2);
  250. }
  251. }
  252. else {
  253. if (Map->head.coor_version.minor == 1) { /* coor format 5.1 */
  254. size = (off_t) (2 * PORT_INT) * n_cats;
  255. }
  256. else { /* coor format 5.0 */
  257. size = (off_t) (PORT_SHORT + PORT_INT) * n_cats;
  258. }
  259. dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
  260. }
  261. }
  262. if (type & GV_POINTS) {
  263. n_points = 1;
  264. }
  265. else {
  266. if (0 >= dig__fread_port_I(&n_points, 1, &(Map->dig_fp)))
  267. return (-2);
  268. }
  269. G_debug(3, " n_points = %d", n_points);
  270. if (p != NULL) {
  271. if (0 > dig_alloc_points(p, n_points + 1))
  272. return (-1);
  273. p->n_points = n_points;
  274. if (0 >= dig__fread_port_D(p->x, n_points, &(Map->dig_fp)))
  275. return (-2);
  276. if (0 >= dig__fread_port_D(p->y, n_points, &(Map->dig_fp)))
  277. return (-2);
  278. if (Map->head.with_z) {
  279. if (0 >= dig__fread_port_D(p->z, n_points, &(Map->dig_fp)))
  280. return (-2);
  281. }
  282. else {
  283. for (i = 0; i < n_points; i++)
  284. p->z[i] = 0.0;
  285. }
  286. }
  287. else {
  288. if (Map->head.with_z)
  289. size = (off_t) n_points * 3 * PORT_DOUBLE;
  290. else
  291. size = (off_t) n_points * 2 * PORT_DOUBLE;
  292. dig_fseek(&(Map->dig_fp), size, SEEK_CUR);
  293. }
  294. G_debug(3, " off = %lu", (unsigned long) dig_ftell(&(Map->dig_fp)));
  295. if (dead)
  296. return 0;
  297. return type;
  298. }