write_sfa.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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 Deletes feature (topology level) -- internal use only
  102. \todo Update fidx
  103. \param pointer to Map_info structure
  104. \param line feature id
  105. \return 0 on success
  106. \return -1 on error
  107. */
  108. int V2_delete_line_sfa(struct Map_info *Map, int line)
  109. {
  110. #if defined HAVE_OGR || defined HAVE_POSTGRES
  111. int ret, i, type, first;
  112. struct P_line *Line;
  113. struct Plus_head *plus;
  114. static struct line_cats *Cats = NULL;
  115. static struct line_pnts *Points = NULL;
  116. G_debug(3, "V2_delete_line_sfa(), line = %d", line);
  117. type = first = 0;
  118. Line = NULL;
  119. plus = &(Map->plus);
  120. if (plus->built >= GV_BUILD_BASE) {
  121. Line = Map->plus.Line[line];
  122. if (Line == NULL)
  123. G_fatal_error(_("Attempt to delete dead feature"));
  124. type = Line->type;
  125. }
  126. if (!Cats) {
  127. Cats = Vect_new_cats_struct();
  128. }
  129. if (!Points) {
  130. Points = Vect_new_line_struct();
  131. }
  132. type = V2_read_line_sfa(Map, Points, Cats, line);
  133. /* Update category index */
  134. if (plus->update_cidx) {
  135. for (i = 0; i < Cats->n_cats; i++) {
  136. dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
  137. }
  138. }
  139. /* Update fidx */
  140. /* TODO */
  141. /* delete the line from coor */
  142. if (Map->format == GV_FORMAT_POSTGIS)
  143. ret = V1_delete_line_pg(Map, Line->offset);
  144. else
  145. ret = V1_delete_line_ogr(Map, Line->offset);
  146. if (ret == -1) {
  147. return ret;
  148. }
  149. /* Update topology */
  150. if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
  151. /* TODO */
  152. /* remove centroid together with boundary (is really an OGR polygon) */
  153. }
  154. /* Delete reference from area */
  155. if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
  156. /* for OGR mapsets, virtual centroid will be removed when
  157. * polygon is removed */
  158. }
  159. /* delete the line from topo */
  160. dig_del_line(plus, line, Points->x[0], Points->y[0], Points->z[0]);
  161. /* Rebuild areas/isles and attach centroids and isles */
  162. if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
  163. /* maybe not needed VERIFY */
  164. }
  165. return ret;
  166. #else
  167. G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
  168. return -1;
  169. #endif
  170. }
  171. #if defined HAVE_OGR || defined HAVE_POSTGRES
  172. /*!
  173. \brief Add feature to topo file (internal use only)
  174. \param Map pointer to Map_info structure
  175. \param line feature id
  176. \param points pointer to line_pnts structure (feature's geometry)
  177. \param cats pointer to line_cats structure (feature's categories)
  178. */
  179. void V2__add_line_to_topo_sfa(struct Map_info *Map, int line,
  180. const struct line_pnts *points,
  181. const struct line_cats *cats)
  182. {
  183. int first, s, i;
  184. int type, area, side;
  185. struct Plus_head *plus;
  186. struct P_line *Line;
  187. struct bound_box box, abox;
  188. G_debug(3, "V2__add_line_to_topo_ogr(): line = %d npoints = %d", line,
  189. points->n_points);
  190. plus = &(Map->plus);
  191. Line = plus->Line[line];
  192. type = Line->type;
  193. if (plus->built >= GV_BUILD_AREAS &&
  194. type == GV_BOUNDARY) {
  195. struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
  196. if (topo->N1 != topo->N2) {
  197. G_warning(_("Boundary is not closed. Skipping."));
  198. return;
  199. }
  200. /* Build new areas/isles */
  201. for (s = 0; s < 2; s++) {
  202. side = (s == 0 ? GV_LEFT : GV_RIGHT);
  203. area = Vect_build_line_area(Map, line, side);
  204. if (area > 0) { /* area */
  205. Vect_get_area_box(Map, area, &box);
  206. if (first) {
  207. Vect_box_copy(&abox, &box);
  208. first = FALSE;
  209. }
  210. else
  211. Vect_box_extend(&abox, &box);
  212. }
  213. else if (area < 0) {
  214. /* isle -> must be attached -> add to abox */
  215. Vect_get_isle_box(Map, -area, &box);
  216. if (first) {
  217. Vect_box_copy(&abox, &box);
  218. first = FALSE;
  219. }
  220. else
  221. Vect_box_extend(&abox, &box);
  222. }
  223. G_debug(4, "Vect_build_line_area(): -> area = %d", area);
  224. }
  225. /* Attach centroid/isle to the new area */
  226. if (plus->built >= GV_BUILD_ATTACH_ISLES)
  227. Vect_attach_isles(Map, &abox);
  228. if (plus->built >= GV_BUILD_CENTROIDS)
  229. Vect_attach_centroids(Map, &abox);
  230. }
  231. /* Add category index */
  232. for (i = 0; i < cats->n_cats; i++) {
  233. dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
  234. type);
  235. }
  236. return;
  237. }
  238. #endif /* HAVE_OGR || HAVE_POSTGRES */