123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /*!
- \file lib/vector/Vlib/write_sfa.c
- \brief Vector library - write vector feature - simple feature access (level 2)
- Higher level functions for reading/writing/manipulating vectors.
- See write_ogr.c (OGR interface) and write_pg.c (PostGIS interface)
- for imlementation issues.
- \todo SFA version of V2__delete_area_cats_from_cidx_nat()
- \todo function to delete corresponding entry in fidx
- \todo SFA version of V2__add_area_cats_to_cidx_nat
- \todo SFA version of V2__add_line_to_topo_nat
- (C) 2011-2012 by Martin Landa, and the GRASS Development Team
- This program is free software under the GNU General Public License
- (>=v2). Read the file COPYING that comes with GRASS for details.
- \author Martin Landa <landa.martin gmail.com>
- */
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #include "local_proto.h"
- #ifdef HAVE_POSTGRES
- #include "pg_local_proto.h"
- #endif
- #if defined HAVE_OGR || defined HAVE_POSTGRES
- static void V2__add_line_to_topo_sfa(struct Map_info *, int, const struct line_pnts *,
- const struct line_cats *);
- #endif
- /*!
- \brief Writes feature on level 2 (OGR/PostGIS interface, pseudo-topological level)
- \param Map pointer to Map_info structure
- \param type feature type (see V1_write_line_ogr() for list of supported types)
- \param points pointer to line_pnts structure (feature geometry)
- \param cats pointer to line_cats structure (feature categories)
-
- \return feature index in offset array (related to pseudo-topology)
- \return -1 on error
- */
- off_t V2_write_line_sfa(struct Map_info *Map, int type,
- const struct line_pnts *points, const struct line_cats *cats)
- {
- #if defined HAVE_OGR || defined HAVE_POSTGRES
- int line;
- off_t offset;
- struct Plus_head *plus;
- struct bound_box box;
- struct Format_info_offset *offset_info;
-
- line = 0;
- plus = &(Map->plus);
-
- G_debug(3, "V2_write_line_sfa(): type = %d (format = %d)",
- type, Map->format);
-
- if (Map->format == GV_FORMAT_POSTGIS) {
- offset_info = &(Map->fInfo.pg.offset);
- offset = V1_write_line_pg(Map, type, points, cats);
- }
- else {
- offset_info = &(Map->fInfo.pg.offset);
- offset = V1_write_line_ogr(Map, type, points, cats);
- }
- if (offset < 0)
- return -1;
- if (!(plus->update_cidx)) {
- plus->cidx_up_to_date = FALSE; /* category index will be outdated */
- }
- /* Update topology */
- if (plus->built >= GV_BUILD_BASE) {
- dig_line_box(points, &box);
- line = dig_add_line(plus, type, points, &box, offset);
- G_debug(3, "\tline added to topo with line = %d", line);
- if (line == 1)
- Vect_box_copy(&(plus->box), &box);
- else
- Vect_box_extend(&(plus->box), &box);
- if (type == GV_BOUNDARY) {
- int ret, cline;
- long fid;
- double x, y;
-
- struct bound_box box;
- struct line_pnts *CPoints;
- /* add virtual centroid to pseudo-topology */
- ret = Vect_get_point_in_poly(points, &x, &y);
- if (ret == 0) {
- CPoints = Vect_new_line_struct();
- Vect_append_point(CPoints, x, y, 0.0);
-
- fid = offset_info->array[offset];
- dig_line_box(CPoints, &box);
- cline = dig_add_line(plus, GV_CENTROID,
- CPoints, &box, fid);
- G_debug(4, "\tCentroid: x = %f, y = %f, cat = %lu, line = %d",
- x, y, fid, cline);
- dig_cidx_add_cat(plus, 1, (int) fid,
- cline, GV_CENTROID);
-
- Vect_destroy_line_struct(CPoints);
- }
- else {
- G_warning(_("Unable to calculate centroid for area"));
- }
- }
- V2__add_line_to_topo_sfa(Map, line, points, cats);
- }
- G_debug(3, "updated lines : %d , updated nodes : %d", plus->uplist.n_uplines,
- plus->uplist.n_upnodes);
- /* returns int line, but is defined as off_t for compatibility with
- * Write_line_array in write.c */
- return line;
- #else
- G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
- return -1;
- #endif
- }
- /*!
- \brief Rewrites feature at the given offset on level 2 (OGR/PostGIS
- interface, pseudo-topological level)
- Note: Topology must be built at level >= GV_BUILD_BASE
- \param Map pointer to Map_info structure
- \param line feature id to be rewritten
- \param type feature type (see V1_write_line_ogr() for supported types)
- \param points pointer to line_pnts structure (feature geometry)
- \param cats pointer to line_cats structure feature categories
-
- \return feature index in offset array (related to pseudo-topology)
- \return -1 on error
- */
- off_t V2_rewrite_line_sfa(struct Map_info *Map, off_t line, int type,
- const struct line_pnts *points, const struct line_cats *cats)
- {
- G_debug(3, "V2_rewrite_line_sfa(): line=%d type=%d",
- (int)line, type);
- if (line < 1 || line > Map->plus.n_lines) {
- G_warning(_("Attempt to access feature with invalid id (%d)"), (int)line);
- return -1;
- }
- #if defined HAVE_OGR || defined HAVE_POSTGRES
- if (type != V2_read_line_sfa(Map, NULL, NULL, line)) {
- G_warning(_("Unable to rewrite feature (incompatible feature types)"));
- return -1;
- }
- if (V2_delete_line_sfa(Map, line) != 0)
- return -1;
- return V2_write_line_sfa(Map, type, points, cats);
- #else
- G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
- return -1;
- #endif
- }
- /*!
- \brief Deletes feature on level 2 (OGR/PostGIS interface)
- Note: Topology must be built at level >= GV_BUILD_BASE
-
- \todo Update fidx
-
- \param pointer to Map_info structure
- \param line feature id to be deleted
-
- \return 0 on success
- \return -1 on error
- */
- int V2_delete_line_sfa(struct Map_info *Map, off_t line)
- {
- #if defined HAVE_OGR || defined HAVE_POSTGRES
- int ret, i, type, first;
- struct P_line *Line;
- struct Plus_head *plus;
- static struct line_cats *Cats = NULL;
- static struct line_pnts *Points = NULL;
- G_debug(3, "V2_delete_line_sfa(): line = %d", (int)line);
- type = first = 0;
- Line = NULL;
- plus = &(Map->plus);
- if (line < 1 || line > Map->plus.n_lines) {
- G_warning(_("Attempt to access feature with invalid id (%d)"), (int)line);
- return -1;
- }
- if (!(plus->update_cidx)) {
- plus->cidx_up_to_date = FALSE; /* category index will be outdated */
- }
- if (plus->built >= GV_BUILD_BASE) {
- Line = Map->plus.Line[line];
- if (Line == NULL)
- G_fatal_error(_("Attempt to delete dead feature"));
- type = Line->type;
- }
- if (!Cats) {
- Cats = Vect_new_cats_struct();
- }
- if (!Points) {
- Points = Vect_new_line_struct();
- }
- type = V2_read_line_sfa(Map, Points, Cats, line);
- if (type < 0)
- return -1;
-
- /* Update category index */
- if (plus->update_cidx) {
- for (i = 0; i < Cats->n_cats; i++) {
- dig_cidx_del_cat(plus, Cats->field[i], Cats->cat[i], line, type);
- }
- }
- /* Update fidx */
- /* TODO */
-
- /* delete the line from coor */
- if (Map->format == GV_FORMAT_POSTGIS)
- ret = V1_delete_line_pg(Map, Line->offset);
- else
- ret = V1_delete_line_ogr(Map, Line->offset);
-
- if (ret == -1) {
- return ret;
- }
- /* Update topology */
- if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
- /* TODO */
- /* remove centroid together with boundary (is really an OGR polygon) */
- }
- /* Delete reference from area */
- if (plus->built >= GV_BUILD_CENTROIDS && type == GV_CENTROID) {
- /* for OGR mapsets, virtual centroid will be removed when
- * polygon is removed */
- }
- /* delete the line from topo */
- dig_del_line(plus, line, Points->x[0], Points->y[0], Points->z[0]);
- /* Rebuild areas/isles and attach centroids and isles */
- if (plus->built >= GV_BUILD_AREAS && type == GV_BOUNDARY) {
- /* maybe not needed VERIFY */
- }
- return ret;
- #else
- G_fatal_error(_("GRASS is not compiled with OGR/PostgreSQL support"));
- return -1;
- #endif
- }
- /*!
- \brief Writes area on topological level (Simple Features interface,
- internal use only)
- \param Map pointer to Map_info structure
- \param points feature geometry (exterior + interior rings)
- \param nparts number of parts including exterior ring
- \param cats feature categories
-
- \return feature offset
- \return -1 on error
- */
- off_t V2__write_area_sfa(struct Map_info *Map,
- const struct line_pnts **points, int nparts,
- const struct line_cats *cats)
- {
- if (Map->format == GV_FORMAT_OGR) {
- #ifdef HAVE_OGR
- return V2__write_area_ogr(Map, points, nparts, cats);
- #else
- G_fatal_error(_("GRASS is not compiled with OGR support"));
- return -1;
- #endif
- }
- else if (Map->format == GV_FORMAT_POSTGIS) {
- #ifdef HAVE_POSTGRES
- return V2__write_area_pg(Map, points, nparts, cats);
- #else
- G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
- return -1;
- #endif
- }
- else {
- G_warning(_("Unsupported vector map format (%d)"), Map->format);
- }
- return -1;
- }
- #if defined HAVE_OGR || defined HAVE_POSTGRES
- /*!
- \brief Add feature to topo file (internal use only)
- \param Map pointer to Map_info structure
- \param line feature id
- \param points pointer to line_pnts structure (feature geometry)
- \param cats pointer to line_cats structure (feature categories)
- */
- void V2__add_line_to_topo_sfa(struct Map_info *Map, int line,
- const struct line_pnts *points,
- const struct line_cats *cats)
- {
- int first, s, i;
- int type, area, side;
- struct Plus_head *plus;
- struct P_line *Line;
-
- struct bound_box box, abox;
-
- G_debug(3, "V2__add_line_to_topo_sfa(): line = %d npoints = %d", line,
- points->n_points);
- plus = &(Map->plus);
- Line = plus->Line[line];
- type = Line->type;
- if (plus->built >= GV_BUILD_AREAS &&
- type == GV_BOUNDARY) {
- struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
-
- if (topo->N1 != topo->N2) {
- G_warning(_("Boundary is not closed. Skipping."));
- return;
- }
-
- /* Build new areas/isles */
- for (s = 0; s < 2; s++) {
- side = (s == 0 ? GV_LEFT : GV_RIGHT);
- area = Vect_build_line_area(Map, line, side);
- if (area > 0) { /* area */
- Vect_get_area_box(Map, area, &box);
- if (first) {
- Vect_box_copy(&abox, &box);
- first = FALSE;
- }
- else
- Vect_box_extend(&abox, &box);
- }
- else if (area < 0) {
- /* isle -> must be attached -> add to abox */
- Vect_get_isle_box(Map, -area, &box);
- if (first) {
- Vect_box_copy(&abox, &box);
- first = FALSE;
- }
- else
- Vect_box_extend(&abox, &box);
- }
- G_debug(4, "Vect_build_line_area(): -> area = %d", area);
- }
- /* Attach centroid/isle to the new area */
- if (plus->built >= GV_BUILD_ATTACH_ISLES)
- Vect_attach_isles(Map, &abox);
- if (plus->built >= GV_BUILD_CENTROIDS)
- Vect_attach_centroids(Map, &abox);
- }
-
- /* Add category index */
- for (i = 0; i < cats->n_cats; i++) {
- dig_cidx_add_cat_sorted(plus, cats->field[i], cats->cat[i], line,
- type);
- }
-
- return;
- }
- #endif /* HAVE_OGR || HAVE_POSTGRES */
|