read_ogr.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. /*!
  2. \file lib/vector/Vlib/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/vector.h>
  12. #include <grass/glocale.h>
  13. #ifdef HAVE_OGR
  14. #include <ogr_api.h>
  15. /*!
  16. * \brief Recursively read feature and add all elements to points_cache and types_cache.
  17. *
  18. * ftype: if > 0 use this type (because parts of Polygon are read as wkbLineString)
  19. *
  20. * \param Map pointer to Map_info structure
  21. * \param[out] hGeom OGR geometry
  22. * \param ftype feature type
  23. *
  24. * \return 0 on success
  25. * \return 1 on error
  26. */
  27. static int cache_feature(struct Map_info *Map, OGRGeometryH hGeom, int ftype)
  28. {
  29. int line, i, np, ng, tp;
  30. OGRwkbGeometryType type;
  31. OGRGeometryH hGeom2;
  32. G_debug(4, "cache_feature() ftype = %d", ftype);
  33. /* Alloc space */
  34. line = Map->fInfo.ogr.lines_num;
  35. if (line == Map->fInfo.ogr.lines_alloc) {
  36. Map->fInfo.ogr.lines_alloc += 20;
  37. Map->fInfo.ogr.lines =
  38. (struct line_pnts **)G_realloc((void *)Map->fInfo.ogr.lines,
  39. Map->fInfo.ogr.lines_alloc *
  40. sizeof(struct line_pnts *));
  41. Map->fInfo.ogr.lines_types =
  42. (int *)G_realloc(Map->fInfo.ogr.lines_types,
  43. Map->fInfo.ogr.lines_alloc * sizeof(int));
  44. for (i = Map->fInfo.ogr.lines_num; i < Map->fInfo.ogr.lines_alloc; i++)
  45. Map->fInfo.ogr.lines[i] = Vect_new_line_struct();
  46. }
  47. Vect_reset_line(Map->fInfo.ogr.lines[line]);
  48. type = wkbFlatten(OGR_G_GetGeometryType(hGeom));
  49. switch (type) {
  50. case wkbPoint:
  51. G_debug(4, "Point");
  52. Vect_append_point(Map->fInfo.ogr.lines[line],
  53. OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
  54. OGR_G_GetZ(hGeom, 0));
  55. Map->fInfo.ogr.lines_types[line] = GV_POINT;
  56. Map->fInfo.ogr.lines_num++;
  57. return 0;
  58. break;
  59. case wkbLineString:
  60. G_debug(4, "LineString");
  61. np = OGR_G_GetPointCount(hGeom);
  62. for (i = 0; i < np; i++) {
  63. Vect_append_point(Map->fInfo.ogr.lines[line],
  64. OGR_G_GetX(hGeom, i), OGR_G_GetY(hGeom, i),
  65. OGR_G_GetZ(hGeom, i));
  66. }
  67. if (ftype > 0) { /* Polygon rings */
  68. Map->fInfo.ogr.lines_types[line] = ftype;
  69. }
  70. else {
  71. Map->fInfo.ogr.lines_types[line] = GV_LINE;
  72. }
  73. Map->fInfo.ogr.lines_num++;
  74. return 0;
  75. break;
  76. case wkbMultiPoint:
  77. case wkbMultiLineString:
  78. case wkbPolygon:
  79. case wkbMultiPolygon:
  80. case wkbGeometryCollection:
  81. ng = OGR_G_GetGeometryCount(hGeom);
  82. G_debug(4, "%d geoms -> next level", ng);
  83. if (type == wkbPolygon) {
  84. tp = GV_BOUNDARY;
  85. }
  86. else {
  87. tp = -1;
  88. }
  89. for (i = 0; i < ng; i++) {
  90. hGeom2 = OGR_G_GetGeometryRef(hGeom, i);
  91. cache_feature(Map, hGeom2, tp);
  92. }
  93. return 0;
  94. break;
  95. default:
  96. G_warning(_("OGR feature type %d not supported"), type);
  97. return 1;
  98. break;
  99. }
  100. }
  101. /*!
  102. * \brief Read next feature from OGR layer. Skip empty features. (level 1)
  103. *
  104. * The action of this routine can be modified by:
  105. * - Vect_read_constraint_region()
  106. * - Vect_read_constraint_type()
  107. * - Vect_remove_constraints()
  108. *
  109. * \param Map pointer to Map_info structure
  110. * \param[out] line_p container used to store line points within
  111. * \param[out] line_c container used to store line categories within
  112. *
  113. * \return feature type
  114. * \return -2 no more features (EOF)
  115. * \return -1 out of memory
  116. */
  117. int V1_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  118. struct line_cats *line_c)
  119. {
  120. int itype;
  121. struct bound_box lbox, mbox;
  122. OGRFeatureH hFeature;
  123. OGRGeometryH hGeom;
  124. G_debug(3, "V1_read_next_line_ogr()");
  125. if (line_p != NULL)
  126. Vect_reset_line(line_p);
  127. if (line_c != NULL)
  128. Vect_reset_cats(line_c);
  129. if (Map->Constraint_region_flag)
  130. Vect_get_constraint_box(Map, &mbox);
  131. while (1) {
  132. /* Read feature to cache if necessary */
  133. while (Map->fInfo.ogr.lines_next == Map->fInfo.ogr.lines_num) {
  134. hFeature = OGR_L_GetNextFeature(Map->fInfo.ogr.layer);
  135. if (hFeature == NULL) {
  136. return -2;
  137. } /* no more features */
  138. hGeom = OGR_F_GetGeometryRef(hFeature);
  139. if (hGeom == NULL) { /* feature without geometry */
  140. OGR_F_Destroy(hFeature);
  141. continue;
  142. }
  143. Map->fInfo.ogr.feature_cache_id = (int)OGR_F_GetFID(hFeature);
  144. if (Map->fInfo.ogr.feature_cache_id == OGRNullFID) {
  145. G_warning(_("OGR feature without ID"));
  146. }
  147. /* Cache the feature */
  148. Map->fInfo.ogr.lines_num = 0;
  149. cache_feature(Map, hGeom, -1);
  150. G_debug(4, "%d lines read to cache", Map->fInfo.ogr.lines_num);
  151. OGR_F_Destroy(hFeature);
  152. Map->fInfo.ogr.lines_next = 0; /* next to be read from cache */
  153. }
  154. /* Read next part of the feature */
  155. G_debug(4, "read next cached line %d", Map->fInfo.ogr.lines_next);
  156. itype = Map->fInfo.ogr.lines_types[Map->fInfo.ogr.lines_next];
  157. /* Constraint on Type of line
  158. * Default is all of Point, Line, Area and whatever else comes along
  159. */
  160. if (Map->Constraint_type_flag) {
  161. if (!(itype & Map->Constraint_type)) {
  162. Map->fInfo.ogr.lines_next++;
  163. continue;
  164. }
  165. }
  166. /* Constraint on specified region */
  167. if (Map->Constraint_region_flag) {
  168. Vect_line_box(Map->fInfo.ogr.lines[Map->fInfo.ogr.lines_next],
  169. &lbox);
  170. if (!Vect_box_overlap(&lbox, &mbox)) {
  171. Map->fInfo.ogr.lines_next++;
  172. continue;
  173. }
  174. }
  175. if (line_p != NULL)
  176. Vect_append_points(line_p,
  177. Map->fInfo.ogr.lines[Map->fInfo.ogr.
  178. lines_next], GV_FORWARD);
  179. if (line_c != NULL && Map->fInfo.ogr.feature_cache_id != OGRNullFID)
  180. Vect_cat_set(line_c, 1, Map->fInfo.ogr.feature_cache_id);
  181. Map->fInfo.ogr.lines_next++;
  182. G_debug(4, "next line read, type = %d", itype);
  183. return itype;
  184. }
  185. return -2; /* not reached */
  186. }
  187. /*!
  188. * \brief Read next feature from OGR layer (topology level).
  189. *
  190. * \param Map pointer to Map_info structure
  191. * \param[out] line_p container used to store line points within
  192. * \param[out] line_c container used to store line categories within
  193. *
  194. * \return feature type
  195. * \return -2 no more features (EOF)
  196. * \return -1 out of memory
  197. */
  198. int
  199. V2_read_next_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  200. struct line_cats *line_c)
  201. {
  202. if (Map->next_line > Map->plus.n_lines)
  203. return -2;
  204. return V2_read_line_ogr(Map, line_p, line_c, Map->next_line++);
  205. }
  206. /*!
  207. * \brief Recursively descend to feature and read the part
  208. *
  209. * \param Map pointer to Map_info structure
  210. * \param hGeom OGR geometry
  211. * \param offset given offset
  212. * \param[out] Points container used to store line pointes within
  213. *
  214. * \return feature type
  215. * \return -1 on error
  216. */
  217. static int read_line(const struct Map_info *Map, OGRGeometryH hGeom, long offset,
  218. struct line_pnts *Points)
  219. {
  220. int i, nPoints;
  221. int eType;
  222. OGRGeometryH hGeom2;
  223. /* Read coors if hGeom is a simple element (wkbPoint, wkbLineString) otherwise
  224. * descend to geometry specified by offset[offset] */
  225. G_debug(4, "read_line() offset = %ld", offset);
  226. eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
  227. G_debug(4, "OGR Geometry of type: %d", eType);
  228. switch (eType) {
  229. case wkbPoint:
  230. G_debug(4, "Point");
  231. if (Points) {
  232. Vect_append_point(Points, OGR_G_GetX(hGeom, 0), OGR_G_GetY(hGeom, 0),
  233. OGR_G_GetZ(hGeom, 0));
  234. }
  235. return GV_POINT;
  236. break;
  237. case wkbLineString:
  238. G_debug(4, "LineString");
  239. if (Points) {
  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. }
  246. return GV_LINE;
  247. break;
  248. case wkbPolygon:
  249. case wkbMultiPoint:
  250. case wkbMultiLineString:
  251. case wkbMultiPolygon:
  252. case wkbGeometryCollection:
  253. G_debug(4, " more geoms -> part %d", Map->fInfo.ogr.offset[offset]);
  254. hGeom2 = OGR_G_GetGeometryRef(hGeom, Map->fInfo.ogr.offset[offset]);
  255. return (read_line(Map, hGeom2, offset + 1, Points));
  256. break;
  257. default:
  258. G_warning(_("OGR feature type %d not supported"), eType);
  259. break;
  260. }
  261. return -1;
  262. }
  263. /*!
  264. * \brief Recursively descend to feature and read the part
  265. *
  266. * \param Map pointer to Map_info structure
  267. * \param hGeom OGR geometry
  268. * \param offset given offset
  269. * \param[out] Points container used to store line pointes within
  270. *
  271. * \return feature type
  272. * \return -1 on error
  273. */
  274. static int get_line_type(const struct Map_info *Map, long FID)
  275. {
  276. int eType;
  277. OGRFeatureH hFeat;
  278. OGRGeometryH hGeom;
  279. G_debug(4, "get_line_type() fid = %ld", FID);
  280. hFeat = OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
  281. if (hFeat == NULL)
  282. return -1;
  283. hGeom = OGR_F_GetGeometryRef(hFeat);
  284. if (hGeom == NULL)
  285. return -1;
  286. eType = wkbFlatten(OGR_G_GetGeometryType(hGeom));
  287. OGR_F_Destroy(hFeat);
  288. G_debug(4, "OGR Geometry of type: %d", eType);
  289. switch (eType) {
  290. case wkbPoint:
  291. case wkbMultiPoint:
  292. return GV_POINT;
  293. break;
  294. case wkbLineString:
  295. case wkbMultiLineString:
  296. return GV_LINE;
  297. break;
  298. case wkbPolygon:
  299. case wkbMultiPolygon:
  300. case wkbGeometryCollection:
  301. return GV_BOUNDARY;
  302. break;
  303. default:
  304. G_warning(_("OGR feature type %d not supported"), eType);
  305. break;
  306. }
  307. return -1;
  308. }
  309. /*!
  310. * \brief Read feature from OGR layer at given offset (level 1)
  311. *
  312. * \param Map pointer to Map_info structure
  313. * \param[out] line_p container used to store line points within
  314. * \param[out] line_c container used to store line categories within
  315. * \param offset given offset
  316. *
  317. * \return line type
  318. * \return 0 dead line
  319. * \return -2 no more features
  320. * \return -1 out of memory
  321. */
  322. int V1_read_line_ogr(struct Map_info *Map,
  323. struct line_pnts *line_p, struct line_cats *line_c, off_t offset)
  324. {
  325. long FID;
  326. int type;
  327. OGRGeometryH hGeom;
  328. G_debug(4, "V1_read_line_ogr() offset = %lu", (long) offset);
  329. if (offset >= Map->fInfo.ogr.offset_num)
  330. return -2;
  331. if (line_p != NULL)
  332. Vect_reset_line(line_p);
  333. if (line_c != NULL)
  334. Vect_reset_cats(line_c);
  335. FID = Map->fInfo.ogr.offset[offset];
  336. G_debug(4, " FID = %ld", FID);
  337. /* coordinates */
  338. if (line_p != NULL) {
  339. /* Read feature to cache if necessary */
  340. if (Map->fInfo.ogr.feature_cache_id != FID) {
  341. G_debug(4, "Read feature (FID = %ld) to cache.", FID);
  342. if (Map->fInfo.ogr.feature_cache) {
  343. OGR_F_Destroy(Map->fInfo.ogr.feature_cache);
  344. }
  345. Map->fInfo.ogr.feature_cache =
  346. OGR_L_GetFeature(Map->fInfo.ogr.layer, FID);
  347. if (Map->fInfo.ogr.feature_cache == NULL) {
  348. G_fatal_error(_("Unable to get feature geometry, FID %ld"),
  349. FID);
  350. }
  351. Map->fInfo.ogr.feature_cache_id = FID;
  352. }
  353. hGeom = OGR_F_GetGeometryRef(Map->fInfo.ogr.feature_cache);
  354. if (hGeom == NULL) {
  355. G_fatal_error(_("Unable to get feature geometry, FID %ld"),
  356. FID);
  357. }
  358. type = read_line(Map, hGeom, offset + 1, line_p);
  359. }
  360. else {
  361. type = get_line_type(Map, FID);
  362. }
  363. /* category */
  364. if (line_c != NULL) {
  365. Vect_cat_set(line_c, 1, (int) FID);
  366. }
  367. return type;
  368. }
  369. /*!
  370. * \brief Reads feature from OGR layer (topology level)
  371. *
  372. * \param Map pointer to Map_info structure
  373. * \param[out] line_p container used to store line points within
  374. * \param[out] line_c container used to store line categories within
  375. * \param line feature id
  376. *
  377. * \return feature type
  378. * \return -2 no more features
  379. * \return -1 out of memory
  380. */
  381. int V2_read_line_ogr(struct Map_info *Map, struct line_pnts *line_p,
  382. struct line_cats *line_c, int line)
  383. {
  384. struct P_line *Line;
  385. G_debug(4, "V2_read_line_ogr() line = %d", line);
  386. Line = Map->plus.Line[line];
  387. if (Line == NULL)
  388. G_fatal_error("V2_read_line_ogr(): %s %d",
  389. _("Attempt to read dead line"), line);
  390. if (Line->type == GV_CENTROID) {
  391. G_debug(4, "Centroid");
  392. if (line_p != NULL) {
  393. int i, found;
  394. struct bound_box box;
  395. struct boxlist list;
  396. struct P_topo_c *topo = (struct P_topo_c *)Line->topo;
  397. /* get area bbox */
  398. Vect_get_area_box(Map, topo->area, &box);
  399. /* search in spatial index for centroid with area bbox */
  400. dig_init_boxlist(&list, 1);
  401. Vect_select_lines_by_box(Map, &box, Line->type, &list);
  402. found = 0;
  403. for (i = 0; i < list.n_values; i++) {
  404. if (list.id[i] == line) {
  405. found = i;
  406. break;
  407. }
  408. }
  409. Vect_append_point(line_p, list.box[found].E, list.box[found].N, 0.0);
  410. }
  411. if (line_c != NULL) {
  412. /* cat = FID and offset = FID for centroid */
  413. Vect_cat_set(line_c, 1, (int) Line->offset);
  414. }
  415. return GV_CENTROID;
  416. }
  417. return V1_read_line_ogr(Map, line_p, line_c, Line->offset);
  418. }
  419. #endif