read_ogr.c 14 KB

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