ellipse.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /**
  2. \file ellipse.c
  3. \brief GProj library - Functions for reading datum parameters from the location database
  4. \author Paul Kelly <paul-grass stjohnspoint.co.uk>
  5. (C) 2003-2008 by the GRASS Development Team
  6. This program is free software under the GNU General Public
  7. License (>=v2). Read the file COPYING that comes with GRASS
  8. for details.
  9. **/
  10. #include <unistd.h>
  11. #include <ctype.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <math.h> /* for sqrt() */
  15. #include <grass/gis.h>
  16. #include <grass/glocale.h>
  17. #include <grass/gprojects.h>
  18. #include "local_proto.h"
  19. static int get_a_e2_rf(const char *, const char *, double *, double *,
  20. double *);
  21. /**
  22. * This routine returns the ellipsoid parameters from the database.
  23. * If the PROJECTION_FILE exists in the PERMANENT mapset, read info from
  24. * that file, otherwise return WGS 84 values.
  25. *
  26. * \return 1 ok, 0 default values used.
  27. * Dies with diagnostic if there is an error
  28. **/
  29. int GPJ_get_ellipsoid_params(double *a, double *e2, double *rf)
  30. {
  31. int ret;
  32. struct Key_Value *proj_keys = G_get_projinfo();
  33. if (proj_keys == NULL)
  34. proj_keys = G_create_key_value();
  35. ret = GPJ__get_ellipsoid_params(proj_keys, a, e2, rf);
  36. G_free_key_value(proj_keys);
  37. return ret;
  38. }
  39. int
  40. GPJ__get_ellipsoid_params(const struct Key_Value *proj_keys,
  41. double *a, double *e2, double *rf)
  42. {
  43. struct gpj_ellps estruct;
  44. struct gpj_datum dstruct;
  45. const char *str, *str3;
  46. char *str1, *ellps;
  47. str = G_find_key_value("datum", proj_keys);
  48. if ((str != NULL) && (GPJ_get_datum_by_name(str, &dstruct) > 0)) {
  49. /* If 'datum' key is present, look up correct ellipsoid
  50. * from datum.table */
  51. ellps = G_store(dstruct.ellps);
  52. GPJ_free_datum(&dstruct);
  53. }
  54. else
  55. /* else use ellipsoid defined in PROJ_INFO */
  56. ellps = G_store(G_find_key_value("ellps", proj_keys));
  57. if (ellps != NULL && *ellps) {
  58. if (GPJ_get_ellipsoid_by_name(ellps, &estruct) < 0)
  59. G_fatal_error(_("Invalid ellipsoid <%s> in file"), ellps);
  60. *a = estruct.a;
  61. *e2 = estruct.es;
  62. *rf = estruct.rf;
  63. GPJ_free_ellps(&estruct);
  64. G_free(ellps);
  65. return 1;
  66. }
  67. else {
  68. if (ellps) /* *ellps = '\0' */
  69. G_free(ellps);
  70. str3 = G_find_key_value("a", proj_keys);
  71. if (str3 != NULL) {
  72. char *str4;
  73. G_asprintf(&str4, "a=%s", str3);
  74. if ((str3 = G_find_key_value("es", proj_keys)) != NULL)
  75. G_asprintf(&str1, "e=%s", str3);
  76. else if ((str3 = G_find_key_value("f", proj_keys)) != NULL)
  77. G_asprintf(&str1, "f=1/%s", str3);
  78. else if ((str3 = G_find_key_value("rf", proj_keys)) != NULL)
  79. G_asprintf(&str1, "f=1/%s", str3);
  80. else if ((str3 = G_find_key_value("b", proj_keys)) != NULL)
  81. G_asprintf(&str1, "b=%s", str3);
  82. else
  83. G_fatal_error(_("No secondary ellipsoid descriptor "
  84. "(rf, es or b) in file"));
  85. if (get_a_e2_rf(str4, str1, a, e2, rf) == 0)
  86. G_fatal_error(_("Invalid ellipsoid descriptors "
  87. "(a, rf, es or b) in file"));
  88. return 1;
  89. }
  90. else {
  91. str = G_find_key_value("proj", proj_keys);
  92. if ((str == NULL) || (strcmp(str, "ll") == 0)) {
  93. *a = 6378137.0;
  94. *e2 = .006694385;
  95. *rf = 298.257223563;
  96. return 0;
  97. }
  98. else {
  99. G_fatal_error(_("No ellipsoid info given in file"));
  100. }
  101. }
  102. }
  103. return 1;
  104. }
  105. /**
  106. * \brief looks up ellipsoid in ellipsoid table and returns the
  107. * a, e2 parameters for the ellipsoid
  108. *
  109. * \return 1 if ok,
  110. * -1 if not found in table
  111. */
  112. int GPJ_get_ellipsoid_by_name(const char *name, struct gpj_ellps *estruct)
  113. {
  114. struct ellps_list *list, *listhead;
  115. list = listhead = read_ellipsoid_table(0);
  116. while (list != NULL) {
  117. if (G_strcasecmp(name, list->name) == 0) {
  118. estruct->name = G_store(list->name);
  119. estruct->longname = G_store(list->longname);
  120. estruct->a = list->a;
  121. estruct->es = list->es;
  122. estruct->rf = list->rf;
  123. free_ellps_list(listhead);
  124. return 1;
  125. }
  126. list = list->next;
  127. }
  128. free_ellps_list(listhead);
  129. return -1;
  130. }
  131. static int
  132. get_a_e2_rf(const char *s1, const char *s2, double *a, double *e2,
  133. double *recipf)
  134. {
  135. double b, f;
  136. if (sscanf(s1, "a=%lf", a) != 1)
  137. return 0;
  138. if (*a <= 0.0)
  139. return 0;
  140. if (sscanf(s2, "e=%lf", e2) == 1) {
  141. f = 1.0 - sqrt(1.0 - *e2);
  142. *recipf = 1.0 / f;
  143. return (*e2 >= 0.0);
  144. }
  145. if (sscanf(s2, "f=1/%lf", recipf) == 1) {
  146. if (*recipf <= 0.0)
  147. return 0;
  148. f = 1.0 / *recipf;
  149. *e2 = f * (2 - f);
  150. return (*e2 >= 0.0);
  151. }
  152. if (sscanf(s2, "b=%lf", &b) == 1) {
  153. if (b <= 0.0)
  154. return 0;
  155. if (b == *a) {
  156. f = 0.0;
  157. *e2 = 0.0;
  158. }
  159. else {
  160. f = (*a - b) / *a;
  161. *e2 = f * (2 - f);
  162. }
  163. *recipf = 1.0 / f;
  164. return (*e2 >= 0.0);
  165. }
  166. return 0;
  167. }
  168. struct ellps_list *read_ellipsoid_table(int fatal)
  169. {
  170. FILE *fd;
  171. char file[GPATH_MAX];
  172. char buf[4096];
  173. char name[100], descr[1024], buf1[1024], buf2[1024];
  174. char badlines[1024];
  175. int line;
  176. int err;
  177. struct ellps_list *current = NULL, *outputlist = NULL;
  178. double a, e2, rf;
  179. int count = 0;
  180. sprintf(file, "%s%s", G_gisbase(), ELLIPSOIDTABLE);
  181. fd = fopen(file, "r");
  182. if (!fd) {
  183. (fatal ? G_fatal_error : G_warning)(
  184. _("Unable to open ellipsoid table file <%s>"), file);
  185. return NULL;
  186. }
  187. err = 0;
  188. *badlines = 0;
  189. for (line = 1; G_getl2(buf, sizeof buf, fd); line++) {
  190. G_strip(buf);
  191. if (*buf == 0 || *buf == '#')
  192. continue;
  193. if (sscanf(buf, "%s \"%1023[^\"]\" %s %s", name, descr, buf1, buf2)
  194. != 4) {
  195. err++;
  196. sprintf(buf, " %d", line);
  197. if (*badlines)
  198. strcat(badlines, ",");
  199. strcat(badlines, buf);
  200. continue;
  201. }
  202. if (get_a_e2_rf(buf1, buf2, &a, &e2, &rf)
  203. || get_a_e2_rf(buf2, buf1, &a, &e2, &rf)) {
  204. if (current == NULL)
  205. current = outputlist = G_malloc(sizeof(struct ellps_list));
  206. else
  207. current = current->next = G_malloc(sizeof(struct ellps_list));
  208. current->name = G_store(name);
  209. current->longname = G_store(descr);
  210. current->a = a;
  211. current->es = e2;
  212. current->rf = rf;
  213. current->next = NULL;
  214. count++;
  215. }
  216. else {
  217. err++;
  218. sprintf(buf, " %d", line);
  219. if (*badlines)
  220. strcat(badlines, ",");
  221. strcat(badlines, buf);
  222. continue;
  223. }
  224. }
  225. fclose(fd);
  226. if (!err)
  227. return outputlist;
  228. (fatal ? G_fatal_error : G_warning)(
  229. err == 1
  230. ? _("Line%s of ellipsoid table file <%s> is invalid")
  231. : _("Lines%s of ellipsoid table file <%s> are invalid"),
  232. badlines, file);
  233. return outputlist;
  234. }
  235. void GPJ_free_ellps(struct gpj_ellps *estruct)
  236. {
  237. G_free(estruct->name);
  238. G_free(estruct->longname);
  239. return;
  240. }
  241. void free_ellps_list(struct ellps_list *elist)
  242. {
  243. struct ellps_list *old;
  244. while (elist != NULL) {
  245. G_free(elist->name);
  246. G_free(elist->longname);
  247. old = elist;
  248. elist = old->next;
  249. G_free(old);
  250. }
  251. return;
  252. }