open_ogr.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*!
  2. \file lib/vector/Vlib/open_ogr.c
  3. \brief Vector library - Open OGR layer as vector map layer
  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 Original author CERL, probably Dave Gerdes or Mike Higgins.
  9. \author Update to GRASS 5.7 Radim Blazek and David D. Gray.
  10. \author Update to GRASS 7.0 Martin Landa <landa.martin gmail.com> (2009)
  11. */
  12. #include <unistd.h>
  13. #include <string.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <grass/vector.h>
  17. #include <grass/dbmi.h>
  18. #include <grass/glocale.h>
  19. #ifdef HAVE_OGR
  20. #include <ogr_api.h>
  21. #endif
  22. /*!
  23. \brief Open existing OGR layer on non-topological level
  24. Note: Map->name, Map->mapset, Map->fInfo.ogr.dsn and
  25. Map->fInfo.ogr.layer_name must be set before.
  26. \param[in,out] Map pointer to Map_info structure
  27. \param update TRUE for write mode, otherwise read-only
  28. \return 0 success
  29. \return -1 error
  30. */
  31. int V1_open_old_ogr(struct Map_info *Map, int update)
  32. {
  33. #ifdef HAVE_OGR
  34. int i, layer, nLayers;
  35. struct Format_info_ogr *ogr_info;
  36. OGRDataSourceH Ogr_ds;
  37. OGRLayerH Ogr_layer;
  38. OGRFeatureDefnH Ogr_featuredefn;
  39. OGRwkbGeometryType Ogr_geom_type;
  40. Ogr_layer = NULL;
  41. Ogr_geom_type = wkbUnknown;
  42. ogr_info = &(Map->fInfo.ogr);
  43. if (!ogr_info->dsn) {
  44. G_fatal_error(_("OGR datasource not defined"));
  45. return -1;
  46. }
  47. if (!ogr_info->layer_name) {
  48. G_fatal_error(_("OGR layer not defined"));
  49. return -1;
  50. }
  51. G_debug(2, "V1_open_old_ogr(): dsn = %s layer = %s", ogr_info->dsn,
  52. ogr_info->layer_name);
  53. OGRRegisterAll();
  54. /* open data source handle */
  55. Ogr_ds = OGROpen(ogr_info->dsn, FALSE, NULL);
  56. if (Ogr_ds == NULL)
  57. G_fatal_error(_("Unable to open OGR data source '%s'"),
  58. ogr_info->dsn);
  59. ogr_info->ds = Ogr_ds;
  60. /* get layer number */
  61. layer = -1;
  62. nLayers = OGR_DS_GetLayerCount(Ogr_ds);
  63. G_debug(2, "%d layers found in data source", nLayers);
  64. for (i = 0; i < nLayers; i++) {
  65. Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
  66. Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
  67. if (strcmp(OGR_FD_GetName(Ogr_featuredefn), ogr_info->layer_name) == 0) {
  68. Ogr_geom_type = OGR_FD_GetGeomType(Ogr_featuredefn);
  69. layer = i;
  70. break;
  71. }
  72. }
  73. if (layer == -1) {
  74. OGR_DS_Destroy(Ogr_ds);
  75. G_fatal_error(_("OGR layer <%s> not found"),
  76. ogr_info->layer_name);
  77. }
  78. G_debug(2, "OGR layer %d opened", layer);
  79. ogr_info->layer = Ogr_layer;
  80. if (update && OGR_L_TestCapability(ogr_info->layer, OLCTransactions) &&
  81. (OGR_L_StartTransaction(ogr_info->layer) != OGRERR_NONE)) {
  82. OGR_DS_Destroy(Ogr_ds);
  83. G_warning(_("OGR transaction with layer <%s> failed to start"),
  84. ogr_info->layer_name);
  85. return -1;
  86. }
  87. switch(Ogr_geom_type) {
  88. case wkbPoint25D: case wkbLineString25D: case wkbPolygon25D:
  89. case wkbMultiPoint25D: case wkbMultiLineString25D: case wkbMultiPolygon25D:
  90. case wkbGeometryCollection25D:
  91. Map->head.with_z = WITH_Z;
  92. break;
  93. default:
  94. Map->head.with_z = WITHOUT_Z;
  95. break;
  96. }
  97. ogr_info->cache.fid = -1; /* FID >= 0 */
  98. return 0;
  99. #else
  100. G_fatal_error(_("GRASS is not compiled with OGR support"));
  101. return -1;
  102. #endif
  103. }
  104. /*!
  105. \brief Open existing OGR layer on topological level
  106. This functions reads feature index (fidx) file required for
  107. pseudo-topology.
  108. \param[in,out] Map pointer to Map_info structure
  109. \return 0 success
  110. \return -1 error
  111. */
  112. int V2_open_old_ogr(struct Map_info *Map)
  113. {
  114. #ifdef HAVE_OGR
  115. G_debug(3, "V2_open_old_ogr(): name = %s mapset = %s", Map->name,
  116. Map->mapset);
  117. if (Vect_open_fidx(Map, &(Map->fInfo.ogr.offset)) != 0) {
  118. G_warning(_("Unable to open feature index file for vector map <%s>"),
  119. Vect_get_full_name(Map));
  120. G_zero(&(Map->fInfo.ogr.offset), sizeof(struct Format_info_offset));
  121. }
  122. Map->fInfo.ogr.next_line = 1; /* reset feature cache */
  123. return 0;
  124. #else
  125. G_fatal_error(_("GRASS is not compiled with OGR support"));
  126. return -1;
  127. #endif
  128. }
  129. /*!
  130. \brief Prepare OGR datasource for creating new OGR layer (level 1)
  131. New OGR layer is created when writing features by
  132. Vect_wrile_line().
  133. \param[out] Map pointer to Map_info structure
  134. \param name name of OGR layer to create
  135. \param with_z WITH_Z for 3D vector data otherwise WITHOUT_Z
  136. \return 0 success
  137. \return -1 error
  138. */
  139. int V1_open_new_ogr(struct Map_info *Map, const char *name, int with_z)
  140. {
  141. #ifdef HAVE_OGR
  142. int i, nlayers;
  143. struct Format_info_ogr *ogr_info;
  144. OGRSFDriverH Ogr_driver;
  145. OGRDataSourceH Ogr_ds;
  146. OGRLayerH Ogr_layer;
  147. OGRFeatureDefnH Ogr_featuredefn;
  148. OGRRegisterAll();
  149. ogr_info = &(Map->fInfo.ogr);
  150. G_debug(1, "V1_open_new_ogr(): name = %s with_z = %d", name, with_z);
  151. Ogr_driver = OGRGetDriverByName(ogr_info->driver_name);
  152. if (!Ogr_driver) {
  153. G_warning(_("Unable to get OGR driver <%s>"), ogr_info->driver_name);
  154. return -1;
  155. }
  156. ogr_info->driver = Ogr_driver;
  157. /* TODO: creation options */
  158. Ogr_ds = OGR_Dr_CreateDataSource(Ogr_driver, ogr_info->dsn, NULL);
  159. if (!Ogr_ds) {
  160. G_warning(_("Unable to create OGR data source '%s'"),
  161. ogr_info->dsn);
  162. return -1;
  163. }
  164. ogr_info->ds = Ogr_ds;
  165. nlayers = OGR_DS_GetLayerCount(Ogr_ds);
  166. for (i = 0; i < nlayers; i++) {
  167. Ogr_layer = OGR_DS_GetLayer(Ogr_ds, i);
  168. Ogr_featuredefn = OGR_L_GetLayerDefn(Ogr_layer);
  169. if (strcmp(OGR_FD_GetName(Ogr_featuredefn), name) == 0) {
  170. if (G_get_overwrite()) {
  171. G_warning(_("OGR layer <%s> already exists and will be overwritten"),
  172. ogr_info->layer_name);
  173. if (OGR_DS_DeleteLayer(Ogr_ds, i) != OGRERR_NONE) {
  174. G_warning(_("Unable to delete OGR layer <%s>"),
  175. ogr_info->layer_name);
  176. return -1;
  177. }
  178. }
  179. else {
  180. G_fatal_error(_("OGR layer <%s> already exists in datasource '%s'"),
  181. ogr_info->layer_name, ogr_info->dsn);
  182. }
  183. ogr_info->layer = NULL;
  184. break;
  185. }
  186. }
  187. return 0;
  188. #else
  189. G_fatal_error(_("GRASS is not compiled with OGR support"));
  190. return -1;
  191. #endif
  192. }
  193. /*!
  194. \brief Open feature index file
  195. \param[in,out] Map pointer to Map_info struct
  196. \param[out] offset pointer to Format_info_offset (OGR or PG)
  197. \return 0 on success
  198. \return -1 on error
  199. */
  200. int Vect_open_fidx(struct Map_info *Map, struct Format_info_offset *offset)
  201. {
  202. char elem[GPATH_MAX];
  203. char buf[5]; /* used for format version */
  204. long length;
  205. int Version_Major, Version_Minor, Back_Major, Back_Minor, byte_order;
  206. struct gvfile fp;
  207. struct Port_info port;
  208. G_debug(1, "Vect_open_fidx(): name = %s mapset = %s format = %d",
  209. Map->name, Map->mapset, Map->format);
  210. sprintf(elem, "%s/%s", GV_DIRECTORY, Map->name);
  211. dig_file_init(&fp);
  212. fp.file = G_fopen_old(elem, GV_FIDX_ELEMENT, Map->mapset);
  213. if (fp.file == NULL) {
  214. G_debug(1, "unable to open fidx file for vector map <%s>",
  215. Vect_get_full_name(Map));
  216. return -1;
  217. }
  218. /* Header */
  219. if (0 >= dig__fread_port_C(buf, 5, &fp))
  220. return -1;
  221. Version_Major = buf[0];
  222. Version_Minor = buf[1];
  223. Back_Major = buf[2];
  224. Back_Minor = buf[3];
  225. byte_order = buf[4];
  226. /* check version numbers */
  227. if (Version_Major > 5 || Version_Minor > 0) {
  228. if (Back_Major > 5 || Back_Minor > 0) {
  229. G_fatal_error(_("Feature index format version %d.%d is not supported by this release."
  230. " Try to rebuild topology or upgrade GRASS."),
  231. Version_Major, Version_Minor);
  232. return -1;
  233. }
  234. G_warning(_("Your GRASS version does not fully support feature index format %d.%d of the vector."
  235. " Consider to rebuild topology or upgrade GRASS."),
  236. Version_Major, Version_Minor);
  237. }
  238. dig_init_portable(&port, byte_order);
  239. dig_set_cur_port(&port);
  240. /* Body */
  241. /* bytes 6 - 9 : header size */
  242. if (0 >= dig__fread_port_L(&length, 1, &fp))
  243. return -1;
  244. G_debug(4, " header size %ld", length);
  245. G_fseek(fp.file, length, SEEK_SET);
  246. /* number of records */
  247. if (0 >= dig__fread_port_I(&(offset->array_num), 1, &fp))
  248. return -1;
  249. /* alloc space */
  250. offset->array = (int *) G_malloc(offset->array_num * sizeof(int));
  251. offset->array_alloc = offset->array_num;
  252. /* offsets */
  253. if (0 >= dig__fread_port_I(offset->array,
  254. offset->array_num, &fp))
  255. return -1;
  256. fclose(fp.file);
  257. G_debug(3, "%d records read from fidx", offset->array_num);
  258. return 0;
  259. }