proj.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include <grass/gis.h>
  2. #include <grass/gprojects.h>
  3. #include <grass/glocale.h>
  4. #include <gdal.h>
  5. #include <ogr_srs_api.h>
  6. /* keep in sync with r.in.gdal, v.in.ogr, v.external */
  7. void check_projection(struct Cell_head *cellhd, GDALDatasetH hDS,
  8. char *outloc, int create_only, int override,
  9. int check_only)
  10. {
  11. struct Cell_head loc_wind;
  12. struct Key_Value *proj_info, *proj_units, *proj_epsg;
  13. struct Key_Value *loc_proj_info, *loc_proj_units;
  14. const char *wkt;
  15. char error_msg[8096];
  16. int proj_trouble;
  17. /* -------------------------------------------------------------------- */
  18. /* Fetch the projection in GRASS form. */
  19. /* -------------------------------------------------------------------- */
  20. proj_info = NULL;
  21. proj_units = NULL;
  22. proj_epsg = NULL;
  23. loc_proj_info = NULL;
  24. loc_proj_units = NULL;
  25. wkt = GDALGetProjectionRef(hDS);
  26. /* proj_trouble:
  27. * 0: valid srs
  28. * 1: no srs, default to xy
  29. * 2: unreadable srs, default to xy
  30. */
  31. /* Projection only required for checking so convert non-interactively */
  32. proj_trouble = 0;
  33. if (wkt && *wkt) {
  34. OGRSpatialReferenceH hSRS;
  35. hSRS = OSRNewSpatialReference(wkt);
  36. if (hSRS != NULL)
  37. GPJ_osr_to_grass(cellhd, &proj_info, &proj_units, hSRS, 0);
  38. if (!hSRS || (!OSRIsProjected(hSRS) && !OSRIsGeographic(hSRS))) {
  39. G_important_message(_("Input contains an invalid SRS. "
  40. "WKT definition:\n%s"), wkt);
  41. proj_trouble = 2;
  42. }
  43. else{
  44. const char *authkey, *authname, *authcode;
  45. if (OSRIsProjected(hSRS))
  46. authkey = "PROJCS";
  47. else /* is geographic */
  48. authkey = "GEOGCS";
  49. authname = OSRGetAuthorityName(hSRS, authkey);
  50. if (authname && *authname && strcmp(authname, "EPSG") == 0) {
  51. authcode = OSRGetAuthorityCode(hSRS, authkey);
  52. if (authcode && *authcode) {
  53. G_debug(1, "found EPSG:%s", authcode);
  54. proj_epsg = G_create_key_value();
  55. G_set_key_value("epsg", authcode, proj_epsg);
  56. }
  57. }
  58. }
  59. if (hSRS)
  60. OSRDestroySpatialReference(hSRS);
  61. }
  62. else {
  63. G_important_message(_("No projection information available"));
  64. cellhd->proj = PROJECTION_XY;
  65. cellhd->zone = 0;
  66. proj_trouble = 1;
  67. }
  68. /* -------------------------------------------------------------------- */
  69. /* Do we need to create a new location? */
  70. /* -------------------------------------------------------------------- */
  71. if (outloc != NULL) {
  72. /* do not create a xy location if an existing SRS was unreadable */
  73. if (proj_trouble == 2) {
  74. G_fatal_error(_("Unable to convert input map projection to GRASS "
  75. "format; cannot create new location."));
  76. }
  77. else {
  78. if (0 != G_make_location_epsg(outloc, cellhd, proj_info,
  79. proj_units, proj_epsg)) {
  80. G_fatal_error(_("Unable to create new location <%s>"),
  81. outloc);
  82. }
  83. G_message(_("Location <%s> created"), outloc);
  84. G_unset_window(); /* new location, projection, and window */
  85. G_get_window(cellhd);
  86. }
  87. /* If create only, clean up and exit here */
  88. if (create_only) {
  89. GDALClose(hDS);
  90. exit(EXIT_SUCCESS);
  91. }
  92. }
  93. else {
  94. int err = 0;
  95. void (*msg_fn)(const char *, ...);
  96. if (check_only && override) {
  97. /* can't check when over-riding check */
  98. override = 0;
  99. }
  100. if (proj_trouble == 2) {
  101. strcpy(error_msg, _("Unable to convert input map projection information "
  102. "to GRASS format."));
  103. if (override) {
  104. msg_fn = G_warning;
  105. }
  106. else {
  107. msg_fn = G_fatal_error;
  108. }
  109. msg_fn(error_msg);
  110. if (!override) {
  111. exit(EXIT_FAILURE);
  112. }
  113. }
  114. /* -------------------------------------------------------------------- */
  115. /* Does the projection of the current location match the */
  116. /* dataset? */
  117. /* -------------------------------------------------------------------- */
  118. G_get_default_window(&loc_wind);
  119. /* fetch LOCATION PROJ info */
  120. if (loc_wind.proj != PROJECTION_XY) {
  121. loc_proj_info = G_get_projinfo();
  122. loc_proj_units = G_get_projunits();
  123. }
  124. if (override) {
  125. cellhd->proj = loc_wind.proj;
  126. cellhd->zone = loc_wind.zone;
  127. G_message(_("Over-riding projection check"));
  128. }
  129. else if (loc_wind.proj != cellhd->proj
  130. || (err =
  131. G_compare_projections(loc_proj_info, loc_proj_units,
  132. proj_info, proj_units)) != 1) {
  133. int i_value;
  134. strcpy(error_msg,
  135. _("Projection of dataset does not"
  136. " appear to match current location.\n\n"));
  137. /* TODO: output this info sorted by key: */
  138. if (loc_wind.proj != cellhd->proj || err != -2) {
  139. /* error in proj_info */
  140. if (loc_proj_info != NULL) {
  141. strcat(error_msg, _("Location PROJ_INFO is:\n"));
  142. for (i_value = 0; i_value < loc_proj_info->nitems;
  143. i_value++)
  144. sprintf(error_msg + strlen(error_msg), "%s: %s\n",
  145. loc_proj_info->key[i_value],
  146. loc_proj_info->value[i_value]);
  147. strcat(error_msg, "\n");
  148. }
  149. if (proj_info != NULL) {
  150. strcat(error_msg, _("Dataset PROJ_INFO is:\n"));
  151. for (i_value = 0; i_value < proj_info->nitems; i_value++)
  152. sprintf(error_msg + strlen(error_msg), "%s: %s\n",
  153. proj_info->key[i_value],
  154. proj_info->value[i_value]);
  155. }
  156. else {
  157. strcat(error_msg, _("Dataset PROJ_INFO is:\n"));
  158. if (cellhd->proj == PROJECTION_XY)
  159. sprintf(error_msg + strlen(error_msg),
  160. "Dataset proj = %d (unreferenced/unknown)\n",
  161. cellhd->proj);
  162. else if (cellhd->proj == PROJECTION_LL)
  163. sprintf(error_msg + strlen(error_msg),
  164. "Dataset proj = %d (lat/long)\n",
  165. cellhd->proj);
  166. else if (cellhd->proj == PROJECTION_UTM)
  167. sprintf(error_msg + strlen(error_msg),
  168. "Dataset proj = %d (UTM), zone = %d\n",
  169. cellhd->proj, cellhd->zone);
  170. else
  171. sprintf(error_msg + strlen(error_msg),
  172. "Dataset proj = %d (unknown), zone = %d\n",
  173. cellhd->proj, cellhd->zone);
  174. }
  175. if (loc_wind.proj != cellhd->proj) {
  176. strcat(error_msg, "\nERROR: proj\n");
  177. }
  178. else {
  179. strcat(error_msg, "\nERROR: ");
  180. switch (err) {
  181. case -1:
  182. strcat(error_msg, "proj\n");
  183. break;
  184. case -2:
  185. strcat(error_msg, "units\n");
  186. break;
  187. case -3:
  188. strcat(error_msg, "datum\n");
  189. break;
  190. case -4:
  191. strcat(error_msg, "ellps, a, es\n");
  192. break;
  193. case -5:
  194. strcat(error_msg, "zone\n");
  195. break;
  196. case -6:
  197. strcat(error_msg, "south\n");
  198. break;
  199. case -7:
  200. strcat(error_msg, "x_0\n");
  201. break;
  202. case -8:
  203. strcat(error_msg, "y_0\n");
  204. break;
  205. case -9:
  206. strcat(error_msg, "lon_0\n");
  207. break;
  208. case -10:
  209. strcat(error_msg, "lat_0\n");
  210. break;
  211. case -11:
  212. strcat(error_msg, "lat_1, lat2\n");
  213. break;
  214. }
  215. }
  216. }
  217. else {
  218. /* error in proj_units */
  219. if (loc_proj_units != NULL) {
  220. strcat(error_msg, "Location PROJ_UNITS is:\n");
  221. for (i_value = 0; i_value < loc_proj_units->nitems;
  222. i_value++)
  223. sprintf(error_msg + strlen(error_msg), "%s: %s\n",
  224. loc_proj_units->key[i_value],
  225. loc_proj_units->value[i_value]);
  226. strcat(error_msg, "\n");
  227. }
  228. if (proj_units != NULL) {
  229. strcat(error_msg, "Dataset PROJ_UNITS is:\n");
  230. for (i_value = 0; i_value < proj_units->nitems; i_value++)
  231. sprintf(error_msg + strlen(error_msg), "%s: %s\n",
  232. proj_units->key[i_value],
  233. proj_units->value[i_value]);
  234. }
  235. }
  236. if (!check_only) {
  237. strcat(error_msg,
  238. _("\nIn case of no significant differences in the projection definitions,"
  239. " use the -o flag to ignore them and use"
  240. " current location definition.\n"));
  241. strcat(error_msg,
  242. _("Consider generating a new location from the input dataset using "
  243. "the 'location' parameter.\n"));
  244. }
  245. if (check_only)
  246. msg_fn = G_warning;
  247. else
  248. msg_fn = G_fatal_error;
  249. msg_fn("%s", error_msg);
  250. if (check_only) {
  251. GDALClose(hDS);
  252. exit(EXIT_FAILURE);
  253. }
  254. }
  255. else {
  256. if (check_only)
  257. msg_fn = G_message;
  258. else
  259. msg_fn = G_verbose_message;
  260. msg_fn(_("Projection of input dataset and current location "
  261. "appear to match"));
  262. if (check_only) {
  263. GDALClose(hDS);
  264. exit(EXIT_SUCCESS);
  265. }
  266. }
  267. }
  268. }