proj3.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*!
  2. \file gis/proj3.c
  3. \brief GIS Library - Projection support
  4. (C) 2001-2009 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 int equal(const char *, const char *);
  15. static int lower(char);
  16. static int initialized;
  17. static struct Key_Value *proj_info, *proj_units;
  18. static void init(void)
  19. {
  20. if (G_is_initialized(&initialized))
  21. return;
  22. proj_info = G_get_projinfo();
  23. proj_units = G_get_projunits();
  24. G_initialize_done(&initialized);
  25. }
  26. /*!
  27. * \brief Get database units
  28. *
  29. * Returns a string describing the database grid units. It returns a
  30. * plural form (eg. feet) if <i>plural</i> is true. Otherwise it
  31. * returns a singular form (eg. foot).
  32. *
  33. * \param plural plural form if true
  34. *
  35. * \return units name
  36. */
  37. const char *G_database_unit_name(int plural)
  38. {
  39. int n;
  40. const char *name;
  41. switch (n = G_projection()) {
  42. case PROJECTION_XY:
  43. case PROJECTION_UTM:
  44. case PROJECTION_LL:
  45. case PROJECTION_SP:
  46. return G__unit_name(G__projection_units(n), plural);
  47. }
  48. name = lookup_units(plural ? "units" : "unit");
  49. if (!name)
  50. return plural ? "units" : "unit";
  51. return name;
  52. }
  53. /*!
  54. * \brief Query cartographic projection
  55. *
  56. * Returns a pointer to a string which is a printable name for
  57. * projection code <i>proj</i> (as returned by G_projection). Returns
  58. * NULL if <i>proj</i> is not a valid projection.
  59. *
  60. * \return projection name
  61. */
  62. const char *G_database_projection_name(void)
  63. {
  64. int n;
  65. const char *name;
  66. switch (n = G_projection()) {
  67. case PROJECTION_XY:
  68. case PROJECTION_UTM:
  69. case PROJECTION_LL:
  70. case PROJECTION_SP:
  71. return G__projection_name(n);
  72. }
  73. name = lookup_proj("name");
  74. if (!name)
  75. return _("Unknown projection");
  76. return name;
  77. }
  78. /*!
  79. * \brief Conversion to meters
  80. *
  81. * Returns a factor which converts the grid unit to meters (by
  82. * multiplication). If the database is not metric (eg. imagery) then
  83. * 0.0 is returned.
  84. *
  85. * \return value
  86. */
  87. double G_database_units_to_meters_factor(void)
  88. {
  89. const char *unit;
  90. const char *buf;
  91. double factor;
  92. int n;
  93. static const struct
  94. {
  95. char *unit;
  96. double factor;
  97. } table[] = {
  98. {"unit", 1.0},
  99. {"meter", 1.0},
  100. {"foot", .3048},
  101. {"inch", .0254},
  102. {NULL, 0.0}
  103. };
  104. factor = 0.0;
  105. buf = lookup_units("meters");
  106. if (buf)
  107. sscanf(buf, "%lf", &factor);
  108. if (factor <= 0.0) {
  109. unit = G_database_unit_name(0);
  110. for (n = 0; table[n].unit; n++)
  111. if (equal(unit, table[n].unit)) {
  112. factor = table[n].factor;
  113. break;
  114. }
  115. }
  116. return factor;
  117. }
  118. /*!
  119. * \brief Get datum name for database
  120. *
  121. * Returns a pointer to the name of the map datum of the current
  122. * database. If there is no map datum explicitely associated with the
  123. * acutal database, the standard map datum WGS84 is returned, on error
  124. * a NULL pointer is returned.
  125. *
  126. * \return datum name
  127. */
  128. const char *G_database_datum_name(void)
  129. {
  130. const char *name;
  131. char buf[256], params[256];
  132. int datumstatus;
  133. name = lookup_proj("datum");
  134. if (name)
  135. return name;
  136. else if (!proj_info)
  137. return NULL;
  138. else
  139. datumstatus = G_get_datumparams_from_projinfo(proj_info, buf, params);
  140. if (datumstatus == 2)
  141. return G_store(params);
  142. else
  143. return NULL;
  144. }
  145. /*!
  146. \brief Get ellipsoid name of current database
  147. \return pointer to valid name if ok
  148. \return NULL on error
  149. */
  150. const char *G_database_ellipse_name(void)
  151. {
  152. const char *name;
  153. name = lookup_proj("ellps");
  154. if (!name) {
  155. char buf[256];
  156. double a, es;
  157. G_get_ellipsoid_parameters(&a, &es);
  158. sprintf(buf, "a=%.16g es=%.16g", a, es);
  159. name = G_store(buf);
  160. }
  161. /* strcpy (name, "Unknown ellipsoid"); */
  162. return name;
  163. }
  164. static const char *lookup_proj(const char *key)
  165. {
  166. init();
  167. return G_find_key_value(key, proj_info);
  168. }
  169. static const char *lookup_units(const char *key)
  170. {
  171. init();
  172. return G_find_key_value(key, proj_units);
  173. }
  174. static int equal(const char *a, const char *b)
  175. {
  176. if (a == NULL || b == NULL)
  177. return a == b;
  178. while (*a && *b)
  179. if (lower(*a++) != lower(*b++))
  180. return 0;
  181. if (*a || *b)
  182. return 0;
  183. return 1;
  184. }
  185. static int lower(char c)
  186. {
  187. if (c >= 'A' && c <= 'Z')
  188. c += 'a' - 'A';
  189. return c;
  190. }