simple_features.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*!
  2. \file vector/Vlib/simple_features.c
  3. \brief Vector library - OGC Simple Features Access
  4. Note: In progress. Currently on GV_POINT, GV_LINE are supported.
  5. Higher level functions for reading/writing/manipulating vectors.
  6. (C) 2009 by the GRASS Development Team
  7. This program is free software under the GNU General Public License
  8. (>=v2). Read the file COPYING that comes with GRASS for details.
  9. \author Martin Landa <landa.martin gmail.com>
  10. */
  11. #include <stdio.h>
  12. #include <grass/vector.h>
  13. #include <grass/glocale.h>
  14. static int check_sftype(const struct line_pnts *, int, int, int);
  15. static int get_sftype(const struct line_pnts *, int, int);
  16. static void print_point(const struct line_pnts *, int, int, int, FILE *);
  17. /*!
  18. \brief Get SF type of given vector feature
  19. List of supported feature types:
  20. - GV_POINT -> SF_POINT
  21. - GV_LINE -> SF_LINE / SF_LINESTRING / SF_LINEARRING
  22. \param Points pointer to line_pnts structure
  23. \param type feature type (GV_POINT, GV_LINE, ...)
  24. \param with_z non-zero value for 3D data
  25. \return SF type identificator (see list of supported types)
  26. \return -1 on error
  27. */
  28. int Vect_sfa_get_line_type(const struct line_pnts *Points, int type, int with_z)
  29. {
  30. return get_sftype(Points, type, with_z);
  31. }
  32. /*!
  33. \brief Check SF type
  34. E.g. if <em>type</em> is GV_LINE with two or more segments and the
  35. start node is identical with the end node, and <em>sftype</em> is
  36. SF_LINEARRING, functions returns 1, otherwise 0.
  37. \param Points pointer to line_pnts structure
  38. \param type feature type (GV_POINT, GV_LINE, ...)
  39. \param sftype SF type to be checked (SF_POINT, SF_LINE, ...)
  40. \param with_z non-zero value for 3D data
  41. \return 1 if type is sftype
  42. \return 0 type differs from sftype
  43. */
  44. int Vect_sfa_check_line_type(const struct line_pnts *Points, int type, int sftype, int with_z)
  45. {
  46. return check_sftype(Points, type, sftype, with_z);
  47. }
  48. /*!
  49. \brief Print feature in Well-Known Text format
  50. \param Points pointer to line_pnts structure
  51. \param type feature type
  52. \param with_z non-zero value for 3D data
  53. \param precision floating number precision
  54. \param[out] file file where to write the output
  55. */
  56. void Vect_sfa_write_line_wkt(const struct line_pnts *Points, int type, int with_z, int precision, FILE *file)
  57. {
  58. int i, sftype;
  59. sftype = Vect_sfa_get_line_type(Points, type, with_z);
  60. switch(sftype) {
  61. case SF_POINT: {
  62. fprintf(file, "POINT(");
  63. print_point(Points, 0, with_z, precision, file);
  64. fprintf(file, ")\n");
  65. break;
  66. }
  67. case SF_LINESTRING: case SF_LINE: case SF_LINEARRING: {
  68. if (sftype == SF_LINESTRING)
  69. fprintf(file, "LINESTRING(");
  70. else if (sftype == SF_LINE)
  71. fprintf(file, "LINE(");
  72. else
  73. fprintf(file, "LINEARRING(");
  74. for (i = 0; i < Points->n_points; i++) {
  75. print_point(Points, i, with_z, precision, file);
  76. if (i < Points->n_points - 1)
  77. fprintf(file, ", ");
  78. }
  79. fprintf(file, ")\n");
  80. break;
  81. }
  82. case SF_POLYGON: {
  83. /* write only outter/inner ring */
  84. fprintf(file, "(");
  85. for (i = 0; i < Points->n_points; i++) {
  86. print_point(Points, i, with_z, precision, file);
  87. if (i < Points->n_points - 1)
  88. fprintf(file, ", ");
  89. }
  90. fprintf(file, ")");
  91. break;
  92. }
  93. default: {
  94. G_warning(_("Unknown Simple Features type (%d)"), sftype);
  95. break;
  96. }
  97. }
  98. fflush(file);
  99. }
  100. /*!
  101. \brief Check if feature is closed
  102. \param Points pointer to line_pnts structure
  103. \param type feature type (GV_POINT, GV_LINE, ...)
  104. \return 1 feature closed
  105. \return 0 feature not closed
  106. \return -1 feature type not supported (GV_POINT, GV_CENTROID, ...)
  107. */
  108. int Vect_sfa_is_line_closed(const struct line_pnts *Points, int type, int with_z)
  109. {
  110. int npoints;
  111. if (type & (GV_LINES)) {
  112. npoints = Vect_get_num_line_points(Points);
  113. if (npoints > 2 &&
  114. Points->x[0] == Points->x[npoints-1] &&
  115. Points->y[0] == Points->y[npoints-1]) {
  116. if (!with_z)
  117. return 1;
  118. if (Points->z[0] == Points->z[npoints-1])
  119. return 1;
  120. }
  121. return 0;
  122. }
  123. return -1;
  124. }
  125. int check_sftype(const struct line_pnts *points, int type, int sftype, int with_z)
  126. {
  127. if (type == GV_POINT && sftype == SF_POINT) {
  128. return 1;
  129. }
  130. if (type == GV_LINE) {
  131. if (sftype == SF_LINESTRING) {
  132. return 1;
  133. }
  134. if (sftype == SF_LINE && Vect_get_num_line_points(points) == 2) {
  135. return 1;
  136. }
  137. if (sftype == SF_LINEARRING) {
  138. if (Vect_sfa_is_line_closed(points, type, with_z))
  139. return 1;
  140. }
  141. }
  142. if (type == GV_BOUNDARY) {
  143. if (sftype == SF_POLYGON &&
  144. Vect_sfa_is_line_closed(points, type, 0)) /* force 2D */
  145. return 1;
  146. }
  147. return 0;
  148. }
  149. int get_sftype(const struct line_pnts *points, int type, int with_z)
  150. {
  151. if (check_sftype(points, type, SF_POINT, with_z))
  152. return SF_POINT;
  153. if (check_sftype(points, type, SF_LINE, with_z))
  154. return SF_LINE;
  155. if (check_sftype(points, type, SF_LINEARRING, with_z))
  156. return SF_LINEARRING;
  157. if (check_sftype(points, type, SF_LINESTRING, with_z))
  158. return SF_LINESTRING;
  159. if (check_sftype(points, type, SF_POLYGON, with_z))
  160. return SF_POLYGON;
  161. return -1;
  162. }
  163. void print_point(const struct line_pnts *Points, int index, int with_z, int precision, FILE *file)
  164. {
  165. fprintf(file, "%.*f %.*f", precision, Points->x[index], precision, Points->y[index]);
  166. if (with_z)
  167. fprintf(file, " %.*f", precision, Points->z[index]);
  168. }