write_sfa.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  1. /*!
  2. \file lib/vector/Vlib/write_sfa.c
  3. \brief Vector library - write vector feature - simple feature access
  4. Higher level functions for reading/writing/manipulating vectors.
  5. See write_ogr.c (OGR interface) and write_pg.c (PostGIS interface)
  6. for imlementation issues.
  7. \todo SFA version of V2__delete_area_cats_from_cidx_nat()
  8. \todo function to delete corresponding entry in fidx
  9. \todo SFA version of V2__add_area_cats_to_cidx_nat
  10. \todo SFA version of V2__add_line_to_topo_nat
  11. (C) 2011-2012 by Martin Landa, and the GRASS Development Team
  12. This program is free software under the GNU General Public License
  13. (>=v2). Read the file COPYING that comes with GRASS for details.
  14. \author Martin Landa <landa.martin gmail.com>
  15. */
  16. #include <grass/vector.h>
  17. #include <grass/glocale.h>
  18. #if defined HAVE_OGR || defined HAVE_POSTGRES
  19. void V2__add_line_to_topo_sfa(struct Map_info *, int, const struct line_pnts *,
  20. const struct line_cats *);
  21. #endif
  22. /*!
  23. \brief Writes feature on level 2 (OGR/PostGIS interface)
  24. \param Map pointer to Map_info structure
  25. \param type feature type (GV_POINT, GV_LINE, ...)
  26. \param points pointer to line_pnts structure (feature geometry)
  27. \param cats pointer to line_cats structure (feature categories)
  28. \return feature offset into file
  29. \return -1 on error
  30. */
  31. off_t V2_write_line_sfa(struct Map_info *Map, int type,
  32. const struct line_pnts *points, const struct line_cats *cats)
  33. {
  34. #if defined HAVE_OGR || defined HAVE_POSTGRES
  35. int line;
  36. off_t offset;
  37. struct Plus_head *plus;
  38. struct bound_box box;
  39. struct Format_info_offset *offset_info;
  40. line = 0;
  41. plus = &(Map->plus);
  42. G_debug(3, "V2_write_line_sfa(): type = %d (format = %d)",
  43. type, Map->format);
  44. if (Map->format == GV_FORMAT_POSTGIS) {
  45. offset_info = &(Map->fInfo.pg.offset);
  46. offset = V1_write_line_pg(Map, type, points, cats);
  47. }
  48. else {
  49. offset_info = &(Map->fInfo.pg.offset);
  50. offset = V1_write_line_ogr(Map, type, points, cats);
  51. }
  52. if (offset < 0)
  53. return -1;
  54. /* Update topology */
  55. if (plus->built >= GV_BUILD_BASE) {
  56. dig_line_box(points, &box);
  57. line = dig_add_line(plus, type, points, &box, offset);
  58. G_debug(3, "\tline added to topo with line = %d", line);
  59. if (line == 1)
  60. Vect_box_copy(&(plus->box), &box);
  61. else
  62. Vect_box_extend(&(plus->box), &box);
  63. if (type == GV_BOUNDARY) {
  64. int ret, cline;
  65. long fid;
  66. double x, y;
  67. struct bound_box box;
  68. struct line_pnts *CPoints;
  69. /* add virtual centroid to pseudo-topology */
  70. ret = Vect_get_point_in_poly(points, &x, &y);
  71. if (ret == 0) {
  72. CPoints = Vect_new_line_struct();
  73. Vect_append_point(CPoints, x, y, 0.0);
  74. fid = offset_info->array[offset];
  75. dig_line_box(CPoints, &box);
  76. cline = dig_add_line(plus, GV_CENTROID,
  77. CPoints, &box, fid);
  78. G_debug(4, "\tCentroid: x = %f, y = %f, cat = %lu, line = %d",
  79. x, y, fid, cline);
  80. dig_cidx_add_cat(plus, 1, (int) fid,
  81. cline, GV_CENTROID);
  82. Vect_destroy_line_struct(CPoints);
  83. }
  84. else {
  85. G_warning(_("Unable to calculate centroid for area"));
  86. }
  87. }
  88. V2__add_line_to_topo_sfa(Map, line, points, cats);
  89. }
  90. G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
  91. plus->uplist.n_upnodes);
  92. /* returns int line, but is defined as off_t for compatibility with
  93. * Write_line_array in write.c */
  94. return line;
  95. #else
  96. G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
  97. return -1;
  98. #endif
  99. }
  100. /*!
  101. \brief Rewrites feature to 'coor' file (topology level) - internal use only
  102. \param Map pointer to Map_info structure
  103. \param line feature id
  104. \param type feature type (GV_POINT, GV_LINE, ...)
  105. \param offset unused
  106. \param points feature geometry
  107. \param cats feature categories
  108. \return offset where line was rewritten
  109. \return -1 on error
  110. */
  111. off_t V2_rewrite_line_sfa(struct Map_info *Map, int line, int type, off_t offset,
  112. const struct line_pnts *points, const struct line_cats *cats)
  113. {
  114. G_debug(3, "V2_rewrite_line_sfa(): line=%d type=%d offset=%llu",
  115. line, type, offset);
  116. #if defined HAVE_OGR || defined HAVE_POSTGRES
  117. if (type != V2_read_line_sfa(Map, NULL, NULL, line)) {
  118. G_warning(_("Unable to rewrite feature (incompatible feature types)"));
  119. return -1;
  120. }
  121. V2_delete_line_sfa(Map, line);
  122. return V2_write_line_sfa(Map, type, points, cats);
  123. #else
  124. G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
  125. return -1;
  126. #endif
  127. }
  128. /*!
  129. \brief Deletes feature (topology level) -- internal use only
  130. \todo Update fidx
  131. \param pointer to Map_info structure
  132. \param line feature id
  133. \return 0 on success
  134. \return -1 on error
  135. */
  136. int V2_delete_line_sfa(struct Map_info *Map, int line)
  137. {
  138. #if defined HAVE_OGR || defined HAVE_POSTGRES
  139. int ret, i, type, first;
  140. struct P_line *Line;
  141. struct Plus_head *plus;
  142. static struct line_cats *Cats = NULL;
  143. static struct line_pnts *Points = NULL;
  144. G_debug(3, "V2_delete_line_sfa(), line = %d", line);
  145. type = first = 0;
  146. Line = NULL;
  147. plus = &(Map->plus);
  148. if (plus->built >= GV_BUILD_BASE) {
  149. Line = Map->plus.Line[line];
  150. if (Line == NULL)
  151. G_fatal_error(_("Attempt to delete dead feature"));
  152. type = Line->type;
  153. }
  154. if (!Cats) {
  155. Cats = Vect_new_cats_struct();
  156. }
  157. if (!Points) {
  158. Points = Vect_new_line_struct();
  159. }
  160. type = V2_read_line_sfa(Map, Points, Cats, line);
  161. /* Update category index */
  162. if (plus->update_cidx) {
  163. for (i = 0; i < Cats->n_cats; i++) {
  164. dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
  165. }
  166. }
  167. /* Update fidx */
  168. /* TODO */
  169. /* delete the line from coor */
  170. if (Map->format == GV_FORMAT_POSTGIS)
  171. ret = V1_delete_line_pg(Map, Line->offset);
  172. else
  173. ret = V1_delete_line_ogr(Map, Line->offset);
  174. if (ret == -1) {
  175. return ret;
  176. }
  177. /* Update topology */
  178. if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
  179. /* TODO */
  180. /* remove centroid together with boundary (is really an OGR polygon) */
  181. }
  182. /* Delete reference from area */
  183. if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
  184. /* for OGR mapsets, virtual centroid will be removed when
  185. * polygon is removed */
  186. }
  187. /* delete the line from topo */
  188. dig_del_line(plus, line, Points->x[0], Points->y[0], Points->z[0]);
  189. /* Rebuild areas/isles and attach centroids and isles */
  190. if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
  191. /* maybe not needed VERIFY */
  192. }
  193. return ret;
  194. #else
  195. G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
  196. return -1;
  197. #endif
  198. }
  199. #if defined HAVE_OGR || defined HAVE_POSTGRES
  200. /*!
  201. \brief Add feature to topo file (internal use only)
  202. \param Map pointer to Map_info structure
  203. \param line feature id
  204. \param points pointer to line_pnts structure (feature's geometry)
  205. \param cats pointer to line_cats structure (feature's categories)
  206. */
  207. void V2__add_line_to_topo_sfa(struct Map_info *Map, int line,
  208. const struct line_pnts *points,
  209. const struct line_cats *cats)
  210. {
  211. int first, s, i;
  212. int type, area, side;
  213. struct Plus_head *plus;
  214. struct P_line *Line;
  215. struct bound_box box, abox;
  216. G_debug(3, "V2__add_line_to_topo_sfa(): line = %d npoints = %d", line,
  217. points->n_points);
  218. plus = &(Map->plus);
  219. Line = plus->Line[line];
  220. type = Line->type;
  221. if (plus->built >= GV_BUILD_AREAS &&
  222. type == GV_BOUNDARY) {
  223. struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
  224. if (topo->N1 != topo->N2) {
  225. G_warning(_("Boundary is not closed. Skipping."));
  226. return;
  227. }
  228. /* Build new areas/isles */
  229. for (s = 0; s < 2; s++) {
  230. side = (s == 0 ? GV_LEFT : GV_RIGHT);
  231. area = Vect_build_line_area(Map, line, side);
  232. if (area > 0) { /* area */
  233. Vect_get_area_box(Map, area, &box);
  234. if (first) {
  235. Vect_box_copy(&abox, &box);
  236. first = FALSE;
  237. }
  238. else
  239. Vect_box_extend(&abox, &box);
  240. }
  241. else if (area < 0) {
  242. /* isle -> must be attached -> add to abox */
  243. Vect_get_isle_box(Map, -area, &box);
  244. if (first) {
  245. Vect_box_copy(&abox, &box);
  246. first = FALSE;
  247. }
  248. else
  249. Vect_box_extend(&abox, &box);
  250. }
  251. G_debug(4, "Vect_build_line_area(): -> area = %d", area);
  252. }
  253. /* Attach centroid/isle to the new area */
  254. if (plus->built >= GV_BUILD_ATTACH_ISLES)
  255. Vect_attach_isles(Map, &abox);
  256. if (plus->built >= GV_BUILD_CENTROIDS)
  257. Vect_attach_centroids(Map, &abox);
  258. }
  259. /* Add category index */
  260. for (i = 0; i < cats->n_cats; i++) {
  261. dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
  262. type);
  263. }
  264. return;
  265. }
  266. #endif /* HAVE_OGR || HAVE_POSTGRES */