123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- /*!
- \file lib/vector/Vlib/simple_features.c
-
- \brief Vector library - OGC Simple Features Access
- Higher level functions for reading/writing/manipulating vectors.
-
- Note: <b>In progress!</b> Currently on GV_POINT, GV_LINE,
- GV_BOUNDARY are supported.
-
- \todo
- - Vect_sfa_line_is_simple()
- - Vect_sfa_line_srid()
- - Vect_sfa_line_envelope()
- - Vect_sfa_line_asbinary()
- - Vect_sfa_line_is_empty()
- - Vect_sfa_line_is_3d()
- - Vect_sfa_line_is_measured()
- - Vect_sfa_line_boundary()
- Reference: http://www.opengeospatial.org/standards/sfa
- (C) 2009, 2011-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 <stdio.h>
- #include <grass/vector.h>
- #include <grass/glocale.h>
- #ifdef HAVE_POSTGRES
- #include "pg_local_proto.h"
- #endif
- #ifdef HAVE_OGR
- #include <ogr_api.h>
- #endif
- static int check_sftype(const struct line_pnts *, int, SF_FeatureType, int);
- static int get_sftype(const struct line_pnts *, int, int);
- static void print_point(const struct line_pnts *, int, int, int, FILE *);
- /*!
- \brief Get SF type of given vector feature
- List of supported feature types:
- - GV_POINT -> SF_POINT
- - GV_LINE -> SF_LINESTRING
- - GV_LINE (closed) -> SF_LINEARRING
- - GV_BOUNDARY -> SF_POLYGON
- \param Points pointer to line_pnts structure
- \param type feature type (see supported types above)
- \param with_z WITH_Z for 3D data
- \return SF type identificator (see list of supported types)
- \return -1 on error
- */
- SF_FeatureType Vect_sfa_get_line_type(const struct line_pnts *Points, int type, int with_z)
- {
- return get_sftype(Points, type, with_z);
- }
- /*!
- \brief Get relevant GV type
- \param Map pointer to Map_info structure
- \param type SF geometry type (SF_POINT, SF_LINESTRING, ...)
- \return GV type
- \return -1 on error
- */
- int Vect_sfa_get_type(SF_FeatureType sftype)
- {
- switch(sftype) {
- case SF_POINT:
- case SF_POINT25D:
- return GV_POINT;
- case SF_LINESTRING:
- case SF_LINESTRING25D:
- case SF_LINEARRING:
- return GV_LINE;
- case SF_POLYGON:
- case SF_POLYGON25D:
- return GV_BOUNDARY;
- default:
- break;
- }
-
- return -1;
- }
- /*!
- \brief Check SF type
- E.g. if <em>type</em> is GV_LINE with two or more segments and the
- start node is identical with the end node, and <em>sftype</em> is
- SF_LINEARRING, functions returns 1, otherwise 0.
- \param Points pointer to line_pnts structure
- \param type feature type (GV_POINT, GV_LINE, ...)
- \param sftype SF type to be checked (SF_POINT, SF_LINE, ...)
- \param with_z non-zero value for 3D data
-
- \return 1 if type is sftype
- \return 0 type differs from sftype
- */
- int Vect_sfa_check_line_type(const struct line_pnts *Points, int type,
- SF_FeatureType sftype, int with_z)
- {
- return check_sftype(Points, type, sftype, with_z);
- }
- /*!
- \brief Get geometry dimension
- \param Points pointer to line_pnts structure
- \param type feature type (GV_POINT, GV_LINE, ...)
- \return 0 for GV_POINT
- \return 1 for GV_LINE
- \return 2 for GV_BOUNDARY
- \return -1 unsupported feature type
- */
- int Vect_sfa_line_dimension(int type)
- {
- if (type == GV_POINT)
- return 0;
- if (type == GV_LINE)
- return 1;
- if (type == GV_BOUNDARY)
- return 2;
- return -1;
- }
- /*!
- \brief Get geometry type (string)
- Supported types:
- - GV_POINT -> SF_POINT -> "POINT"
- - GV_LINE -> SF_LINESTRING -> "LINESTRING"
- - GV_LINE (closed) -> SF_LINEARRING -> "LINEARRING"
- - GV_BOUNDARY (closed) -> SF_POLYGON -> "POLYGON"
-
- Note: Allocated string should be freed by G_free().
-
- \param Points pointer to line_pnts structure (feature geometry)
- \param type feature type (see supported types above)
- \return geometry type string
- \return NULL unsupported feature type
- */
- char *Vect_sfa_line_geometry_type(const struct line_pnts *Points, int type)
- {
- SF_FeatureType sftype = Vect_sfa_get_line_type(Points, type, 0);
- if (sftype == SF_POINT)
- return G_store("POINT");
- if (sftype == SF_LINESTRING)
- return G_store("LINESTRING");
- if (sftype == SF_LINEARRING)
- return G_store("LINEARRING");
- if (sftype == SF_POLYGON)
- return G_store("POLYGON");
-
- return NULL;
- }
- /*!
- \brief Export geometry to Well-Known Text
-
- \param Points pointer to line_pnts structure
- \param type feature type
- \param with_z non-zero value for 3D data
- \param precision floating number precision
- \param[out] file file where to write the output
- \return 0 on success
- \return -1 unsupported feature type
- */
- int Vect_sfa_line_astext(const struct line_pnts *Points, int type, int with_z, int precision, FILE *file)
- {
- int i, sftype;
-
- sftype = Vect_sfa_get_line_type(Points, type, with_z);
-
- switch(sftype) {
- case SF_POINT: { /* point */
- fprintf(file, "POINT(");
- print_point(Points, 0, with_z, precision, file);
- fprintf(file, ")\n");
- break;
- }
- case SF_LINESTRING: case SF_LINEARRING: /* line */ {
- if (sftype == SF_LINESTRING)
- fprintf(file, "LINESTRING(");
- else
- fprintf(file, "LINEARRING(");
- for (i = 0; i < Points->n_points; i++) {
- print_point(Points, i, with_z, precision, file);
- if (i < Points->n_points - 1)
- fprintf(file, ", ");
- }
- fprintf(file, ")\n");
- break;
- }
- case SF_POLYGON: /* polygon */ {
- /* write only outter/inner ring */
- fprintf(file, "(");
- for (i = 0; i < Points->n_points; i++) {
- print_point(Points, i, with_z, precision, file);
- if (i < Points->n_points - 1)
- fprintf(file, ", ");
- }
- fprintf(file, ")");
- break;
- }
- default: {
- G_warning(_("Unknown Simple Features type (%d)"), sftype);
- return -1;
- }
- }
-
- fflush(file);
- return 0;
- }
- /*!
- \brief Check if feature is simple
- \param Points pointer to line_pnts structure
- \param type feature type (GV_POINT, GV_LINE, ...)
-
- \return 1 feature simple
- \return 0 feature not simple
- \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
- */
- int Vect_sfa_is_line_simple(const struct line_pnts *Points, int type, int with_z)
- {
- SF_FeatureType sftype;
-
- sftype = Vect_sfa_get_line_type(Points, type, with_z);
- /* TODO */
- return 0;
- }
- /*!
- \brief Check if feature is closed
- \param Points pointer to line_pnts structure
- \param type feature type (GV_LINE or GV_BOUNDARY)
- \return 1 feature closed
- \return 0 feature not closed
- \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
- */
- int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type, int with_z)
- {
- int npoints;
- if (type & (GV_LINES)) {
- npoints = Vect_get_num_line_points(Points);
- if (npoints > 2 &&
- Points->x[0] == Points->x[npoints-1] &&
- Points->y[0] == Points->y[npoints-1]) {
- if (!with_z)
- return 1;
- if (Points->z[0] == Points->z[npoints-1])
- return 1;
- }
- return 0;
- }
- return -1;
- }
- /*!
- \brief Get number of simple features
- For native format or PostGIS Topology returns -1
- \param Map vector map
- \return number of features
- \return -1 on error
- */
- int Vect_sfa_get_num_features(const struct Map_info *Map)
- {
- int nfeat;
- nfeat = 0;
- if (Map->format == GV_FORMAT_OGR || Map->format == GV_FORMAT_OGR_DIRECT) {
- /* OGR */
- #ifdef HAVE_OGR
- const struct Format_info_ogr *ogr_info;
-
- ogr_info = &(Map->fInfo.ogr);
-
- if (!ogr_info->layer)
- return -1;
- return OGR_L_GetFeatureCount(ogr_info->layer, TRUE);
- #else
- G_fatal_error(_("GRASS is not compiled with OGR support"));
- return -1;
- #endif
- }
- else if (Map->format == GV_FORMAT_POSTGIS && !Map->fInfo.pg.toposchema_name) {
- #ifdef HAVE_POSTGRES
- /* PostGIS */
- char stmt[DB_SQL_MAX];
-
- const struct Format_info_pg *pg_info;
- pg_info = &(Map->fInfo.pg);
-
- if (!pg_info->conn || !pg_info->table_name) {
- G_warning(_("No connection defined"));
- return -1;
- }
- sprintf(stmt, "SELECT count(*) FROM \"%s\".\"%s\"", pg_info->schema_name,
- pg_info->table_name);
- nfeat = Vect__execute_get_value_pg(pg_info->conn, stmt);
- if (nfeat < 0) {
- G_warning(_("Unable to get number of simple features"));
- return -1;
- }
- #else
- G_fatal_error(_("GRASS is not compiled with PostgreSQL support"));
- return -1;
- #endif
- }
- else {
- G_warning(_("Unable to report simple features for vector map <%s>"),
- Vect_get_full_name(Map));
- return -1;
- }
- return nfeat;
- }
- int check_sftype(const struct line_pnts *points, int type,
- SF_FeatureType sftype, int with_z)
- {
- if (type == GV_POINT && sftype == SF_POINT) {
- return 1;
- }
- if (type == GV_LINE) {
- if (sftype == SF_LINESTRING)
- return 1;
-
- if (sftype == SF_LINEARRING &&
- Vect_sfa_is_line_closed(points, type, with_z))
- return 1;
- }
- if (type == GV_BOUNDARY) {
- if (sftype == SF_POLYGON &&
- Vect_sfa_is_line_closed(points, type, 0)) /* force 2D */
- return 1;
- }
- return 0;
- }
- int get_sftype(const struct line_pnts *points, int type, int with_z)
- {
- if (check_sftype(points, type, SF_POINT, with_z))
- return SF_POINT;
- if (check_sftype(points, type, SF_LINEARRING, with_z))
- return SF_LINEARRING;
- if (check_sftype(points, type, SF_LINESTRING, with_z))
- return SF_LINESTRING;
- if (check_sftype(points, type, SF_POLYGON, with_z))
- return SF_POLYGON;
- return -1;
- }
- void print_point(const struct line_pnts *Points, int index, int with_z, int precision, FILE *file)
- {
- fprintf(file, "%.*f %.*f", precision, Points->x[index], precision, Points->y[index]);
- if (with_z)
- fprintf(file, " %.*f", precision, Points->z[index]);
- }
|