simple_features.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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 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, int, 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_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. int 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 Check SF type
  45. E.g. if <em>type</em> is GV_LINE with two or more segments and the
  46. start node is identical with the end node, and <em>sftype</em> is
  47. SF_LINEARRING, functions returns 1, otherwise 0.
  48. \param Points pointer to line_pnts structure
  49. \param type feature type (GV_POINT, GV_LINE, ...)
  50. \param sftype SF type to be checked (SF_POINT, SF_LINE, ...)
  51. \param with_z non-zero value for 3D data
  52. \return 1 if type is sftype
  53. \return 0 type differs from sftype
  54. */
  55. int Vect_sfa_check_line_type(const struct line_pnts *Points, int type, int sftype, int with_z)
  56. {
  57. return check_sftype(Points, type, sftype, with_z);
  58. }
  59. /*!
  60. \brief Get geometry dimension
  61. \param Points pointer to line_pnts structure
  62. \param type feature type (GV_POINT, GV_LINE, ...)
  63. \return 0
  64. \return 1
  65. \return 2
  66. \return -1 unsupported feature type
  67. */
  68. int Vect_sfa_line_dimension(int type)
  69. {
  70. if (type == GV_POINT)
  71. return 0;
  72. if (type == GV_LINE)
  73. return 1;
  74. if (type == GV_AREA)
  75. return 2;
  76. return -1;
  77. }
  78. /*!
  79. \brief Get geometry type (string)
  80. \param Points pointer to line_pnts structure
  81. \param type feature type (GV_POINT, GV_LINE, ...)
  82. \return geometry type string
  83. \return NULL unsupported feature type
  84. */
  85. char *Vect_sfa_line_geometry_type(const struct line_pnts *Points, int type)
  86. {
  87. int sftype = Vect_sfa_get_line_type(Points, type, 0);
  88. if (sftype == SF_POINT)
  89. return G_store("POINT");
  90. if (sftype == SF_LINESTRING)
  91. return G_store("LINESTRING");
  92. if (sftype == SF_LINE)
  93. return G_store("LINE");
  94. if (sftype == SF_LINEARRING)
  95. return G_store("LINEARRING");
  96. return NULL;
  97. }
  98. /*!
  99. \brief Export geometry to Well-Known Text
  100. \param Points pointer to line_pnts structure
  101. \param type feature type
  102. \param with_z non-zero value for 3D data
  103. \param precision floating number precision
  104. \param[out] file file where to write the output
  105. \return 0 on success
  106. \return -1 unsupported feature type
  107. */
  108. int Vect_sfa_line_astext(const struct line_pnts *Points, int type, int with_z, int precision, FILE *file)
  109. {
  110. int i, sftype;
  111. sftype = Vect_sfa_get_line_type(Points, type, with_z);
  112. switch(sftype) {
  113. case SF_POINT: { /* point */
  114. fprintf(file, "POINT(");
  115. print_point(Points, 0, with_z, precision, file);
  116. fprintf(file, ")\n");
  117. break;
  118. }
  119. case SF_LINESTRING: case SF_LINE: case SF_LINEARRING: /* line */ {
  120. if (sftype == SF_LINESTRING)
  121. fprintf(file, "LINESTRING(");
  122. else if (sftype == SF_LINE)
  123. fprintf(file, "LINE(");
  124. else
  125. fprintf(file, "LINEARRING(");
  126. for (i = 0; i < Points->n_points; i++) {
  127. print_point(Points, i, with_z, precision, file);
  128. if (i < Points->n_points - 1)
  129. fprintf(file, ", ");
  130. }
  131. fprintf(file, ")\n");
  132. break;
  133. }
  134. case SF_POLYGON: /* polygon */ {
  135. /* write only outter/inner ring */
  136. fprintf(file, "(");
  137. for (i = 0; i < Points->n_points; i++) {
  138. print_point(Points, i, with_z, precision, file);
  139. if (i < Points->n_points - 1)
  140. fprintf(file, ", ");
  141. }
  142. fprintf(file, ")");
  143. break;
  144. }
  145. default: {
  146. G_warning(_("Unknown Simple Features type (%d)"), sftype);
  147. return -1;
  148. }
  149. }
  150. fflush(file);
  151. return 0;
  152. }
  153. /*!
  154. \brief Check if feature is simple
  155. \param Points pointer to line_pnts structure
  156. \param type feature type (GV_POINT, GV_LINE, ...)
  157. \return 1 feature simple
  158. \return 0 feature not simple
  159. \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
  160. */
  161. int Vect_sfa_is_line_simple(const struct line_pnts *Points, int type, int with_z)
  162. {
  163. int sftype;
  164. sftype = Vect_sfa_get_line_type(Points, type, with_z);
  165. /* TODO */
  166. return 0;
  167. }
  168. /*!
  169. \brief Check if feature is closed
  170. \param Points pointer to line_pnts structure
  171. \param type feature type (GV_POINT, GV_LINE, ...)
  172. \return 1 feature closed
  173. \return 0 feature not closed
  174. \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
  175. */
  176. int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type, int with_z)
  177. {
  178. int npoints;
  179. if (type & (GV_LINES)) {
  180. npoints = Vect_get_num_line_points(Points);
  181. if (npoints > 2 &&
  182. Points->x[0] == Points->x[npoints-1] &&
  183. Points->y[0] == Points->y[npoints-1]) {
  184. if (!with_z)
  185. return 1;
  186. if (Points->z[0] == Points->z[npoints-1])
  187. return 1;
  188. }
  189. return 0;
  190. }
  191. return -1;
  192. }
  193. int check_sftype(const struct line_pnts *points, int type, int sftype, int with_z)
  194. {
  195. if (type == GV_POINT && sftype == SF_POINT) {
  196. return 1;
  197. }
  198. if (type == GV_LINE) {
  199. if (sftype == SF_LINESTRING) {
  200. return 1;
  201. }
  202. if (sftype == SF_LINE && Vect_get_num_line_points(points) == 2) {
  203. return 1;
  204. }
  205. if (sftype == SF_LINEARRING) {
  206. if (Vect_sfa_is_line_closed(points, type, with_z))
  207. return 1;
  208. }
  209. }
  210. if (type == GV_BOUNDARY) {
  211. if (sftype == SF_POLYGON &&
  212. Vect_sfa_is_line_closed(points, type, 0)) /* force 2D */
  213. return 1;
  214. }
  215. return 0;
  216. }
  217. int get_sftype(const struct line_pnts *points, int type, int with_z)
  218. {
  219. if (check_sftype(points, type, SF_POINT, with_z))
  220. return SF_POINT;
  221. if (check_sftype(points, type, SF_LINE, with_z))
  222. return SF_LINE;
  223. if (check_sftype(points, type, SF_LINEARRING, with_z))
  224. return SF_LINEARRING;
  225. if (check_sftype(points, type, SF_LINESTRING, with_z))
  226. return SF_LINESTRING;
  227. if (check_sftype(points, type, SF_POLYGON, with_z))
  228. return SF_POLYGON;
  229. return -1;
  230. }
  231. void print_point(const struct line_pnts *Points, int index, int with_z, int precision, FILE *file)
  232. {
  233. fprintf(file, "%.*f %.*f", precision, Points->x[index], precision, Points->y[index]);
  234. if (with_z)
  235. fprintf(file, " %.*f", precision, Points->z[index]);
  236. }