simple_features.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*!
  2. \file lib/vector/Vlib/simple_features.c
  3. \brief Vector library - OGC Simple Features Access
  4. Higher level functions for reading/writing/manipulating vectors.
  5. Note: <b>In progress!</b> Currently on GV_POINT, GV_LINE,
  6. GV_BOUNDARY are supported.
  7. \todo
  8. - Vect_sfa_line_is_simple()
  9. - Vect_sfa_line_srid()
  10. - Vect_sfa_line_envelope()
  11. - Vect_sfa_line_asbinary()
  12. - Vect_sfa_line_is_empty()
  13. - Vect_sfa_line_is_3d()
  14. - Vect_sfa_line_is_measured()
  15. - Vect_sfa_line_boundary()
  16. Reference: http://www.opengeospatial.org/standards/sfa
  17. (C) 2009, 2011-2012 by the GRASS Development Team
  18. This program is free software under the GNU General Public License
  19. (>=v2). Read the file COPYING that comes with GRASS for details.
  20. \author Martin Landa <landa.martin gmail.com>
  21. */
  22. #include <stdio.h>
  23. #include <grass/vector.h>
  24. #include <grass/glocale.h>
  25. static int check_sftype(const struct line_pnts *, int, SF_FeatureType, int);
  26. static int get_sftype(const struct line_pnts *, int, int);
  27. static void print_point(const struct line_pnts *, int, int, int, FILE *);
  28. /*!
  29. \brief Get SF type of given vector feature
  30. List of supported feature types:
  31. - GV_POINT -> SF_POINT
  32. - GV_LINE -> SF_LINESTRING
  33. - GV_LINE (closed) -> SF_LINEARRING
  34. - GV_BOUNDARY -> SF_POLYGON
  35. \param Points pointer to line_pnts structure
  36. \param type feature type (see supported types above)
  37. \param with_z WITH_Z for 3D data
  38. \return SF type identificator (see list of supported types)
  39. \return -1 on error
  40. */
  41. SF_FeatureType Vect_sfa_get_line_type(const struct line_pnts *Points, int type, int with_z)
  42. {
  43. return get_sftype(Points, type, with_z);
  44. }
  45. /*!
  46. \brief Get relevant GV type
  47. \param Map pointer to Map_info structure
  48. \param type SF geometry type (SF_POINT, SF_LINESTRING, ...)
  49. \return GV type
  50. \return -1 on error
  51. */
  52. int Vect_sfa_get_type(SF_FeatureType sftype)
  53. {
  54. switch(sftype) {
  55. case SF_POINT:
  56. case SF_POINT25D:
  57. return GV_POINT;
  58. case SF_LINESTRING:
  59. case SF_LINESTRING25D:
  60. case SF_LINEARRING:
  61. return GV_LINE;
  62. case SF_POLYGON:
  63. case SF_POLYGON25D:
  64. return GV_BOUNDARY;
  65. default:
  66. break;
  67. }
  68. return -1;
  69. }
  70. /*!
  71. \brief Check SF type
  72. E.g. if <em>type</em> is GV_LINE with two or more segments and the
  73. start node is identical with the end node, and <em>sftype</em> is
  74. SF_LINEARRING, functions returns 1, otherwise 0.
  75. \param Points pointer to line_pnts structure
  76. \param type feature type (GV_POINT, GV_LINE, ...)
  77. \param sftype SF type to be checked (SF_POINT, SF_LINE, ...)
  78. \param with_z non-zero value for 3D data
  79. \return 1 if type is sftype
  80. \return 0 type differs from sftype
  81. */
  82. int Vect_sfa_check_line_type(const struct line_pnts *Points, int type,
  83. SF_FeatureType sftype, int with_z)
  84. {
  85. return check_sftype(Points, type, sftype, with_z);
  86. }
  87. /*!
  88. \brief Get geometry dimension
  89. \param Points pointer to line_pnts structure
  90. \param type feature type (GV_POINT, GV_LINE, ...)
  91. \return 0 for GV_POINT
  92. \return 1 for GV_LINE
  93. \return 2 for GV_BOUNDARY
  94. \return -1 unsupported feature type
  95. */
  96. int Vect_sfa_line_dimension(int type)
  97. {
  98. if (type == GV_POINT)
  99. return 0;
  100. if (type == GV_LINE)
  101. return 1;
  102. if (type == GV_BOUNDARY)
  103. return 2;
  104. return -1;
  105. }
  106. /*!
  107. \brief Get geometry type (string)
  108. Supported types:
  109. - GV_POINT -> SF_POINT -> "POINT"
  110. - GV_LINE -> SF_LINESTRING -> "LINESTRING"
  111. - GV_LINE (closed) -> SF_LINEARRING -> "LINEARRING"
  112. - GV_BOUNDARY (closed) -> SF_POLYGON -> "POLYGON"
  113. Note: Allocated string should be freed by G_free().
  114. \param Points pointer to line_pnts structure (feature geometry)
  115. \param type feature type (see supported types above)
  116. \return geometry type string
  117. \return NULL unsupported feature type
  118. */
  119. char *Vect_sfa_line_geometry_type(const struct line_pnts *Points, int type)
  120. {
  121. SF_FeatureType sftype = Vect_sfa_get_line_type(Points, type, 0);
  122. if (sftype == SF_POINT)
  123. return G_store("POINT");
  124. if (sftype == SF_LINESTRING)
  125. return G_store("LINESTRING");
  126. if (sftype == SF_LINEARRING)
  127. return G_store("LINEARRING");
  128. if (sftype == SF_POLYGON)
  129. return G_store("POLYGON");
  130. return NULL;
  131. }
  132. /*!
  133. \brief Export geometry to Well-Known Text
  134. \param Points pointer to line_pnts structure
  135. \param type feature type
  136. \param with_z non-zero value for 3D data
  137. \param precision floating number precision
  138. \param[out] file file where to write the output
  139. \return 0 on success
  140. \return -1 unsupported feature type
  141. */
  142. int Vect_sfa_line_astext(const struct line_pnts *Points, int type, int with_z, int precision, FILE *file)
  143. {
  144. int i, sftype;
  145. sftype = Vect_sfa_get_line_type(Points, type, with_z);
  146. switch(sftype) {
  147. case SF_POINT: { /* point */
  148. fprintf(file, "POINT(");
  149. print_point(Points, 0, with_z, precision, file);
  150. fprintf(file, ")\n");
  151. break;
  152. }
  153. case SF_LINESTRING: case SF_LINEARRING: /* line */ {
  154. if (sftype == SF_LINESTRING)
  155. fprintf(file, "LINESTRING(");
  156. else
  157. fprintf(file, "LINEARRING(");
  158. for (i = 0; i < Points->n_points; i++) {
  159. print_point(Points, i, with_z, precision, file);
  160. if (i < Points->n_points - 1)
  161. fprintf(file, ", ");
  162. }
  163. fprintf(file, ")\n");
  164. break;
  165. }
  166. case SF_POLYGON: /* polygon */ {
  167. /* write only outter/inner ring */
  168. fprintf(file, "(");
  169. for (i = 0; i < Points->n_points; i++) {
  170. print_point(Points, i, with_z, precision, file);
  171. if (i < Points->n_points - 1)
  172. fprintf(file, ", ");
  173. }
  174. fprintf(file, ")");
  175. break;
  176. }
  177. default: {
  178. G_warning(_("Unknown Simple Features type (%d)"), sftype);
  179. return -1;
  180. }
  181. }
  182. fflush(file);
  183. return 0;
  184. }
  185. /*!
  186. \brief Check if feature is simple
  187. \param Points pointer to line_pnts structure
  188. \param type feature type (GV_POINT, GV_LINE, ...)
  189. \return 1 feature simple
  190. \return 0 feature not simple
  191. \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
  192. */
  193. int Vect_sfa_is_line_simple(const struct line_pnts *Points, int type, int with_z)
  194. {
  195. SF_FeatureType sftype;
  196. sftype = Vect_sfa_get_line_type(Points, type, with_z);
  197. /* TODO */
  198. return 0;
  199. }
  200. /*!
  201. \brief Check if feature is closed
  202. \param Points pointer to line_pnts structure
  203. \param type feature type (GV_LINE or GV_BOUNDARY)
  204. \return 1 feature closed
  205. \return 0 feature not closed
  206. \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
  207. */
  208. int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type, int with_z)
  209. {
  210. int npoints;
  211. if (type & (GV_LINES)) {
  212. npoints = Vect_get_num_line_points(Points);
  213. if (npoints > 2 &&
  214. Points->x[0] == Points->x[npoints-1] &&
  215. Points->y[0] == Points->y[npoints-1]) {
  216. if (!with_z)
  217. return 1;
  218. if (Points->z[0] == Points->z[npoints-1])
  219. return 1;
  220. }
  221. return 0;
  222. }
  223. return -1;
  224. }
  225. int check_sftype(const struct line_pnts *points, int type,
  226. SF_FeatureType sftype, int with_z)
  227. {
  228. if (type == GV_POINT && sftype == SF_POINT) {
  229. return 1;
  230. }
  231. if (type == GV_LINE) {
  232. if (sftype == SF_LINESTRING)
  233. return 1;
  234. if (sftype == SF_LINEARRING &&
  235. Vect_sfa_is_line_closed(points, type, with_z))
  236. return 1;
  237. }
  238. if (type == GV_BOUNDARY) {
  239. if (sftype == SF_POLYGON &&
  240. Vect_sfa_is_line_closed(points, type, 0)) /* force 2D */
  241. return 1;
  242. }
  243. return 0;
  244. }
  245. int get_sftype(const struct line_pnts *points, int type, int with_z)
  246. {
  247. if (check_sftype(points, type, SF_POINT, with_z))
  248. return SF_POINT;
  249. if (check_sftype(points, type, SF_LINEARRING, with_z))
  250. return SF_LINEARRING;
  251. if (check_sftype(points, type, SF_LINESTRING, with_z))
  252. return SF_LINESTRING;
  253. if (check_sftype(points, type, SF_POLYGON, with_z))
  254. return SF_POLYGON;
  255. return -1;
  256. }
  257. void print_point(const struct line_pnts *Points, int index, int with_z, int precision, FILE *file)
  258. {
  259. fprintf(file, "%.*f %.*f", precision, Points->x[index], precision, Points->y[index]);
  260. if (with_z)
  261. fprintf(file, " %.*f", precision, Points->z[index]);
  262. }