GRASS 8 Programmer's Manual 8.6.0dev(2026)-0f6a7341fc
Loading...
Searching...
No Matches
get_ellipse.c
Go to the documentation of this file.
1/*!
2 \file lib/gis/get_ellipse.c
3
4 \brief GIS Library - Getting ellipsoid parameters from the database.
5
6 This routine returns the ellipsoid parameters from the database.
7 If the PROJECTION_FILE exists in the PERMANENT mapset, read info
8 from that file, otherwise return WGS 84 values.
9
10 New 05/2000 by al: for datum shift the f parameter is needed too.
11 This all is not a clean design, but it keeps backward-
12 compatibility.
13 Looks up ellipsoid in ellipsoid table and returns the
14 a, e2 and f parameters for the ellipsoid
15
16 SPDX-FileCopyrightText: 2001-2009 GRASS Development Team
17 SPDX-License-Identifier: GPL-2.0-or-later
18
19 \author CERL
20 */
21
22#include <unistd.h>
23#include <ctype.h>
24#include <string.h>
25#include <stdlib.h>
26#include <math.h> /* for sqrt() */
27#include <grass/gis.h>
28#include <grass/glocale.h>
29
30static const char PERMANENT[] = "PERMANENT";
31
32static struct table {
33 struct ellipse {
34 char *name;
35 char *descr;
36 double a;
37 double e2;
38 double f;
39 } *ellipses;
40 int count;
41 int size;
42 int initialized;
43} table;
44
45/* static int get_a_e2 (char *, char *, double *,double *); */
46static int get_a_e2_f(const char *, const char *, double *, double *, double *);
47static int compare_ellipse_names(const void *, const void *);
48static int get_ellipsoid_parameters(struct Key_Value *, double *, double *);
49
50/*!
51 * \brief get ellipsoid parameters
52 *
53 * This routine returns the semi-major axis <b>a</b> (in meters) and
54 * the eccentricity squared <b>e2</b> for the ellipsoid associated
55 * with the database. If there is no ellipsoid explicitly associated
56 * with the database, it returns the values for the WGS 84 ellipsoid.
57 *
58 * \param[out] a semi-major axis
59 * \param[out] e2 eccentricity squared
60 *
61 * \return 1 success
62 * \return 0 default values used
63 */
64int G_get_ellipsoid_parameters(double *a, double *e2)
65{
66 int stat;
67 char ipath[GPATH_MAX];
68 struct Key_Value *proj_keys;
69
71
73
74 if (access(ipath, 0) != 0) {
75 *a = 6378137.0;
76 *e2 = .006694385;
77 return 0;
78 }
79
81
82 stat = get_ellipsoid_parameters(proj_keys, a, e2);
83
85
86 return stat;
87}
88
89/*!
90 * \brief Get ellipsoid parameters by name
91 *
92 * This routine returns the semi-major axis <i>a</i> (in meters) and
93 * eccentricity squared <i>e2</i> for the named ellipsoid.
94 *
95 * \param name ellipsoid name
96 * \param[out] a semi-major axis
97 * \param[out] e2 eccentricity squared
98 *
99 * \return 1 on success
100 * \return 0 if ellipsoid not found
101 */
102int G_get_ellipsoid_by_name(const char *name, double *a, double *e2)
103{
104 int i;
105
107
108 for (i = 0; i < table.count; i++) {
109 if (G_strcasecmp(name, table.ellipses[i].name) == 0) {
110 *a = table.ellipses[i].a;
111 *e2 = table.ellipses[i].e2;
112 return 1;
113 }
114 }
115 return 0;
116}
117
118/*!
119 * \brief Get ellipsoid name
120 *
121 * This function returns a pointer to the short name for the
122 * <i>n</i><i>th</i> ellipsoid. If <i>n</i> is less than 0 or greater
123 * than the number of known ellipsoids, it returns a NULL pointer.
124 *
125 * \param n ellipsoid identificator
126 *
127 * \return ellipsoid name
128 * \return NULL if no ellipsoid found
129 */
130const char *G_ellipsoid_name(int n)
131{
133 return n >= 0 && n < table.count ? table.ellipses[n].name : NULL;
134}
135
136/*!
137 * \brief Get spheroid parameters by name
138 *
139 * This function returns the semi-major axis <i>a</i> (in meters), the
140 * eccentricity squared <i>e2</i> and the inverse flattening <i>f</i>
141 * for the named ellipsoid.
142 *
143 * \param name spheroid name
144 * \param[out] a semi-major axis
145 * \param[out] e2 eccentricity squared
146 * \param[out] f inverse flattening
147 *
148 * \return 1 on success
149 * \return 0 if no spheroid found
150 */
151int G_get_spheroid_by_name(const char *name, double *a, double *e2, double *f)
152{
153 int i;
154
156
157 for (i = 0; i < table.count; i++) {
158 if (G_strcasecmp(name, table.ellipses[i].name) == 0) {
159 *a = table.ellipses[i].a;
160 *e2 = table.ellipses[i].e2;
161 *f = table.ellipses[i].f;
162 return 1;
163 }
164 }
165 return 0;
166}
167
168/*!
169 * \brief Get description for nth ellipsoid
170 *
171 * This function returns a pointer to the description text for the
172 * <i>n</i>th ellipsoid. If <i>n</i> is less than 0 or greater
173 * than the number of known ellipsoids, it returns a NULL pointer.
174 *
175 * \param n ellipsoid identificator
176 *
177 * \return pointer to ellipsoid description
178 * \return NULL if no ellipsoid found
179 */
180const char *G_ellipsoid_description(int n)
181{
183 return n >= 0 && n < table.count ? table.ellipses[n].descr : NULL;
184}
185
186static int get_a_e2_f(const char *s1, const char *s2, double *a, double *e2,
187 double *f)
188{
189 double b, recipf;
190
191 if (sscanf(s1, "a=%lf", a) != 1)
192 return 0;
193
194 if (*a <= 0.0)
195 return 0;
196
197 if (sscanf(s2, "e=%lf", e2) == 1) {
198 *f = (double)1.0 / -sqrt(((double)1.0 - *e2)) + (double)1.0;
199 return (*e2 >= 0.0);
200 }
201
202 if (sscanf(s2, "f=1/%lf", f) == 1) {
203 if (*f <= 0.0)
204 return 0;
205 recipf = (double)1.0 / (*f);
206 *e2 = recipf + recipf - recipf * recipf;
207 return (*e2 >= 0.0);
208 }
209
210 if (sscanf(s2, "b=%lf", &b) == 1) {
211 if (b <= 0.0)
212 return 0;
213 if (b == *a) {
214 *f = 0.0;
215 *e2 = 0.0;
216 }
217 else {
218 recipf = ((*a) - b) / (*a);
219 *f = (double)1.0 / recipf;
220 *e2 = recipf + recipf - recipf * recipf;
221 }
222 return (*e2 >= 0.0);
223 }
224 return 0;
225}
226
227static int compare_ellipse_names(const void *pa, const void *pb)
228{
229 const struct ellipse *a = pa;
230 const struct ellipse *b = pb;
231
232 return G_strcasecmp(a->name, b->name);
233}
234
235/*!
236 \brief Read ellipsoid table
237
238 \param fatal non-zero value for G_fatal_error(), otherwise
239 G_warning() is used
240
241 \return 1 on success
242 \return 0 on error
243 */
245{
246 FILE *fd;
247 char file[GPATH_MAX];
248 char buf[1024];
249 char badlines[256];
250 int line;
251 int err;
252
253 if (G_is_initialized(&table.initialized))
254 return 1;
255
256 snprintf(file, sizeof(file), "%s/etc/proj/ellipse.table", G_gisbase());
257 fd = fopen(file, "r");
258
259 if (fd == NULL) {
261 _("Unable to open ellipsoid table file <%s>"), file);
262 G_initialize_done(&table.initialized);
263 return 0;
264 }
265
266 err = 0;
267 *badlines = 0;
268 for (line = 1; G_getl2(buf, sizeof buf, fd); line++) {
269 char name[100], descr[100], buf1[100], buf2[100];
270 struct ellipse *e;
271
272 G_strip(buf);
273 if (*buf == 0 || *buf == '#')
274 continue;
275
276 if (sscanf(buf, "%s \"%99[^\"]\" %s %s", name, descr, buf1, buf2) !=
277 4) {
278 err++;
279 snprintf(buf, sizeof(buf), " %d", line);
280 if (*badlines)
281 G_strlcat(badlines, ",", sizeof(badlines));
282 G_strlcat(badlines, buf, sizeof(badlines));
283 continue;
284 }
285
286 if (table.count >= table.size) {
287 table.size += 60;
288 table.ellipses =
289 G_realloc(table.ellipses, table.size * sizeof(struct ellipse));
290 }
291
292 e = &table.ellipses[table.count];
293
294 e->name = G_store(name);
295 e->descr = G_store(descr);
296
297 if (get_a_e2_f(buf1, buf2, &e->a, &e->e2, &e->f) ||
298 get_a_e2_f(buf2, buf1, &e->a, &e->e2, &e->f))
299 table.count++;
300 else {
301 err++;
302 snprintf(buf, sizeof(buf), " %d", line);
303 if (*badlines)
304 G_strlcat(badlines, ",", sizeof(badlines));
305 G_strlcat(badlines, buf, sizeof(badlines));
306 continue;
307 }
308 }
309
310 fclose(fd);
311
312 if (!err) {
313 /* over correct typed version */
314 qsort(table.ellipses, table.count, sizeof(struct ellipse),
315 compare_ellipse_names);
316 G_initialize_done(&table.initialized);
317 return 1;
318 }
319
321 n_(("Line%s of ellipsoid table file <%s> is invalid"),
322 ("Lines%s of ellipsoid table file <%s> are invalid"), err),
323 badlines, file);
324
325 G_initialize_done(&table.initialized);
326
327 return 0;
328}
329
330static int get_ellipsoid_parameters(struct Key_Value *proj_keys, double *a,
331 double *e2)
332{
333 const char *str, *str1;
334
335 if (!proj_keys) {
336 return -1;
337 }
338
339 if ((str = G_find_key_value("ellps", proj_keys)) != NULL) {
340 if (strncmp(str, "sphere", 6) == 0) {
341 str = G_find_key_value("a", proj_keys);
342 if (str != NULL) {
343 if (sscanf(str, "%lf", a) != 1)
344 G_fatal_error(_("Invalid a: field '%s' in file %s in <%s>"),
346 }
347 else
348 *a = 6370997.0;
349
350 *e2 = 0.0;
351
352 return 0;
353 }
354 else {
355 if (G_get_ellipsoid_by_name(str, a, e2) == 0)
356 G_fatal_error(_("Invalid ellipsoid '%s' in file %s in <%s>"),
358 else
359 return 1;
360 }
361 }
362 else {
363 str = G_find_key_value("a", proj_keys);
365 if ((str != NULL) && (str1 != NULL)) {
366 if (sscanf(str, "%lf", a) != 1)
367 G_fatal_error(_("Invalid a: field '%s' in file %s in <%s>"),
369 if (sscanf(str1, "%lf", e2) != 1)
370 G_fatal_error(_("Invalid es: field '%s' in file %s in <%s>"),
372
373 return 1;
374 }
375 else {
376 str = G_find_key_value("proj", proj_keys);
377 if ((str == NULL) || (strcmp(str, "ll") == 0)) {
378 *a = 6378137.0;
379 *e2 = .006694385;
380 return 0;
381 }
382 else
383 G_fatal_error(_("No ellipsoid info given in file %s in <%s>"),
385 }
386 }
387
388 return 1;
389}
#define NULL
Definition ccmath.h:32
AMI_err name(char **stream_name)
Definition ami_stream.h:426
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition getl.c:58
#define G_realloc(p, n)
Definition defs/gis.h:138
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition gisbase.c:39
char * G_file_name(char *, const char *, const char *, const char *)
Builds full path names to GIS data files.
Definition file_name.c:59
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
Definition key_value1.c:102
struct Key_Value * G_read_key_value_file(const char *)
Read key/values pairs from file.
Definition key_value3.c:53
size_t G_strlcat(char *, const char *, size_t)
Size-bounded string concatenation.
Definition strlcat.c:59
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition strings.c:298
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition key_value1.c:83
int G_is_initialized(int *)
Definition counter.c:60
void G_initialize_done(int *)
Definition counter.c:77
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition strings.c:45
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
int G_read_ellipsoid_table(int fatal)
Read ellipsoid table.
const char * G_ellipsoid_description(int n)
Get description for nth ellipsoid.
int G_get_spheroid_by_name(const char *name, double *a, double *e2, double *f)
Get spheroid parameters by name.
const char * G_ellipsoid_name(int n)
Get ellipsoid name.
int G_get_ellipsoid_parameters(double *a, double *e2)
get ellipsoid parameters
Definition get_ellipse.c:64
int G_get_ellipsoid_by_name(const char *name, double *a, double *e2)
Get ellipsoid parameters by name.
#define PERMANENT
#define PROJECTION_FILE
Definition gis.h:130
#define GPATH_MAX
Definition gis.h:196
#define n_(strs, strp, num)
Definition glocale.h:11
#define _(str)
Definition glocale.h:10
int count
#define file
const char * name
Definition named_colr.c:6
double b
Definition r_raster.c:37
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
#define access
Definition unistd.h:7