GRASS GIS 8 Programmer's Manual 8.2.1RC1(2022)-exported
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
21static const char *lookup_proj(const char *);
22static const char *lookup_units(const char *);
23static const char *lookup_epsg();
24static int equal(const char *, const char *);
25static int lower(char);
26
27static int initialized;
28static struct Key_Value *proj_info, *proj_units, *proj_epsg;
29
30static 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*/
53const 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*/
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*/
184const 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*/
210const 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*/
234const char *G_database_epsg_code(void)
235{
236 return lookup_epsg();
237}
238
239const char *lookup_proj(const char *key)
240{
241 init();
242 return G_find_key_value(key, proj_info);
243}
244
245const char *lookup_units(const char *key)
246{
247 init();
248 return G_find_key_value(key, proj_units);
249}
250
251const char *lookup_epsg()
252{
253 init();
254 return G_find_key_value("epsg", proj_epsg);
255}
256
257int 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
269int lower(char c)
270{
271 if (c >= 'A' && c <= 'Z')
272 c += 'a' - 'A';
273 return c;
274}
void init(double work[])
Definition: as177.c:65
#define NULL
Definition: ccmath.h:32
void G_initialize_done(int *p)
Definition: counter.c:76
int G_is_initialized(int *p)
Definition: counter.c:59
#define FALSE
Definition: dbfopen.c:182
double b
int G_get_ellipsoid_parameters(double *a, double *e2)
get ellipsoid parameters
Definition: get_ellipse.c:67
struct Key_Value * G_get_projinfo(void)
Gets projection information for location.
Definition: get_projinfo.c:61
struct Key_Value * G_get_projepsg(void)
Gets EPSG information for the current location.
Definition: get_projinfo.c:102
struct Key_Value * G_get_projunits(void)
Gets units information for location.
Definition: get_projinfo.c:32
int G_get_datumparams_from_projinfo(const struct Key_Value *projinfo, char *datumname, char *params)
Definition: gis/datum.c:109
const char * G_find_key_value(const char *key, const struct Key_Value *kv)
Find given key (case sensitive)
Definition: key_value1.c:84
const char * name
Definition: named_colr.c:7
int G_projection(void)
Query cartographic projection.
Definition: proj1.c:32
int G_projection_units(int n)
Get projection units code (for internal use only)
Definition: proj2.c:32
const char * G_projection_name(int n)
Get projection name.
Definition: proj2.c:55
const char * G_database_epsg_code(void)
Get EPGS code for the current location.
Definition: proj3.c:234
double G_database_units_to_meters_factor(void)
Conversion to meters.
Definition: proj3.c:138
int G_database_unit()
Get units id for the current location.
Definition: proj3.c:65
const char * G_database_datum_name(void)
Get datum name for the current location.
Definition: proj3.c:184
const char * G_database_ellipse_name(void)
Get ellipsoid name for the current location.
Definition: proj3.c:210
const char * G_database_unit_name(int plural)
Get units (localized) name for the current location.
Definition: proj3.c:53
const char * G_database_projection_name(void)
Query cartographic projection for the current location.
Definition: proj3.c:110
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:87
const char * G_get_units_name(int units, int plural, int square)
Get localized units name.
Definition: units.c:203