GRASS GIS 8 Programmer's Manual  8.4.0dev(2024)-112dd97adf
area_pg.c
Go to the documentation of this file.
1 /*!
2  \file lib/vector/Vlib/area_pg.c
3 
4  \brief Vector library - area-related functions (PostGIS Topology)
5 
6  Higher level functions for reading/writing/manipulating vectors.
7 
8  (C) 2013 by the GRASS Development Team
9 
10  This program is free software under the GNU General Public License
11  (>=v2). Read the file COPYING that comes with GRASS for details.
12 
13  \author Martin Landa <landa.martin gmail.com>
14  */
15 
16 #include <grass/vector.h>
17 
18 #ifdef HAVE_POSTGRES
19 #include "pg_local_proto.h"
20 
21 static PGresult *build_stmt(const struct Plus_head *,
22  const struct Format_info_pg *, const plus_t *, int);
23 
24 /*!
25  \brief Get area boundary points (PostGIS Topology)
26 
27  Used by Vect_build_line_area() and Vect_get_area_points().
28 
29  \param Map pointer to Map_info struct
30  \param lines array of boundary lines
31  \param n_lines number of lines in array
32  \param[out] APoints pointer to output line_pnts struct
33 
34  \return number of points
35  \return -1 on error
36  */
37 int Vect__get_area_points_pg(struct Map_info *Map, const plus_t *lines,
38  int n_lines, struct line_pnts *APoints)
39 {
40  int i, direction;
41 
42  struct Format_info_pg *pg_info;
43 
44  PGresult *res;
45 
46  pg_info = (struct Format_info_pg *)&(Map->fInfo.pg);
47 
48  Vect_reset_line(APoints);
49 
50  res = build_stmt(&(Map->plus), pg_info, lines, n_lines);
51  if (!res)
52  return -1;
53 
54  for (i = 0; i < n_lines; i++) {
55  Vect__cache_feature_pg(PQgetvalue(res, i, 0), FALSE, FALSE,
56  &(pg_info->cache),
57  NULL); /* do caching in readable way */
58  direction = lines[i] > 0 ? GV_FORWARD : GV_BACKWARD;
59  Vect_append_points(APoints, pg_info->cache.lines[0], direction);
60  APoints->n_points--; /* skip last point, avoids duplicates */
61  }
62  APoints->n_points++; /* close polygon */
63 
64  PQclear(res);
65 
66  return APoints->n_points;
67 }
68 
69 PGresult *build_stmt(const struct Plus_head *plus,
70  const struct Format_info_pg *pg_info, const plus_t *lines,
71  int n_lines)
72 {
73  int i, line;
74  size_t stmt_id_size;
75  char *stmt, *stmt_id, buf_id[128];
76 
77  struct P_line *BLine;
78 
79  PGresult *res;
80 
81  stmt = NULL;
82  stmt_id_size = DB_SQL_MAX;
83  stmt_id = (char *)G_malloc(stmt_id_size);
84  stmt_id[0] = '\0';
85 
86  for (i = 0; i < n_lines; i++) {
87  if (strlen(stmt_id) + 100 > stmt_id_size) {
88  stmt_id_size = strlen(stmt_id) + DB_SQL_MAX;
89  stmt_id = (char *)G_realloc(stmt_id, stmt_id_size);
90  }
91  line = abs(lines[i]);
92  BLine = plus->Line[line];
93  if (i > 0)
94  strcat(stmt_id, ",");
95  sprintf(buf_id, "%d", (int)BLine->offset);
96  strcat(stmt_id, buf_id);
97  }
98  /* Not really working - why?
99  G_asprintf(&stmt, "SELECT geom FROM \"%s\".edge_data WHERE edge_id IN
100  (%s) " "ORDER BY POSITION(edge_id::text in '%s')",
101  pg_info->toposchema_name, stmt_id, stmt_id);
102  */
103  G_asprintf(&stmt,
104  "SELECT geom FROM \"%s\".edge_data AS t "
105  "JOIN (SELECT id, row_number() over() AS id_sorter FROM "
106  "(SELECT UNNEST(ARRAY[%s]) AS id) AS y) x ON "
107  "t.edge_id in (%s) AND x.id = t.edge_id "
108  "ORDER BY x.id_sorter",
109  pg_info->toposchema_name, stmt_id, stmt_id);
110  G_free(stmt_id);
111 
112  G_debug(2, "SQL: %s", stmt);
113  res = PQexec(pg_info->conn, stmt);
114  G_free(stmt);
115 
116  if (!res || PQresultStatus(res) != PGRES_TUPLES_OK ||
117  PQntuples(res) != n_lines) {
118  if (res)
119  PQclear(res);
120 
121  return NULL;
122  }
123 
124  return res;
125 }
126 #endif
int Vect__get_area_points_pg(struct Map_info *Map, const plus_t *lines, int n_lines, struct line_pnts *APoints)
Get area boundary points (PostGIS Topology)
Definition: area_pg.c:37
#define NULL
Definition: ccmath.h:32
#define DB_SQL_MAX
Definition: dbmi.h:142
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
#define G_realloc(p, n)
Definition: defs/gis.h:96
#define G_malloc(n)
Definition: defs/gis.h:94
int G_asprintf(char **, const char *,...) __attribute__((format(printf
int G_debug(int, const char *,...) __attribute__((format(printf
void Vect_reset_line(struct line_pnts *)
Reset line.
Definition: line.c:129
int Vect_append_points(struct line_pnts *, const struct line_pnts *, int)
Appends points to the end of a line.
Definition: line.c:335
#define GV_FORWARD
Line direction indicator forward/backward.
Definition: dig_defines.h:179
#define GV_BACKWARD
Definition: dig_defines.h:180
int plus_t
plus_t size
Definition: dig_structs.h:41
#define FALSE
Definition: gis.h:83
SF_FeatureType Vect__cache_feature_pg(const char *data, int skip_polygon, int force_type, struct Format_info_cache *cache, struct feat_parts *fparts)
Read geometry from HEX data.
Definition: read_pg.c:778
struct line_pnts ** lines
Lines array.
Definition: dig_structs.h:462
Non-native format info (PostGIS)
Definition: dig_structs.h:590
PGconn * conn
PGconn object (generated by PQconnectdb)
Definition: dig_structs.h:650
char * toposchema_name
Topology schema name and id.
Definition: dig_structs.h:686
PGresult * res
Definition: dig_structs.h:651
struct Format_info_cache cache
Lines cache for reading feature.
Definition: dig_structs.h:670
struct Format_info_pg pg
PostGIS info.
Definition: dig_structs.h:712
Vector map info.
Definition: dig_structs.h:1243
struct Format_info fInfo
Format info for non-native formats.
Definition: dig_structs.h:1400
struct Plus_head plus
Plus info (topology, version, ...)
Definition: dig_structs.h:1270
Vector geometry.
Definition: dig_structs.h:1553
off_t offset
Offset in coor file for line.
Definition: dig_structs.h:1571
Basic topology-related info.
Definition: dig_structs.h:769
struct P_line ** Line
Array of vector geometries.
Definition: dig_structs.h:871
Feature geometry info - coordinates.
Definition: dig_structs.h:1651
int n_points
Number of points.
Definition: dig_structs.h:1667