proj3.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*!
  2. \file lib/gis/proj3.c
  3. \brief GIS Library - Projection support (database)
  4. (C) 2001-2014 by the GRASS Development Team
  5. This program is free software under the GNU General Public License
  6. (>=v2). Read the file COPYING that comes with GRASS for details.
  7. \author Original author CERL
  8. */
  9. #include <string.h>
  10. #include <grass/gis.h>
  11. #include <grass/glocale.h>
  12. static const char *lookup_proj(const char *);
  13. static const char *lookup_units(const char *);
  14. static const char *lookup_epsg();
  15. static int equal(const char *, const char *);
  16. static int lower(char);
  17. static int initialized;
  18. static struct Key_Value *proj_info, *proj_units, *proj_epsg;
  19. static void init(void)
  20. {
  21. if (G_is_initialized(&initialized))
  22. return;
  23. proj_info = G_get_projinfo();
  24. proj_units = G_get_projunits();
  25. proj_epsg = G_get_projepsg();
  26. G_initialize_done(&initialized);
  27. }
  28. /*!
  29. \brief Get units (localized) name for the current location
  30. Returns a string describing the database grid units. It returns a
  31. plural form (eg. 'feet') if <i>plural</i> is non-zero. Otherwise it
  32. returns a singular form (eg. 'foot').
  33. \param plural plural form if non-zero
  34. \return localized units name
  35. */
  36. const char *G_database_unit_name(int plural)
  37. {
  38. int units;
  39. const char *name;
  40. units = G__projection_units(G_projection());
  41. if (units == U_UNDEFINED) {
  42. name = lookup_units(plural ? "units" : "unit");
  43. if (!name)
  44. return plural ? _("units") : _("unit");
  45. if (strcasecmp(name, "meter") == 0 || strcasecmp(name, "metre") == 0
  46. || strcasecmp(name, "meters") == 0 || strcasecmp(name, "metres") == 0)
  47. units = U_METERS;
  48. else if (strcasecmp(name, "kilometer") == 0 || strcasecmp(name, "kilometre") == 0
  49. || strcasecmp(name, "kilometers") == 0 || strcasecmp(name, "kilometres") == 0)
  50. units = U_KILOMETERS;
  51. else if (strcasecmp(name, "acre") == 0 || strcasecmp(name, "acres") == 0)
  52. units = U_ACRES;
  53. else if (strcasecmp(name, "hectare") == 0 || strcasecmp(name, "hectares") == 0)
  54. units = U_HECTARES;
  55. else if (strcasecmp(name, "mile") == 0 || strcasecmp(name, "miles") == 0)
  56. units = U_MILES;
  57. else if (strcasecmp(name, "foot") == 0 || strcasecmp(name, "feet") == 0)
  58. units = U_FEET;
  59. else if (strcasecmp(name, "foot_us") == 0 || strcasecmp(name, "foot_uss") == 0)
  60. units = U_USFEET;
  61. else if (strcasecmp(name, "degree") == 0 || strcasecmp(name, "degrees") == 0)
  62. units = U_DEGREES;
  63. else
  64. units = U_UNKNOWN;
  65. }
  66. return G_get_units_name(units, plural, FALSE);
  67. }
  68. /*!
  69. \brief Query cartographic projection for the current location
  70. Returns a pointer to a string which is a printable name for
  71. projection code <i>proj</i> (as returned by G_projection). Returns
  72. NULL if <i>proj</i> is not a valid projection.
  73. \return projection name
  74. */
  75. const char *G_database_projection_name(void)
  76. {
  77. int n;
  78. const char *name;
  79. switch (n = G_projection()) {
  80. case PROJECTION_XY:
  81. case PROJECTION_UTM:
  82. case PROJECTION_LL:
  83. return G__projection_name(n);
  84. }
  85. name = lookup_proj("name");
  86. if (!name)
  87. return _("Unknown projection");
  88. return name;
  89. }
  90. /*!
  91. \brief Conversion to meters
  92. Returns a factor which converts the grid unit to meters (by
  93. multiplication). If the database is not metric (eg. imagery) then
  94. 0.0 is returned.
  95. \return value
  96. */
  97. double G_database_units_to_meters_factor(void)
  98. {
  99. const char *unit;
  100. const char *buf;
  101. double factor;
  102. int n;
  103. /* TODO: sync with definitions in ../proj/units.table */
  104. static const struct
  105. {
  106. char *unit;
  107. double factor;
  108. } table[] = {
  109. {"unit", 1.0},
  110. {"meter", 1.0},
  111. {"foot", .3048},
  112. {"foot_us", 1200/3937.},
  113. {"inch", .0254},
  114. {NULL, 0.0}
  115. };
  116. factor = 0.0;
  117. buf = lookup_units("meters");
  118. if (buf)
  119. sscanf(buf, "%lf", &factor);
  120. if (factor <= 0.0) {
  121. unit = G_database_unit_name(0);
  122. for (n = 0; table[n].unit; n++)
  123. if (equal(unit, table[n].unit)) {
  124. factor = table[n].factor;
  125. break;
  126. }
  127. }
  128. return factor;
  129. }
  130. /*!
  131. \brief Get datum name for the current location
  132. Returns a pointer to the name of the map datum of the current
  133. database. If there is no map datum explicitely associated with the
  134. acutal database, the standard map datum WGS84 is returned, on error
  135. a NULL pointer is returned.
  136. \return datum name
  137. */
  138. const char *G_database_datum_name(void)
  139. {
  140. const char *name;
  141. char buf[256], params[256];
  142. int datumstatus;
  143. name = lookup_proj("datum");
  144. if (name)
  145. return name;
  146. else if (!proj_info)
  147. return NULL;
  148. else
  149. datumstatus = G_get_datumparams_from_projinfo(proj_info, buf, params);
  150. if (datumstatus == 2)
  151. return G_store(params);
  152. else
  153. return NULL;
  154. }
  155. /*!
  156. \brief Get ellipsoid name for the current location
  157. \return pointer to valid name if ok
  158. \return NULL on error
  159. */
  160. const char *G_database_ellipse_name(void)
  161. {
  162. const char *name;
  163. name = lookup_proj("ellps");
  164. if (!name) {
  165. char buf[256];
  166. double a, es;
  167. G_get_ellipsoid_parameters(&a, &es);
  168. sprintf(buf, "a=%.16g es=%.16g", a, es);
  169. name = G_store(buf);
  170. }
  171. /* strcpy (name, "Unknown ellipsoid"); */
  172. return name;
  173. }
  174. /*!
  175. \brief Get EPGS code for the current location
  176. \return pointer to valid EPSG code on success
  177. \return NULL on error
  178. */
  179. const char *G_database_epsg_code(void)
  180. {
  181. return lookup_epsg();
  182. }
  183. const char *lookup_proj(const char *key)
  184. {
  185. init();
  186. return G_find_key_value(key, proj_info);
  187. }
  188. const char *lookup_units(const char *key)
  189. {
  190. init();
  191. return G_find_key_value(key, proj_units);
  192. }
  193. const char *lookup_epsg()
  194. {
  195. init();
  196. return G_find_key_value("epsg", proj_epsg);
  197. }
  198. int equal(const char *a, const char *b)
  199. {
  200. if (a == NULL || b == NULL)
  201. return a == b;
  202. while (*a && *b)
  203. if (lower(*a++) != lower(*b++))
  204. return 0;
  205. if (*a || *b)
  206. return 0;
  207. return 1;
  208. }
  209. int lower(char c)
  210. {
  211. if (c >= 'A' && c <= 'Z')
  212. c += 'a' - 'A';
  213. return c;
  214. }