input.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. ****************************************************************************
  3. *
  4. * MODULE: g.proj
  5. * AUTHOR(S): Paul Kelly - paul-grass@stjohnspoint.co.uk
  6. * Frank Warmerdam
  7. * Radim Blazek
  8. * PURPOSE: Provides a means of reporting the contents of GRASS
  9. * projection information files and creating
  10. * new projection information files.
  11. * COPYRIGHT: (C) 2001-2007 by the GRASS Development Team
  12. *
  13. * This program is free software under the GNU General Public
  14. * License (>=v2). Read the file COPYING that comes with GRASS
  15. * for details.
  16. *
  17. *****************************************************************************/
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <math.h>
  21. #include <grass/gis.h>
  22. #include <grass/gprojects.h>
  23. #include <grass/glocale.h>
  24. #include <grass/config.h>
  25. #ifdef HAVE_OGR
  26. # include <gdal.h>
  27. # include <ogr_api.h>
  28. # include <cpl_csv.h>
  29. #endif
  30. #include "local_proto.h"
  31. static void set_default_region(void);
  32. #ifdef HAVE_OGR
  33. static void set_gdal_region(GDALDatasetH);
  34. #endif
  35. /**
  36. * \brief Read projection and region information from current location
  37. *
  38. * Reads projection and region information from current location and
  39. * stores in global structs cellhd, projinfo and projunits.
  40. **/
  41. void input_currloc(void)
  42. {
  43. G_get_default_window(&cellhd);
  44. if (cellhd.proj != PROJECTION_XY) {
  45. projinfo = G_get_projinfo();
  46. projunits = G_get_projunits();
  47. projepsg = G_get_projepsg();
  48. }
  49. return;
  50. }
  51. #ifdef HAVE_OGR
  52. /**
  53. * \brief Read projection information in WKT format from stdin or a file
  54. *
  55. * Reads projection information from a file or stdin and stores in global
  56. * structs projinfo and projunits.
  57. * Populates global cellhd with default region information.
  58. *
  59. * \param wktfile File to read WKT co-ordinate system description from; -
  60. * for stdin
  61. *
  62. * \return 2 if a projected or lat/long co-ordinate system has been
  63. * defined; 1 if an unreferenced XY co-ordinate system has
  64. * been defined
  65. **/
  66. int input_wkt(char *wktfile)
  67. {
  68. FILE *infd;
  69. char buff[8000];
  70. OGRSpatialReferenceH hSRS;
  71. int ret;
  72. if (strcmp(wktfile, "-") == 0)
  73. infd = stdin;
  74. else
  75. infd = fopen(wktfile, "r");
  76. if (infd) {
  77. fread(buff, sizeof(buff), 1, infd);
  78. if (ferror(infd))
  79. G_fatal_error(_("Error reading WKT projection description"));
  80. else
  81. fclose(infd);
  82. /* Get rid of newlines */
  83. G_squeeze(buff);
  84. }
  85. else
  86. G_fatal_error(_("Unable to open file '%s' for reading"), wktfile);
  87. ret = GPJ_wkt_to_grass(&cellhd, &projinfo, &projunits, buff, 0);
  88. set_default_region();
  89. hSRS = OSRNewSpatialReference(buff);
  90. if (hSRS) {
  91. const char *authkey, *authname, *authcode;
  92. authkey = NULL;
  93. if (OSRIsProjected(hSRS))
  94. authkey = "PROJCS";
  95. else if (OSRIsGeographic(hSRS))
  96. authkey = "GEOGCS";
  97. if (authkey) {
  98. authname = OSRGetAuthorityName(hSRS, authkey);
  99. if (authname && *authname && strcmp(authname, "EPSG") == 0) {
  100. authcode = OSRGetAuthorityCode(hSRS, authkey);
  101. if (authcode && *authcode) {
  102. projepsg = G_create_key_value();
  103. G_set_key_value("epsg", authcode, projepsg);
  104. }
  105. }
  106. }
  107. }
  108. return ret;
  109. }
  110. /**
  111. * \brief Read projection information in PROJ.4 format from a string
  112. * or stdin
  113. *
  114. * Reads projection information from a string or stdin and stores in global
  115. * structs projinfo and projunits.
  116. * Populates global cellhd with default region information.
  117. *
  118. * \param proj4params String representation of PROJ.4 co-ordinate system
  119. * description, or - to read it from stdin
  120. *
  121. * \return 2 if a projected or lat/long co-ordinate system has been
  122. * defined; 1 if an unreferenced XY co-ordinate system has
  123. * been defined
  124. **/
  125. int input_proj4(char *proj4params)
  126. {
  127. FILE *infd;
  128. char buff[8000];
  129. char *proj4string;
  130. OGRSpatialReferenceH hSRS;
  131. int ret = 0;
  132. if (strcmp(proj4params, "-") == 0) {
  133. infd = stdin;
  134. fgets(buff, sizeof(buff), infd);
  135. G_asprintf(&proj4string, "%s +no_defs", buff);
  136. }
  137. else
  138. G_asprintf(&proj4string, "%s +no_defs", proj4params);
  139. /* Set finder function for locating OGR csv co-ordinate system tables */
  140. /* SetCSVFilenameHook(GPJ_set_csv_loc); */
  141. hSRS = OSRNewSpatialReference(NULL);
  142. if (OSRImportFromProj4(hSRS, proj4string) != OGRERR_NONE)
  143. G_fatal_error(_("Can't parse PROJ.4-style parameter string"));
  144. G_free(proj4string);
  145. ret = GPJ_osr_to_grass(&cellhd, &projinfo, &projunits, hSRS, 0);
  146. OSRDestroySpatialReference(hSRS);
  147. set_default_region();
  148. return ret;
  149. }
  150. /**
  151. * \brief Read projection information corresponding to an EPSG co-ordinate
  152. * system number
  153. *
  154. * Determines projection information corresponding to an EPSG co-ordinate
  155. * system number and stores in global structs projinfo and projunits.
  156. * Populates global cellhd with default region information.
  157. *
  158. * \param epsg_num EPSG number for co-ordinate system
  159. *
  160. * \return 2 if a projected or lat/long co-ordinate system has been
  161. * defined; 1 if an unreferenced XY co-ordinate system has
  162. * been defined
  163. **/
  164. int input_epsg(int epsg_num)
  165. {
  166. OGRSpatialReferenceH hSRS;
  167. char epsgstr[100];
  168. int ret = 0;
  169. /* Set finder function for locating OGR csv co-ordinate system tables */
  170. /* SetCSVFilenameHook(GPJ_set_csv_loc); */
  171. hSRS = OSRNewSpatialReference(NULL);
  172. if (OSRImportFromEPSG(hSRS, epsg_num) != OGRERR_NONE)
  173. G_fatal_error(_("Unable to translate EPSG code"));
  174. ret = GPJ_osr_to_grass(&cellhd, &projinfo, &projunits, hSRS, 0);
  175. sprintf(epsgstr, "%d", epsg_num);
  176. projepsg = G_create_key_value();
  177. G_set_key_value("epsg", epsgstr, projepsg);
  178. OSRDestroySpatialReference(hSRS);
  179. set_default_region();
  180. return ret;
  181. }
  182. /**
  183. * \brief Read projection and region information associated with a
  184. * georeferenced file
  185. *
  186. * Reads projection information associated with a georeferenced file, if
  187. * available. Attempts are made to open the file with OGR and GDAL in turn.
  188. * (GDAL conventionally supports raster formats, and OGR vector formats.)
  189. *
  190. * If successful, projection and region information are read from the file
  191. * using GDAL/OGR functions and stored in global structs cellhd, projinfo
  192. * and projunits.
  193. *
  194. * \param geofile Path to georeferenced file
  195. *
  196. * \return 2 if a projected or lat/long co-ordinate system has been
  197. * defined; 1 if an unreferenced XY co-ordinate system has
  198. * been defined
  199. **/
  200. int input_georef(char *geofile)
  201. {
  202. OGRDataSourceH ogr_ds;
  203. OGRSpatialReferenceH hSRS;
  204. int ret = 0;
  205. /* Try opening file with OGR first because it doesn't output a
  206. * (potentially confusing) error message if it can't open the file */
  207. G_debug(1, "Trying to open <%s> with OGR...", geofile);
  208. OGRRegisterAll();
  209. hSRS = NULL;
  210. if ((ogr_ds = OGROpen(geofile, FALSE, NULL))
  211. && (OGR_DS_GetLayerCount(ogr_ds) > 0)) {
  212. OGRLayerH ogr_layer;
  213. G_debug(1, "...succeeded.");
  214. /* Get the first layer */
  215. ogr_layer = OGR_DS_GetLayer(ogr_ds, 0);
  216. hSRS = OGR_L_GetSpatialRef(ogr_layer);
  217. ret = GPJ_osr_to_grass(&cellhd, &projinfo, &projunits, hSRS, 0);
  218. set_default_region();
  219. OGR_DS_Destroy(ogr_ds);
  220. }
  221. else {
  222. /* Try opening with GDAL */
  223. GDALDatasetH gdal_ds;
  224. G_debug(1, "Trying to open with GDAL...");
  225. GDALAllRegister();
  226. if ((gdal_ds = GDALOpen(geofile, GA_ReadOnly))) {
  227. char *wktstring;
  228. G_debug(1, "...succeeded.");
  229. wktstring = (char *)GDALGetProjectionRef(gdal_ds);
  230. ret =
  231. GPJ_wkt_to_grass(&cellhd, &projinfo, &projunits, wktstring,
  232. 0);
  233. set_gdal_region(gdal_ds);
  234. hSRS = OSRNewSpatialReference(wktstring);
  235. }
  236. else
  237. G_fatal_error(_("Unable to read georeferenced file <%s> using "
  238. "GDAL library"), geofile);
  239. }
  240. if (cellhd.proj == PROJECTION_XY)
  241. G_warning(_("Read of file %s was successful, but it did not contain "
  242. "projection information. 'XY (unprojected)' will be used"),
  243. geofile);
  244. if (hSRS) {
  245. const char *authkey, *authname, *authcode;
  246. authkey = NULL;
  247. if (OSRIsProjected(hSRS))
  248. authkey = "PROJCS";
  249. else if (OSRIsGeographic(hSRS))
  250. authkey = "GEOGCS";
  251. if (authkey) {
  252. authname = OSRGetAuthorityName(hSRS, authkey);
  253. if (authname && *authname && strcmp(authname, "EPSG") == 0) {
  254. authcode = OSRGetAuthorityCode(hSRS, authkey);
  255. if (authcode && *authcode) {
  256. projepsg = G_create_key_value();
  257. G_set_key_value("epsg", authcode, projepsg);
  258. }
  259. }
  260. }
  261. }
  262. return ret;
  263. }
  264. #endif /* HAVE_OGR */
  265. /**
  266. * \brief Populates global cellhd with "default" region settings
  267. **/
  268. static void set_default_region(void)
  269. {
  270. /* If importing projection there will be no region information, so
  271. * set some default values */
  272. cellhd.rows = 1;
  273. cellhd.rows3 = 1;
  274. cellhd.cols = 1;
  275. cellhd.cols3 = 1;
  276. cellhd.depths = 1.;
  277. cellhd.north = 1.;
  278. cellhd.ns_res = 1.;
  279. cellhd.ns_res3 = 1.;
  280. cellhd.south = 0.;
  281. cellhd.west = 0.;
  282. cellhd.ew_res = 1.;
  283. cellhd.ew_res3 = 1.;
  284. cellhd.east = 1.;
  285. cellhd.top = 1.;
  286. cellhd.tb_res = 1.;
  287. cellhd.bottom = 0.;
  288. return;
  289. }
  290. #ifdef HAVE_OGR
  291. /**
  292. * \brief Populates global cellhd with region settings based on
  293. * georeferencing information in a GDAL dataset
  294. *
  295. * \param hDS GDAL dataset object to retrieve georeferencing information from
  296. **/
  297. static void set_gdal_region(GDALDatasetH hDS)
  298. {
  299. double adfGeoTransform[6];
  300. /* Populate with initial values in case we can't set everything */
  301. set_default_region();
  302. /* Code below originally from r.in.gdal */
  303. cellhd.rows = GDALGetRasterYSize(hDS);
  304. cellhd.cols = GDALGetRasterXSize(hDS);
  305. cellhd.rows3 = cellhd.rows;
  306. cellhd.cols3 = cellhd.cols;
  307. if (GDALGetGeoTransform(hDS, adfGeoTransform) == CE_None
  308. && adfGeoTransform[5] < 0.0) {
  309. if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0) {
  310. /* Map is rotated. Calculation of north/south extents and
  311. * resolution more complicated.
  312. * TODO: do it anyway */
  313. return;
  314. }
  315. cellhd.north = adfGeoTransform[3];
  316. cellhd.ns_res = fabs(adfGeoTransform[5]);
  317. cellhd.south = cellhd.north - cellhd.ns_res * cellhd.rows;
  318. cellhd.west = adfGeoTransform[0];
  319. cellhd.ew_res = adfGeoTransform[1];
  320. cellhd.east = cellhd.west + cellhd.cols * cellhd.ew_res;
  321. cellhd.ns_res3 = cellhd.ns_res;
  322. cellhd.ew_res3 = cellhd.ew_res;
  323. }
  324. else {
  325. cellhd.north = cellhd.rows;
  326. cellhd.east = cellhd.cols;
  327. }
  328. return;
  329. }
  330. #endif /* HAVE_OGR */