|
@@ -32,7 +32,7 @@ static unsigned int wkb_data_length;
|
|
|
|
|
|
static int read_next_line_pg(struct Map_info *,
|
|
|
struct line_pnts *, struct line_cats *, int);
|
|
|
-SF_FeatureType get_feature(struct Format_info_pg *, int, const char *);
|
|
|
+SF_FeatureType get_feature(struct Format_info_pg *, int, int);
|
|
|
static unsigned char *hex_to_wkb(const char *, int *);
|
|
|
static int point_from_wkb(const unsigned char *, int, int, int,
|
|
|
struct line_pnts *);
|
|
@@ -46,7 +46,8 @@ static int geometry_collection_from_wkb(const unsigned char *, int, int, int,
|
|
|
static int error_corrupted_data(const char *);
|
|
|
static void reallocate_cache(struct Format_info_cache *, int);
|
|
|
static void add_fpart(struct feat_parts *, SF_FeatureType, int, int);
|
|
|
-static int read_centroid_pg(struct Format_info_pg *, int, struct line_pnts *);
|
|
|
+static int get_centroid_topo(struct Format_info_pg *, int, struct line_pnts *);
|
|
|
+static int get_centroid(struct Map_info *, int, struct line_pnts *);
|
|
|
#endif
|
|
|
|
|
|
/*!
|
|
@@ -249,7 +250,7 @@ int V1_read_line_pg(struct Map_info *Map,
|
|
|
|
|
|
G_debug(3, "read (%s) feature (fid = %ld) to cache",
|
|
|
pg_info->table_name, fid);
|
|
|
- get_feature(pg_info, fid, NULL);
|
|
|
+ get_feature(pg_info, fid, -1);
|
|
|
|
|
|
if (pg_info->cache.sf_type == SF_NONE) {
|
|
|
G_warning(_("Feature %d without geometry skipped"), fid);
|
|
@@ -287,8 +288,7 @@ int V2_read_line_pg(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
struct line_cats *line_c, int line)
|
|
|
{
|
|
|
#ifdef HAVE_POSTGRES
|
|
|
- int type;
|
|
|
- char *topotable_name;
|
|
|
+ int type, fid;
|
|
|
|
|
|
struct Format_info_pg *pg_info;
|
|
|
struct P_line *Line;
|
|
@@ -314,19 +314,20 @@ int V2_read_line_pg(struct Map_info *Map, struct line_pnts *line_p,
|
|
|
if (line_c)
|
|
|
Vect_cat_set(line_c, 1, (int) Line->offset);
|
|
|
|
|
|
- if (Line->type == GV_POINT)
|
|
|
- topotable_name = "node";
|
|
|
- else if (Line->type & GV_LINES)
|
|
|
- topotable_name = "edge";
|
|
|
- else if (Line->type == GV_CENTROID) {
|
|
|
- return read_centroid_pg(pg_info, (int) Line->offset, line_p);
|
|
|
- }
|
|
|
- else {
|
|
|
- G_warning(_("Unsupported feature type %d"), Line->type);
|
|
|
- return -1;
|
|
|
+ if (Line->type == GV_CENTROID) {
|
|
|
+ if (pg_info->toposchema_name)
|
|
|
+ return get_centroid_topo(pg_info, line, line_p);
|
|
|
+ else
|
|
|
+ return get_centroid(Map, line, line_p);
|
|
|
}
|
|
|
|
|
|
- get_feature(pg_info, Line->offset, topotable_name);
|
|
|
+ /* get feature id */
|
|
|
+ if (pg_info->toposchema_name)
|
|
|
+ fid = Line->offset;
|
|
|
+ else
|
|
|
+ fid = pg_info->offset.array[Line->offset];
|
|
|
+
|
|
|
+ get_feature(pg_info, fid, Line->type);
|
|
|
|
|
|
if (pg_info->cache.sf_type == SF_NONE) {
|
|
|
G_warning(_("Feature %d without geometry skipped"), Line->offset);
|
|
@@ -393,7 +394,7 @@ int read_next_line_pg(struct Map_info *Map,
|
|
|
/* read feature to cache if necessary */
|
|
|
while (pg_info->cache.lines_next == pg_info->cache.lines_num) {
|
|
|
/* cache feature -> line_p & line_c */
|
|
|
- sf_type = get_feature(pg_info, -1, NULL);
|
|
|
+ sf_type = get_feature(pg_info, -1, -1);
|
|
|
|
|
|
if (sf_type == SF_NONE) {
|
|
|
G_warning(_("Feature %d without geometry skipped"), line);
|
|
@@ -462,15 +463,14 @@ int read_next_line_pg(struct Map_info *Map,
|
|
|
\return simple feature type (SF_POINT, SF_LINESTRING, ...)
|
|
|
\return -1 on error
|
|
|
*/
|
|
|
-SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid,
|
|
|
- const char *topotable_name)
|
|
|
+SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid, int type)
|
|
|
{
|
|
|
char *data;
|
|
|
char stmt[DB_SQL_MAX];
|
|
|
int left_face, right_face;
|
|
|
|
|
|
- if (!topotable_name && !pg_info->geom_column) {
|
|
|
- G_warning(_("No geometry column defined"));
|
|
|
+ if (!pg_info->geom_column && !pg_info->topogeom_column) {
|
|
|
+ G_warning(_("No geometry or topo geometry column defined"));
|
|
|
return -1;
|
|
|
}
|
|
|
if (fid < 1) {
|
|
@@ -481,7 +481,7 @@ SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid,
|
|
|
}
|
|
|
}
|
|
|
else {
|
|
|
- if (!topotable_name && !pg_info->fid_column) {
|
|
|
+ if (!pg_info->fid_column) {
|
|
|
G_warning(_("Random access not supported. "
|
|
|
"Primary key not defined."));
|
|
|
return -1;
|
|
@@ -490,7 +490,7 @@ SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid,
|
|
|
if (execute(pg_info->conn, "BEGIN") == -1)
|
|
|
return -1;
|
|
|
|
|
|
- if (!topotable_name) {
|
|
|
+ if (!pg_info->toposchema_name) {
|
|
|
/* simple feature access */
|
|
|
sprintf(stmt,
|
|
|
"DECLARE %s_%s%p CURSOR FOR SELECT %s FROM \"%s\".\"%s\" "
|
|
@@ -500,6 +500,18 @@ SF_FeatureType get_feature(struct Format_info_pg *pg_info, int fid,
|
|
|
}
|
|
|
else {
|
|
|
/* topological access */
|
|
|
+ char *topotable_name;
|
|
|
+
|
|
|
+ if (type == GV_POINT)
|
|
|
+ topotable_name = "node";
|
|
|
+ else if (type & GV_LINES)
|
|
|
+ topotable_name = "edge";
|
|
|
+ else {
|
|
|
+ G_warning(_("Unsupported feature type %d"), type);
|
|
|
+ execute(pg_info->conn, "ROLLBACK");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
sprintf(stmt,
|
|
|
"DECLARE %s_%s%p CURSOR FOR SELECT geom,left_face,right_face "
|
|
|
" FROM \"%s\".\"%s\" "
|
|
@@ -1219,7 +1231,7 @@ void reallocate_cache(struct Format_info_cache *cache, int num)
|
|
|
cache->lines_alloc = 1;
|
|
|
}
|
|
|
else {
|
|
|
- cache->lines_alloc += 20;
|
|
|
+ cache->lines_alloc += num;
|
|
|
}
|
|
|
|
|
|
cache->lines = (struct line_pnts **)G_realloc(cache->lines,
|
|
@@ -1229,7 +1241,7 @@ void reallocate_cache(struct Format_info_cache *cache, int num)
|
|
|
cache->lines_alloc * sizeof(int));
|
|
|
|
|
|
if (cache->lines_alloc > 1) {
|
|
|
- for (i = cache->lines_alloc - 20; i < cache->lines_alloc; i++) {
|
|
|
+ for (i = cache->lines_alloc - num; i < cache->lines_alloc; i++) {
|
|
|
cache->lines[i] = Vect_new_line_struct();
|
|
|
cache->lines_types[i] = -1;
|
|
|
}
|
|
@@ -1250,7 +1262,7 @@ void add_fpart(struct feat_parts *fparts, SF_FeatureType ftype,
|
|
|
if (fparts->a_parts == 0)
|
|
|
fparts->a_parts = 1;
|
|
|
else
|
|
|
- fparts->a_parts += 20;
|
|
|
+ fparts->a_parts += fparts->n_parts;
|
|
|
|
|
|
fparts->ftype = (SF_FeatureType *) G_realloc(fparts->ftype,
|
|
|
fparts->a_parts *
|
|
@@ -1268,8 +1280,18 @@ void add_fpart(struct feat_parts *fparts, SF_FeatureType ftype,
|
|
|
fparts->n_parts++;
|
|
|
}
|
|
|
|
|
|
-int read_centroid_pg(struct Format_info_pg *pg_info,
|
|
|
- int centroid, struct line_pnts *line_p)
|
|
|
+/*
|
|
|
+ \brief Get centroid from PostGIS topology
|
|
|
+
|
|
|
+ \param pg_info pointer to Format_info_pg
|
|
|
+ \param centroid centroid id
|
|
|
+ \param[out] line_p output geometry
|
|
|
+
|
|
|
+ \return GV_CENTROID on success
|
|
|
+ \return -1 on error
|
|
|
+*/
|
|
|
+int get_centroid_topo(struct Format_info_pg *pg_info,
|
|
|
+ int centroid, struct line_pnts *line_p)
|
|
|
{
|
|
|
char stmt[DB_SQL_MAX];
|
|
|
char *data;
|
|
@@ -1300,4 +1322,51 @@ int read_centroid_pg(struct Format_info_pg *pg_info,
|
|
|
|
|
|
return GV_CENTROID;
|
|
|
}
|
|
|
+
|
|
|
+/*
|
|
|
+ \brief Get centroid
|
|
|
+
|
|
|
+ \param pg_info pointer to Format_info_pg
|
|
|
+ \param centroid centroid id
|
|
|
+ \param[out] line_p output geometry
|
|
|
+
|
|
|
+ \return GV_CENTROID on success
|
|
|
+ \return -1 on error
|
|
|
+*/
|
|
|
+int get_centroid(struct Map_info *Map, int centroid,
|
|
|
+ struct line_pnts *line_p)
|
|
|
+{
|
|
|
+ int i, found;
|
|
|
+ struct bound_box box;
|
|
|
+ struct boxlist list;
|
|
|
+ struct P_line *Line;
|
|
|
+ struct P_topo_c *topo;
|
|
|
+
|
|
|
+ Line = Map->plus.Line[centroid];
|
|
|
+ topo = (struct P_topo_c *)Line->topo;
|
|
|
+
|
|
|
+ /* get area bbox */
|
|
|
+ Vect_get_area_box(Map, topo->area, &box);
|
|
|
+ /* search in spatial index for centroid with area bbox */
|
|
|
+ dig_init_boxlist(&list, TRUE);
|
|
|
+ Vect_select_lines_by_box(Map, &box, Line->type, &list);
|
|
|
+
|
|
|
+ found = -1;
|
|
|
+ for (i = 0; i < list.n_values; i++) {
|
|
|
+ if (list.id[i] == centroid) {
|
|
|
+ found = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (found == -1)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ if (line_p) {
|
|
|
+ Vect_reset_line(line_p);
|
|
|
+ Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
|
|
|
+ }
|
|
|
+
|
|
|
+ return GV_CENTROID;
|
|
|
+}
|
|
|
#endif
|