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