list_codes.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. #include <string.h>
  2. #include <unistd.h>
  3. #include <grass/gis.h>
  4. #include <grass/glocale.h>
  5. #include <grass/config.h>
  6. #ifdef HAVE_PROJ_H
  7. #include <proj.h>
  8. #if PROJ_VERSION_MAJOR >= 6
  9. #define USE_PROJDB
  10. #endif
  11. #else
  12. #include <proj_api.h>
  13. #endif
  14. char *get_authority_names(void)
  15. {
  16. char *authnames;
  17. #ifdef USE_PROJDB
  18. /* PROJ 6 */
  19. int i, len;
  20. PROJ_STRING_LIST authlist = proj_get_authorities_from_database(NULL);
  21. len = 0;
  22. for (i = 0; authlist[i]; i++) {
  23. len += strlen(authlist[i]) + 1;
  24. }
  25. if (len > 0) {
  26. authnames = G_malloc((len + 1) * sizeof(char)); /* \0 */
  27. *authnames = '\0';
  28. for (i = 0; authlist[i]; i++) {
  29. if (i > 0)
  30. strcat(authnames, ",");
  31. strcat(authnames, authlist[i]);
  32. }
  33. }
  34. else {
  35. authnames = G_store("");
  36. }
  37. #else
  38. /* PROJ 4, 5 */
  39. /* there are various init files in share/proj/:
  40. * EPSG,GL27,IGNF,ITRF2000,ITRF2008,ITRF2014,nad27,nad83,esri
  41. * but they have different formats: bothering only with EPSG here */
  42. authnames = G_store("EPSG");
  43. #endif
  44. return authnames;
  45. }
  46. void list_codes(char *authname)
  47. {
  48. #ifdef USE_PROJDB
  49. /* PROJ 6+ */
  50. int i, crs_cnt;
  51. PROJ_CRS_INFO **proj_crs_info;
  52. crs_cnt = 0;
  53. proj_crs_info = proj_get_crs_info_list_from_database(NULL,
  54. authname, NULL, &crs_cnt);
  55. if (crs_cnt < 1)
  56. G_fatal_error(_("No codes found for authority %s"),
  57. authname);
  58. for (i = 0; i < crs_cnt; i++) {
  59. const char *proj_definition;
  60. char emptystr;
  61. PJ *pj;
  62. emptystr = '\0';
  63. pj = proj_create_from_database(NULL,
  64. proj_crs_info[i]->auth_name,
  65. proj_crs_info[i]->code,
  66. PJ_CATEGORY_CRS,
  67. 0, NULL);
  68. proj_definition = proj_as_proj_string(NULL, pj, PJ_PROJ_5, NULL);
  69. if (!proj_definition) {
  70. /* what to do with a CRS without proj string ? */
  71. G_debug(1, "No proj string for %s:%s",
  72. proj_crs_info[i]->auth_name,
  73. proj_crs_info[i]->code);
  74. proj_definition = &emptystr;
  75. }
  76. if (proj_definition) {
  77. fprintf(stdout, "%s|%s|%s\n", proj_crs_info[i]->code,
  78. proj_crs_info[i]->name,
  79. proj_definition);
  80. }
  81. proj_destroy(pj);
  82. }
  83. #else
  84. char pathname[GPATH_MAX];
  85. char code[GNAME_MAX], name[GNAME_MAX], proj_def[8192];
  86. FILE *fp;
  87. char buf[4096];
  88. int line;
  89. #ifdef HAVE_PROJ_H
  90. /* PROJ 5 */
  91. PJ_INIT_INFO init_info;
  92. if (G_strcasecmp(authname, "EPSG") == 0)
  93. authname = "epsg";
  94. init_info = proj_init_info(authname);
  95. sprintf(pathname, "%s", init_info.filename);
  96. if (access(pathname, F_OK) != 0)
  97. G_fatal_error(_("Unable to find init file %s"), authname);
  98. #else
  99. /* PROJ 4 */
  100. /* can't use pj_find_file() from the old proj api
  101. * because it does not exist in PROJ 4 */
  102. char *grass_proj_share;
  103. if (G_strcasecmp(authname, "EPSG") == 0)
  104. authname = "epsg";
  105. grass_proj_share = getenv("GRASS_PROJSHARE");
  106. if (!grass_proj_share)
  107. G_fatal_error(_("Environment variable GRASS_PROJSHARE is not set"));
  108. sprintf(pathname, "%s/%s", grass_proj_share, authname);
  109. G_convert_dirseps_to_host(pathname);
  110. #endif
  111. /* PROJ 4 / 5 */
  112. /* the init files do not have a common structure, thus restrict to epsg
  113. * see pj_init.c get_init_string() in PROJ 4 / 5 for a
  114. * generic init file parser, however without descriptive name */
  115. if (strcmp(authname, "epsg") != 0)
  116. G_fatal_error(_("Only epsg file is currently supported"));
  117. /* open the init file */
  118. fp = fopen(pathname, "r");
  119. if (!fp) {
  120. G_fatal_error(_("Unable to open init file <%s>"), authname);
  121. }
  122. code[0] = '\0';
  123. name[0] = '\0';
  124. proj_def[0] = '\0';
  125. /* print list of codes, names, definitions */
  126. for (line = 1; G_getl2(buf, sizeof(buf), fp); line++) {
  127. int buflen, bufstart;
  128. int i, j;
  129. G_strip(buf);
  130. buflen = strlen(buf);
  131. if (*buf == '\0' ||
  132. (buflen >= 10 && strncmp(buf, "<metadata>", 10) == 0)) {
  133. name[0] = '\0';
  134. continue;
  135. }
  136. /* name: could be text following '# ' */
  137. /* code: <code>
  138. * definition follows code until next '<' */
  139. if (*buf == '#' && buflen > 2) {
  140. sprintf(name, "%s", buf + 2);
  141. continue;
  142. }
  143. i = 0;
  144. bufstart = 0;
  145. while (i < buflen) {
  146. if (buf[i] == '<') {
  147. /* end of section ? */
  148. if (code[0] != '\0') {
  149. G_strip(proj_def);
  150. /* the descriptive name may be hidden in proj_def as
  151. * +title=
  152. * e.g. IGNF */
  153. fprintf(stdout, "%s|%s|%s\n", code, name, proj_def);
  154. code[0] = '\0';
  155. name[0] = '\0';
  156. proj_def[0] = '\0';
  157. }
  158. /* start of section ? */
  159. bufstart = i + 1;
  160. j = bufstart;
  161. while (j < buflen && buf[j] != '>')
  162. j++;
  163. if (j < buflen) {
  164. buf[j] = '\0';
  165. sprintf(code, "%s", buf + bufstart);
  166. }
  167. i = j + 1;
  168. bufstart = i;
  169. continue;
  170. }
  171. if (buf[i] == '#') {
  172. /* the remaining content of the line could be the name */
  173. bufstart = i + 1;
  174. if (bufstart < buflen) {
  175. sprintf(name, "%s", buf + bufstart);
  176. G_strip(name);
  177. }
  178. i = buflen;
  179. continue;
  180. }
  181. if (code[0] != '\0') {
  182. char stopchar;
  183. int proj_len;
  184. /* inside a section definition */
  185. /* test for '<' or '#' later on in the line */
  186. j = bufstart;
  187. while (j < buflen && buf[j] != '<' && buf[j] != '#')
  188. j++;
  189. if (j < buflen) {
  190. stopchar = buf[j];
  191. buf[j] = '\0';
  192. proj_len = strlen(proj_def);
  193. proj_def[proj_len] = ' ';
  194. proj_def[proj_len + 1] = '\0';
  195. strcat(proj_def, buf + bufstart);
  196. buf[j] = stopchar;
  197. i = j;
  198. bufstart = i;
  199. }
  200. else {
  201. proj_len = strlen(proj_def);
  202. proj_def[proj_len] = ' ';
  203. proj_def[proj_len + 1] = '\0';
  204. strcat(proj_def, buf + bufstart);
  205. i = buflen;
  206. bufstart = i;
  207. }
  208. }
  209. else
  210. i++;
  211. }
  212. }
  213. fclose(fp);
  214. #endif
  215. }