simple_features.c 7.5 KB

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