GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-602118adcc
proj3.c
Go to the documentation of this file.
1 /*!
2  \file lib/gis/proj3.c
3 
4  \brief GIS Library - Projection support (database)
5 
6  (C) 2001-2014 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Original author CERL
12  */
13 
14 /* TODO: the G_database_*() functions should be renamed to G_location_*()
15  * because they apply to a GRASS location, not to a GRASS database */
16 
17 #include <string.h>
18 #include <grass/gis.h>
19 #include <grass/glocale.h>
20 
21 static const char *lookup_proj(const char *);
22 static const char *lookup_units(const char *);
23 static const char *lookup_epsg(void);
24 static int equal(const char *, const char *);
25 static int lower(char);
26 
27 static int initialized;
28 static struct Key_Value *proj_info, *proj_units, *proj_epsg;
29 
30 static void init(void)
31 {
32  if (G_is_initialized(&initialized))
33  return;
34 
35  proj_info = G_get_projinfo();
36  proj_units = G_get_projunits();
37  proj_epsg = G_get_projepsg();
38 
39  G_initialize_done(&initialized);
40 }
41 
42 /*!
43  \brief Get units (localized) name for the current location
44 
45  Returns a string describing the database grid units. It returns a
46  plural form (eg. 'feet') if <i>plural</i> is non-zero. Otherwise it
47  returns a singular form (eg. 'foot').
48 
49  \param plural plural form if non-zero
50 
51  \return localized units name
52  */
53 const char *G_database_unit_name(int plural)
54 {
55  int units;
56 
57  units = G_database_unit();
58  return G_get_units_name(units, plural, FALSE);
59 }
60 
61 /*!
62  \brief Get units id for the current location
63 
64  \return units id
65  */
66 int G_database_unit(void)
67 {
68  int units;
69  const char *name;
70 
72 
73  if (units == U_UNDEFINED) {
74  name = lookup_units("unit");
75  if (!name)
76  return U_UNKNOWN;
77 
78  if (strcasecmp(name, "meter") == 0 || strcasecmp(name, "metre") == 0 ||
79  strcasecmp(name, "meters") == 0 || strcasecmp(name, "metres") == 0)
80  units = U_METERS;
81  else if (strcasecmp(name, "kilometer") == 0 ||
82  strcasecmp(name, "kilometre") == 0 ||
83  strcasecmp(name, "kilometers") == 0 ||
84  strcasecmp(name, "kilometres") == 0)
85  units = U_KILOMETERS;
86  else if (strcasecmp(name, "acre") == 0 ||
87  strcasecmp(name, "acres") == 0)
88  units = U_ACRES;
89  else if (strcasecmp(name, "hectare") == 0 ||
90  strcasecmp(name, "hectares") == 0)
91  units = U_HECTARES;
92  else if (strcasecmp(name, "mile") == 0 ||
93  strcasecmp(name, "miles") == 0)
94  units = U_MILES;
95  else if (strcasecmp(name, "foot") == 0 || strcasecmp(name, "feet") == 0)
96  units = U_FEET;
97  else if (strcasecmp(name, "foot_us") == 0 ||
98  strcasecmp(name, "foot_uss") == 0)
99  units = U_USFEET;
100  else if (strcasecmp(name, "degree") == 0 ||
101  strcasecmp(name, "degrees") == 0)
102  units = U_DEGREES;
103  else
104  units = U_UNKNOWN;
105  }
106  return units;
107 }
108 
109 /*!
110  \brief Query cartographic projection for the current location
111 
112  Returns a pointer to a string which is a printable name for
113  projection code <i>proj</i> (as returned by G_projection). Returns
114  NULL if <i>proj</i> is not a valid projection.
115 
116  \return projection name
117  */
118 const char *G_database_projection_name(void)
119 {
120  int n;
121  const char *name;
122 
123  switch (n = G_projection()) {
124  case PROJECTION_XY:
125  case PROJECTION_UTM:
126  case PROJECTION_LL:
127  return G_projection_name(n);
128  }
129 
130  name = lookup_proj("name");
131  if (!name)
132  return _("Unknown projection");
133 
134  return name;
135 }
136 
137 /*!
138  \brief Conversion to meters
139 
140  Returns a factor which converts the grid unit to meters (by
141  multiplication). If the database is not metric (eg. imagery) then
142  0.0 is returned.
143 
144  \return value
145  */
147 {
148  const char *unit;
149  const char *buf;
150  double factor;
151  int n;
152 
153  /* TODO: sync with definitions in ../proj/units.table */
154  static const struct {
155  char *unit;
156  double factor;
157  } table[] = {{"unit", 1.0}, {"meter", 1.0},
158  {"foot", .3048}, {"foot_us", 1200 / 3937.},
159  {"inch", .0254}, {NULL, 0.0}};
160 
161  factor = 0.0;
162  buf = lookup_units("meters");
163  if (buf)
164  sscanf(buf, "%lf", &factor);
165  if (factor <= 0.0) {
166  unit = G_database_unit_name(0);
167  for (n = 0; table[n].unit; n++)
168  if (equal(unit, table[n].unit)) {
169  factor = table[n].factor;
170  break;
171  }
172  }
173  return factor;
174 }
175 
176 /*!
177  \brief Get datum name for the current location
178 
179  Returns a pointer to the name of the map datum of the current
180  database. If there is no map datum explicitly associated with the
181  actual database, the standard map datum WGS84 is returned, on error
182  a NULL pointer is returned.
183 
184  \return datum name
185  */
186 const char *G_database_datum_name(void)
187 {
188  const char *name;
189  char buf[256], params[256];
190  int datumstatus;
191 
192  name = lookup_proj("datum");
193  if (name)
194  return name;
195  else if (!proj_info)
196  return NULL;
197  else
198  datumstatus = G_get_datumparams_from_projinfo(proj_info, buf, params);
199 
200  if (datumstatus == 2)
201  return G_store(params);
202  else
203  return NULL;
204 }
205 
206 /*!
207  \brief Get ellipsoid name for the current location
208 
209  \return pointer to valid name if ok
210  \return NULL on error
211  */
212 const char *G_database_ellipse_name(void)
213 {
214  const char *name;
215 
216  name = lookup_proj("ellps");
217  if (!name) {
218  char buf[256];
219  double a, es;
220 
222  sprintf(buf, "a=%.16g es=%.16g", a, es);
223  name = G_store(buf);
224  }
225 
226  /* strcpy (name, "Unknown ellipsoid"); */
227  return name;
228 }
229 
230 /*!
231  \brief Get EPGS code for the current location
232 
233  \return pointer to valid EPSG code on success
234  \return NULL on error
235  */
236 const char *G_database_epsg_code(void)
237 {
238  return lookup_epsg();
239 }
240 
241 const char *lookup_proj(const char *key)
242 {
243  init();
244  return G_find_key_value(key, proj_info);
245 }
246 
247 const char *lookup_units(const char *key)
248 {
249  init();
250  return G_find_key_value(key, proj_units);
251 }
252 
253 const char *lookup_epsg(void)
254 {
255  init();
256  return G_find_key_value("epsg", proj_epsg);
257 }
258 
259 int equal(const char *a, const char *b)
260 {
261  if (a == NULL || b == NULL)
262  return a == b;
263  while (*a && *b)
264  if (lower(*a++) != lower(*b++))
265  return 0;
266  if (*a || *b)
267  return 0;
268  return 1;
269 }
270 
271 int lower(char c)
272 {
273  if (c >= 'A' && c <= 'Z')
274  c += 'a' - 'A';
275  return c;
276 }
void init(double work[])
Definition: as177.c:61
#define NULL
Definition: ccmath.h:32
struct Key_Value * G_get_projinfo(void)
Gets projection information for location.
Definition: get_projinfo.c:61
struct Key_Value * G_get_projunits(void)
Gets units information for location.
Definition: get_projinfo.c:32
int G_get_ellipsoid_parameters(double *, double *)
get ellipsoid parameters
Definition: get_ellipse.c:66
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition: key_value1.c:85
const char * G_get_units_name(int, int, int)
Get localized units name.
Definition: units.c:204
int G_projection_units(int)
Get projection units code (for internal use only)
Definition: proj2.c:32
int G_get_datumparams_from_projinfo(const struct Key_Value *, char *, char *)
Definition: gis/datum.c:107
const char * G_projection_name(int)
Get projection name.
Definition: proj2.c:55
int G_is_initialized(int *)
Definition: counter.c:60
void G_initialize_done(int *)
Definition: counter.c:77
struct Key_Value * G_get_projepsg(void)
Gets EPSG information for the current location.
Definition: get_projinfo.c:102
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
int G_projection(void)
Query cartographic projection.
Definition: proj1.c:32
#define PROJECTION_XY
Projection code - XY coordinate system (unreferenced data)
Definition: gis.h:124
#define U_UNDEFINED
List of units.
Definition: gis.h:104
#define U_FEET
Definition: gis.h:111
#define U_ACRES
Definition: gis.h:106
#define U_METERS
Definition: gis.h:109
#define U_DEGREES
Definition: gis.h:113
#define PROJECTION_UTM
Projection code - UTM.
Definition: gis.h:126
#define FALSE
Definition: gis.h:83
#define U_UNKNOWN
Definition: gis.h:105
#define U_HECTARES
Definition: gis.h:107
#define PROJECTION_LL
Projection code - Latitude-Longitude.
Definition: gis.h:130
#define U_USFEET
Definition: gis.h:114
#define U_MILES
Definition: gis.h:110
#define U_KILOMETERS
Definition: gis.h:108
#define _(str)
Definition: glocale.h:10
const char * name
Definition: named_colr.c:6
const char * G_database_epsg_code(void)
Get EPGS code for the current location.
Definition: proj3.c:236
const char * G_database_projection_name(void)
Query cartographic projection for the current location.
Definition: proj3.c:118
double G_database_units_to_meters_factor(void)
Conversion to meters.
Definition: proj3.c:146
const char * G_database_unit_name(int plural)
Get units (localized) name for the current location.
Definition: proj3.c:53
int G_database_unit(void)
Get units id for the current location.
Definition: proj3.c:66
const char * G_database_ellipse_name(void)
Get ellipsoid name for the current location.
Definition: proj3.c:212
const char * G_database_datum_name(void)
Get datum name for the current location.
Definition: proj3.c:186
double b
Definition: r_raster.c:39
Definition: gis.h:528