123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- /*!
- \file lib/vector/Vlib/area_pg.c
- \brief Vector library - area-related functions (PostGIS Topology)
- Higher level functions for reading/writing/manipulating vectors.
- (C) 2013 by 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>
- #ifdef HAVE_POSTGRES
- #include "pg_local_proto.h"
- static PGresult *build_stmt(const struct Plus_head *, const struct Format_info_pg *, const plus_t *, int);
- /*!
- \brief Get area boundary points (PostGIS Topology)
-
- Used by Vect_build_line_area() and Vect_get_area_points().
- \param Map pointer to Map_info struct
- \param lines array of boundary lines
- \param n_lines number of lines in array
- \param[out] APoints pointer to output line_pnts struct
- \return number of points
- \return -1 on error
- */
- int Vect__get_area_points_pg(const struct Map_info *Map, const plus_t *lines, int n_lines,
- struct line_pnts *APoints)
- {
- int i, direction;
-
- struct Format_info_pg *pg_info;
-
- PGresult *res;
-
- pg_info = (struct Format_info_pg *)&(Map->fInfo.pg);
-
- Vect_reset_line(APoints);
- res = build_stmt(&(Map->plus), pg_info, lines, n_lines);
- if (!res)
- return -1;
-
- for (i = 0; i < n_lines; i++) {
- Vect__cache_feature_pg(PQgetvalue(res, i, 0), FALSE, FALSE,
- &(pg_info->cache), NULL); /* do caching in readable way */
- direction = lines[i] > 0 ? GV_FORWARD : GV_BACKWARD;
- Vect_append_points(APoints, pg_info->cache.lines[0], direction);
- APoints->n_points--; /* skip last point, avoids duplicates */
- }
- APoints->n_points++; /* close polygon */
- PQclear(res);
-
- return APoints->n_points;
- }
- PGresult *build_stmt(const struct Plus_head *plus, const struct Format_info_pg *pg_info,
- const plus_t *lines, int n_lines)
- {
- int i, line;
- size_t stmt_id_size;
- char *stmt, *stmt_id, buf_id[128];
- struct P_line *BLine;
-
- PGresult *res;
-
- stmt = NULL;
- stmt_id_size = DB_SQL_MAX;
- stmt_id = (char *) G_malloc(stmt_id_size);
- stmt_id[0] = '\0';
- for (i = 0; i < n_lines; i++) {
- if (strlen(stmt_id) + 100 > stmt_id_size) {
- stmt_id_size = strlen(stmt_id) + DB_SQL_MAX;
- stmt_id = (char *) G_realloc(stmt_id, stmt_id_size);
- }
- line = abs(lines[i]);
- BLine = plus->Line[line];
- if (i > 0)
- strcat(stmt_id, ",");
- sprintf(buf_id, "%d", (int) BLine->offset);
- strcat(stmt_id, buf_id);
- }
- /* Not really working - why?
- G_asprintf(&stmt, "SELECT geom FROM \"%s\".edge_data WHERE edge_id IN (%s) "
- "ORDER BY POSITION(edge_id::text in '%s')", pg_info->toposchema_name,
- stmt_id, stmt_id);
- */
- G_asprintf(&stmt, "SELECT geom FROM \"%s\".edge_data AS t "
- "JOIN (SELECT id, row_number() over() AS id_sorter FROM "
- "(SELECT UNNEST(ARRAY[%s]) AS id) AS y) x ON "
- "t.edge_id in (%s) AND x.id = t.edge_id "
- "ORDER BY x.id_sorter", pg_info->toposchema_name, stmt_id, stmt_id);
- G_free(stmt_id);
-
- G_debug(2, "SQL: %s", stmt);
- res = PQexec(pg_info->conn, stmt);
- G_free(stmt);
- if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
- PQntuples(res) != n_lines) {
- if (res)
- PQclear(res);
-
- return NULL;
- }
- return res;
- }
- #endif
|