write_sfa.c 8.9 KB

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