read_ogr.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. /*!
  2. \file lib/vector/Vlib/read_ogr.c
  3. \brief Vector library - reading data (OGR format)
  4. Higher level functions for reading/writing/manipulating vectors.
  5. (C) 2001-2010 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. \author Martin Landa <landa.martin gmail.com>
  10. */
  11. #include <grass/config.h>
  12. #include <grass/gis.h>
  13. #include <grass/vector.h>
  14. #include <grass/glocale.h>
  15. #ifdef HAVE_OGR
  16. #include <ogr_api.h>
  17. /*!
  18. * \brief Recursively read feature and add all elements to points_cache and types_cache.
  19. *
  20. * ftype: if > 0 use this type (because parts of Polygon are read as wkbLineString)
  21. *
  22. * \param Map pointer to Map_info structure
  23. * \param[out] hGeom OGR geometry
  24. * \param ftype feature type
  25. *
  26. * \return 0 on success
  27. * \return 1 on error
  28. */
  29. static int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
  30. {
  31. int line, i, np, ng, tp;
  32. OGRwkbGeometryType type;
  33. OGRGeometryH hGeom2;
  34. G_debug(4, "cache_feature() ftype = %d", ftype);
  35. /* Alloc space */
  36. line = Map->fInfo.ogr.lines_num;
  37. if (line == Map->fInfo.ogr.lines_alloc) {
  38. Map->fInfo.ogr.lines_alloc += 20;
  39. Map->fInfo.ogr.lines =
  40. (struct line_pnts **)G_realloc((void *)Map->fInfo.ogr.lines,
  41. Map->fInfo.ogr.lines_alloc *
  42. sizeof(struct line_pnts *));
  43. Map->fInfo.ogr.lines_types =
  44. (int *)G_realloc(Map->fInfo.ogr.lines_types,
  45. Map->fInfo.ogr.lines_alloc * sizeof(int));
  46. for (i = Map->fInfo.ogr.lines_num; i < Map->fInfo.ogr.lines_alloc; 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 feature from OGR layer. Skip empty features. (level 1)
  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 pointer to Map_info structure
  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 feature type
  116. * \return -2 no more features (EOF)
  117. * \return -1 out of memory
  118. */
  119. int V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  120. struct line_cats *line_c)
  121. {
  122. int itype;
  123. struct bound_box lbox, mbox;
  124. OGRFeatureH hFeature;
  125. OGRGeometryH hGeom;
  126. G_debug(3, "V1_read_next_line_ogr()");
  127. if (line_p != NULL)
  128. Vect_reset_line(line_p);
  129. if (line_c != NULL)
  130. Vect_reset_cats(line_c);
  131. if (Map->Constraint_region_flag)
  132. Vect_get_constraint_box(Map, &mbox);
  133. while (1) {
  134. /* Read feature to cache if necessary */
  135. while (Map->fInfo.ogr.lines_next == Map->fInfo.ogr.lines_num) {
  136. hFeature = OGR_L_GetNextFeature(Map->fInfo.ogr.layer);
  137. if (hFeature == NULL) {
  138. return -2;
  139. } /* no more features */
  140. hGeom = OGR_F_GetGeometryRef(hFeature);
  141. if (hGeom == NULL) { /* feature without geometry */
  142. OGR_F_Destroy(hFeature);
  143. continue;
  144. }
  145. Map->fInfo.ogr.feature_cache_id = (int)OGR_F_GetFID(hFeature);
  146. if (Map->fInfo.ogr.feature_cache_id == OGRNullFID) {
  147. G_warning(_("OGR feature without ID"));
  148. }
  149. /* Cache the feature */
  150. Map->fInfo.ogr.lines_num = 0;
  151. cache_feature(Map, hGeom, -1);
  152. G_debug(4, "%d lines read to cache", Map->fInfo.ogr.lines_num);
  153. OGR_F_Destroy(hFeature);
  154. Map->fInfo.ogr.lines_next = 0; /* next to be read from cache */
  155. }
  156. /* Read next part of the feature */
  157. G_debug(4, "read next cached line %d", Map->fInfo.ogr.lines_next);
  158. itype = Map->fInfo.ogr.lines_types[Map->fInfo.ogr.lines_next];
  159. /* Constraint on Type of line
  160. * Default is all of Point, Line, Area and whatever else comes along
  161. */
  162. if (Map->Constraint_type_flag) {
  163. if (!(itype & Map->Constraint_type)) {
  164. Map->fInfo.ogr.lines_next++;
  165. continue;
  166. }
  167. }
  168. /* Constraint on specified region */
  169. if (Map->Constraint_region_flag) {
  170. Vect_line_box(Map->fInfo.ogr.lines[Map->fInfo.ogr.lines_next],
  171. &lbox);
  172. if (!Vect_box_overlap(&lbox, &mbox)) {
  173. Map->fInfo.ogr.lines_next++;
  174. continue;
  175. }
  176. }
  177. if (line_p != NULL)
  178. Vect_append_points(line_p,
  179. Map->fInfo.ogr.lines[Map->fInfo.ogr.
  180. lines_next], GV_FORWARD);
  181. if (line_c != NULL && Map->fInfo.ogr.feature_cache_id != OGRNullFID)
  182. Vect_cat_set(line_c, 1, Map->fInfo.ogr.feature_cache_id);
  183. Map->fInfo.ogr.lines_next++;
  184. G_debug(4, "next line read, type = %d", itype);
  185. return itype;
  186. }
  187. return -2; /* not reached */
  188. }
  189. /*!
  190. * \brief Read next feature from OGR layer (topology level).
  191. *
  192. * \param Map pointer to Map_info structure
  193. * \param[out] line_p container used to store line points within
  194. * \param[out] line_c container used to store line categories within
  195. *
  196. * \return feature type
  197. * \return -2 no more features (EOF)
  198. * \return -1 out of memory
  199. */
  200. int
  201. V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  202. struct line_cats *line_c)
  203. {
  204. if (Map->next_line > Map->plus.n_lines)
  205. return -2;
  206. return V2_read_line_ogr(Map, line_p, line_c, Map->next_line++);
  207. }
  208. /*!
  209. * \brief Recursively descend to feature and read the part
  210. *
  211. * \param Map pointer to Map_info structure
  212. * \param hGeom OGR geometry
  213. * \param offset given offset
  214. * \param[out] Points container used to store line pointes within
  215. *
  216. * \return feature type
  217. * \return -1 on error
  218. */
  219. static int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
  220. struct line_pnts *Points)
  221. {
  222. int i, nPoints;
  223. int eType;
  224. OGRGeometryH hGeom2;
  225. /* Read coors if hGeom is a simple element (wkbPoint, wkbLineString) otherwise
  226. * descend to geometry specified by offset[offset] */
  227. G_debug(4, "read_line() offset = %ld", offset);
  228. eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
  229. G_debug(4, "OGR Geometry of type: %d", eType);
  230. switch (eType) {
  231. case wkbPoint:
  232. G_debug(4, "Point");
  233. if (Points) {
  234. Vect_append_point(Points, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
  235. OGR_G_GetZ(hGeom, 0));
  236. }
  237. return GV_POINT;
  238. break;
  239. case wkbLineString:
  240. G_debug(4, "LineString");
  241. if (Points) {
  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. }
  248. return GV_LINE;
  249. break;
  250. case wkbPolygon:
  251. case wkbMultiPoint:
  252. case wkbMultiLineString:
  253. case wkbMultiPolygon:
  254. case wkbGeometryCollection:
  255. G_debug(4, " more geoms -> part %d", Map->fInfo.ogr.offset[offset]);
  256. hGeom2 = OGR_G_GetGeometryRef(hGeom, Map->fInfo.ogr.offset[offset]);
  257. return (read_line(Map, hGeom2, offset + 1, Points));
  258. break;
  259. default:
  260. G_warning(_("OGR feature type %d not supported"), eType);
  261. break;
  262. }
  263. return -1;
  264. }
  265. /*!
  266. * \brief Recursively descend to feature and read the part
  267. *
  268. * \param Map pointer to Map_info structure
  269. * \param hGeom OGR geometry
  270. * \param offset given offset
  271. * \param[out] Points container used to store line pointes within
  272. *
  273. * \return feature type
  274. * \return -1 on error
  275. */
  276. static int get_line_type(const struct Map_info *Map, long FID)
  277. {
  278. int eType;
  279. OGRFeatureH hFeat;
  280. OGRGeometryH hGeom;
  281. G_debug(4, "get_line_type() fid = %ld", FID);
  282. hFeat = OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
  283. if (hFeat == NULL)
  284. return -1;
  285. hGeom = OGR_F_GetGeometryRef(hFeat);
  286. if (hGeom == NULL)
  287. return -1;
  288. eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
  289. OGR_F_Destroy(hFeat);
  290. G_debug(4, "OGR Geometry of type: %d", eType);
  291. switch (eType) {
  292. case wkbPoint:
  293. case wkbMultiPoint:
  294. return GV_POINT;
  295. break;
  296. case wkbLineString:
  297. case wkbMultiLineString:
  298. return GV_LINE;
  299. break;
  300. case wkbPolygon:
  301. case wkbMultiPolygon:
  302. case wkbGeometryCollection:
  303. return GV_BOUNDARY;
  304. break;
  305. default:
  306. G_warning(_("OGR feature type %d not supported"), eType);
  307. break;
  308. }
  309. return -1;
  310. }
  311. /*!
  312. * \brief Read feature from OGR layer at given offset (level 1)
  313. *
  314. * \param Map pointer to Map_info structure
  315. * \param[out] line_p container used to store line points within
  316. * \param[out] line_c container used to store line categories within
  317. * \param offset given offset
  318. *
  319. * \return line type
  320. * \return 0 dead line
  321. * \return -2 no more features
  322. * \return -1 out of memory
  323. */
  324. int V1_read_line_ogr(struct Map_info *Map,
  325. struct line_pnts *line_p, struct line_cats *line_c, off_t offset)
  326. {
  327. long FID;
  328. int type;
  329. OGRGeometryH hGeom;
  330. G_debug(4, "V1_read_line_ogr() offset = %lu", (long) offset);
  331. if (offset >= Map->fInfo.ogr.offset_num)
  332. return -2;
  333. if (line_p != NULL)
  334. Vect_reset_line(line_p);
  335. if (line_c != NULL)
  336. Vect_reset_cats(line_c);
  337. FID = Map->fInfo.ogr.offset[offset];
  338. G_debug(4, " FID = %ld", FID);
  339. /* coordinates */
  340. if (line_p != NULL) {
  341. /* Read feature to cache if necessary */
  342. if (Map->fInfo.ogr.feature_cache_id != FID) {
  343. G_debug(4, "Read feature (FID = %ld) to cache.", FID);
  344. if (Map->fInfo.ogr.feature_cache) {
  345. OGR_F_Destroy(Map->fInfo.ogr.feature_cache);
  346. }
  347. Map->fInfo.ogr.feature_cache =
  348. OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
  349. if (Map->fInfo.ogr.feature_cache == NULL) {
  350. G_fatal_error(_("Unable to get feature geometry, FID %ld"),
  351. FID);
  352. }
  353. Map->fInfo.ogr.feature_cache_id = FID;
  354. }
  355. hGeom = OGR_F_GetGeometryRef(Map->fInfo.ogr.feature_cache);
  356. if (hGeom == NULL) {
  357. G_fatal_error(_("Unable to get feature geometry, FID %ld"),
  358. FID);
  359. }
  360. type = read_line(Map, hGeom, offset + 1, line_p);
  361. }
  362. else {
  363. type = get_line_type(Map, FID);
  364. }
  365. /* category */
  366. if (line_c != NULL) {
  367. Vect_cat_set(line_c, 1, (int) FID);
  368. }
  369. return type;
  370. }
  371. /*!
  372. * \brief Reads feature from OGR layer (topology level)
  373. *
  374. * \param Map pointer to Map_info structure
  375. * \param[out] line_p container used to store line points within
  376. * \param[out] line_c container used to store line categories within
  377. * \param line feature id
  378. *
  379. * \return feature type
  380. * \return -2 no more features
  381. * \return -1 out of memory
  382. */
  383. int V2_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  384. struct line_cats *line_c, int line)
  385. {
  386. struct P_line *Line;
  387. G_debug(4, "V2_read_line_ogr() line = %d", line);
  388. Line = Map->plus.Line[line];
  389. if (Line == NULL)
  390. G_fatal_error("V2_read_line_ogr(): %s %d",
  391. _("Attempt to read dead line"), line);
  392. if (Line->type == GV_CENTROID) {
  393. plus_t node;
  394. struct P_node *Node;
  395. G_debug(4, "Centroid");
  396. node = Line->N1;
  397. Node = Map->plus.Node[node];
  398. if (line_p != NULL) {
  399. Vect_append_point(line_p, Node->x, Node->y, 0.0);
  400. }
  401. if (line_c != NULL) {
  402. /* cat = FID and offset = FID for centroid */
  403. Vect_cat_set(line_c, 1, (int) Line->offset);
  404. }
  405. return GV_CENTROID;
  406. }
  407. return V1_read_line_ogr(Map, line_p, line_c, Line->offset);
  408. }
  409. #endif