read_ogr.c 9.9 KB

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