read_ogr.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /*!
  2. \file read_ogr.c
  3. \brief Vector library - reading data (OGR format)
  4. Higher level functions for reading/writing/manipulating vectors.
  5. (C) 2001-2009 by the GRASS Development Team
  6. This program is free software under the GNU General Public License
  7. (>=v2). Read the file COPYING that comes with GRASS for details.
  8. \author Radim Blazek, Piero Cavalieri
  9. */
  10. #include <grass/config.h>
  11. #include <grass/gis.h>
  12. #include <grass/vector.h>
  13. #include <grass/glocale.h>
  14. #ifdef HAVE_OGR
  15. #include <ogr_api.h>
  16. /*!
  17. * \brief Recursively read feature and add all elements to points_cache and types_cache.
  18. *
  19. * ftype : if > 0 use this type (because parts of Polygon are read as wkbLineString)
  20. *
  21. * \param Map vector map layer
  22. * \param[out] hGeom OGR geometry
  23. * \param ftype feature type
  24. *
  25. * \return 0 OK
  26. * \return 1 error
  27. */
  28. static int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
  29. {
  30. int line, i, np, ng, tp;
  31. OGRwkbGeometryType type;
  32. OGRGeometryH hGeom2;
  33. G_debug(4, "cache_feature");
  34. /* Alloc space */
  35. line = Map->fInfo.ogr.lines_num;
  36. if (line == Map->fInfo.ogr.lines_alloc) {
  37. Map->fInfo.ogr.lines_alloc += 20;
  38. Map->fInfo.ogr.lines =
  39. (struct line_pnts **)G_realloc((void *)Map->fInfo.ogr.lines,
  40. Map->fInfo.ogr.lines_alloc *
  41. sizeof(struct line_pnts *));
  42. Map->fInfo.ogr.lines_types =
  43. (int *)G_realloc(Map->fInfo.ogr.lines_types,
  44. Map->fInfo.ogr.lines_alloc * sizeof(int));
  45. for (i = Map->fInfo.ogr.lines_num; i < Map->fInfo.ogr.lines_alloc;
  46. i++)
  47. Map->fInfo.ogr.lines[i] = Vect_new_line_struct();
  48. }
  49. Vect_reset_line(Map->fInfo.ogr.lines[line]);
  50. type = wkbFlatten(OGR_G_GetGeometryType(hGeom));
  51. switch (type) {
  52. case wkbPoint:
  53. G_debug(4, "Point");
  54. Vect_append_point(Map->fInfo.ogr.lines[line],
  55. OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
  56. OGR_G_GetZ(hGeom, 0));
  57. Map->fInfo.ogr.lines_types[line] = GV_POINT;
  58. Map->fInfo.ogr.lines_num++;
  59. return 0;
  60. break;
  61. case wkbLineString:
  62. G_debug(4, "LineString");
  63. np = OGR_G_GetPointCount(hGeom);
  64. for (i = 0; i < np; i++) {
  65. Vect_append_point(Map->fInfo.ogr.lines[line],
  66. OGR_G_GetX(hGeom, i), OGR_G_GetY(hGeom, i),
  67. OGR_G_GetZ(hGeom, i));
  68. }
  69. if (ftype > 0) { /* Polygon rings */
  70. Map->fInfo.ogr.lines_types[line] = ftype;
  71. }
  72. else {
  73. Map->fInfo.ogr.lines_types[line] = GV_LINE;
  74. }
  75. Map->fInfo.ogr.lines_num++;
  76. return 0;
  77. break;
  78. case wkbMultiPoint:
  79. case wkbMultiLineString:
  80. case wkbPolygon:
  81. case wkbMultiPolygon:
  82. case wkbGeometryCollection:
  83. ng = OGR_G_GetGeometryCount(hGeom);
  84. G_debug(4, "%d geoms -> next level", ng);
  85. if (type == wkbPolygon) {
  86. tp = GV_BOUNDARY;
  87. }
  88. else {
  89. tp = -1;
  90. }
  91. for (i = 0; i < ng; i++) {
  92. hGeom2 = OGR_G_GetGeometryRef(hGeom, i);
  93. cache_feature(Map, hGeom2, tp);
  94. }
  95. return 0;
  96. break;
  97. default:
  98. G_warning(_("OGR feature type %d not supported"), type);
  99. return 1;
  100. break;
  101. }
  102. }
  103. /*!
  104. * \brief Read next line from OGR layer. Skip empty features.
  105. *
  106. * The action of this routine can be modified by:
  107. * - Vect_read_constraint_region()
  108. * - Vect_read_constraint_type()
  109. * - Vect_remove_constraints()
  110. *
  111. * \param Map vector map layer
  112. * \param[out] line_p container used to store line points within
  113. * \param[out] line_c container used to store line categories within
  114. *
  115. * \return line type
  116. * \return -2 no more features (EOF)
  117. * \return -1 out of memory
  118. */
  119. int
  120. V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  121. struct line_cats *line_c)
  122. {
  123. int itype;
  124. struct bound_box lbox, mbox;
  125. OGRFeatureH hFeature;
  126. OGRGeometryH hGeom;
  127. G_debug(3, "V1_read_next_line_ogr()");
  128. if (line_p != NULL)
  129. Vect_reset_line(line_p);
  130. if (line_c != NULL)
  131. Vect_reset_cats(line_c);
  132. if (Map->Constraint_region_flag)
  133. Vect_get_constraint_box(Map, &mbox);
  134. while (1) {
  135. /* Read feature to cache if necessary */
  136. while (Map->fInfo.ogr.lines_next == Map->fInfo.ogr.lines_num) {
  137. hFeature = OGR_L_GetNextFeature(Map->fInfo.ogr.layer);
  138. if (hFeature == NULL) {
  139. return -2;
  140. } /* no more features */
  141. hGeom = OGR_F_GetGeometryRef(hFeature);
  142. if (hGeom == NULL) { /* feature without geometry */
  143. OGR_F_Destroy(hFeature);
  144. continue;
  145. }
  146. Map->fInfo.ogr.feature_cache_id = (int)OGR_F_GetFID(hFeature);
  147. if (Map->fInfo.ogr.feature_cache_id == OGRNullFID) {
  148. G_warning(_("OGR feature without ID"));
  149. }
  150. /* Cache the feature */
  151. Map->fInfo.ogr.lines_num = 0;
  152. cache_feature(Map, hGeom, -1);
  153. G_debug(4, "%d lines read to cache", Map->fInfo.ogr.lines_num);
  154. OGR_F_Destroy(hFeature);
  155. Map->fInfo.ogr.lines_next = 0; /* next to be read from cache */
  156. }
  157. /* Read next part of the feature */
  158. G_debug(4, "read next cached line %d", Map->fInfo.ogr.lines_next);
  159. itype = Map->fInfo.ogr.lines_types[Map->fInfo.ogr.lines_next];
  160. /* Constraint on Type of line
  161. * Default is all of Point, Line, Area and whatever else comes along
  162. */
  163. if (Map->Constraint_type_flag) {
  164. if (!(itype & Map->Constraint_type)) {
  165. Map->fInfo.ogr.lines_next++;
  166. continue;
  167. }
  168. }
  169. /* Constraint on specified region */
  170. if (Map->Constraint_region_flag) {
  171. Vect_line_box(Map->fInfo.ogr.lines[Map->fInfo.ogr.lines_next],
  172. &lbox);
  173. if (!Vect_box_overlap(&lbox, &mbox)) {
  174. Map->fInfo.ogr.lines_next++;
  175. continue;
  176. }
  177. }
  178. if (line_p != NULL)
  179. Vect_append_points(line_p,
  180. Map->fInfo.ogr.lines[Map->fInfo.ogr.
  181. lines_next], GV_FORWARD);
  182. if (line_c != NULL && Map->fInfo.ogr.feature_cache_id != OGRNullFID)
  183. Vect_cat_set(line_c, 1, Map->fInfo.ogr.feature_cache_id);
  184. Map->fInfo.ogr.lines_next++;
  185. G_debug(4, "next line read, type = %d", itype);
  186. return (itype);
  187. }
  188. return -2; /* not reached */
  189. }
  190. /*!
  191. * \brief Read next line from OGR layer.
  192. *
  193. * \param Map vector map layer
  194. * \param[out] line_p container used to store line points within
  195. * \param[out] line_c container used to store line categories within
  196. *
  197. * \return line type
  198. * \return -2 no more features (EOF)
  199. * \return -1 out of memory
  200. */
  201. int
  202. V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  203. struct line_cats *line_c)
  204. {
  205. if (Map->next_line > Map->plus.n_lines)
  206. return -2;
  207. return V2_read_line_ogr(Map, line_p, line_c, Map->next_line++);
  208. }
  209. /*!
  210. * \brief Recursively descend to feature and read the part
  211. *
  212. * \param Map vector map layer
  213. * \param hGeom OGR geometry
  214. * \param offset given offset
  215. * \param[out] Points container used to store line pointes within
  216. *
  217. * \return 0 OK
  218. * \return 1 error
  219. */
  220. static int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
  221. struct line_pnts *Points)
  222. {
  223. int i, nPoints;
  224. int eType;
  225. OGRGeometryH hGeom2;
  226. /* Read coors if hGeom is a simple element (wkbPoint, wkbLineString) otherwise
  227. * descend to geometry specified by offset[offset] */
  228. G_debug(4, "read_line() offset = %ld", offset);
  229. eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
  230. G_debug(4, "OGR Geometry of type: %d", eType);
  231. switch (eType) {
  232. case wkbPoint:
  233. G_debug(4, "Point");
  234. Vect_append_point(Points, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
  235. OGR_G_GetZ(hGeom, 0));
  236. return 0;
  237. break;
  238. case wkbLineString:
  239. G_debug(4, "LineString");
  240. nPoints = OGR_G_GetPointCount(hGeom);
  241. for (i = 0; i < nPoints; i++) {
  242. Vect_append_point(Points, OGR_G_GetX(hGeom, i),
  243. OGR_G_GetY(hGeom, i), OGR_G_GetZ(hGeom, i));
  244. }
  245. return 0;
  246. break;
  247. case wkbPolygon:
  248. case wkbMultiPoint:
  249. case wkbMultiLineString:
  250. case wkbMultiPolygon:
  251. case wkbGeometryCollection:
  252. G_debug(4, " more geoms -> part %d", Map->fInfo.ogr.offset[offset]);
  253. hGeom2 = OGR_G_GetGeometryRef(hGeom, Map->fInfo.ogr.offset[offset]);
  254. return (read_line(Map, hGeom2, offset + 1, Points));
  255. break;
  256. default:
  257. G_warning(_("OGR feature type %d not supported"), eType);
  258. break;
  259. }
  260. return 1;
  261. }
  262. /*!
  263. * \brief Read line from layer on given offset.
  264. *
  265. * \param Map vector map layer
  266. * \param[out] line_p container used to store line points within
  267. * \param[out] line_c container used to store line categories within
  268. * \param line line id
  269. *
  270. * \return line type
  271. * \return -2 end of table (last row)
  272. * \return -1 out of memory
  273. */
  274. int
  275. V2_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  276. struct line_cats *line_c, int line)
  277. {
  278. int node;
  279. int offset;
  280. long FID;
  281. struct P_line *Line;
  282. struct P_node *Node;
  283. OGRGeometryH hGeom;
  284. G_debug(4, "V2_read_line_ogr() line = %d", line);
  285. if (line_p != NULL)
  286. Vect_reset_line(line_p);
  287. if (line_c != NULL)
  288. Vect_reset_cats(line_c);
  289. Line = Map->plus.Line[line];
  290. offset = (int)Line->offset;
  291. if (Line->type == GV_CENTROID) {
  292. G_debug(4, "Centroid");
  293. node = Line->N1;
  294. Node = Map->plus.Node[node];
  295. /* coordinates */
  296. if (line_p != NULL) {
  297. Vect_append_point(line_p, Node->x, Node->y, 0.0);
  298. }
  299. /* category */
  300. if (line_c != NULL) {
  301. /* cat = FID and offset = FID for centroid */
  302. Vect_cat_set(line_c, 1, (int)offset);
  303. }
  304. return (GV_CENTROID);
  305. }
  306. else {
  307. FID = Map->fInfo.ogr.offset[offset];
  308. G_debug(4, " FID = %ld", FID);
  309. /* coordinates */
  310. if (line_p != NULL) {
  311. /* Read feature to cache if necessary */
  312. if (Map->fInfo.ogr.feature_cache_id != FID) {
  313. G_debug(4, "Read feature (FID = %ld) to cache.", FID);
  314. if (Map->fInfo.ogr.feature_cache) {
  315. OGR_F_Destroy(Map->fInfo.ogr.feature_cache);
  316. }
  317. Map->fInfo.ogr.feature_cache =
  318. OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
  319. if (Map->fInfo.ogr.feature_cache == NULL) {
  320. G_fatal_error(_("Unable to get feature geometry, FID %ld"),
  321. FID);
  322. }
  323. Map->fInfo.ogr.feature_cache_id = FID;
  324. }
  325. hGeom = OGR_F_GetGeometryRef(Map->fInfo.ogr.feature_cache);
  326. if (hGeom == NULL) {
  327. G_fatal_error(_("Unable to get feature geometry, FID %ld"),
  328. FID);
  329. }
  330. read_line(Map, hGeom, Line->offset + 1, line_p);
  331. }
  332. /* category */
  333. if (line_c != NULL) {
  334. Vect_cat_set(line_c, 1, (int)FID);
  335. }
  336. return Line->type;
  337. }
  338. return -2; /* not reached */
  339. }
  340. #endif