GRASS 8 Programmer's Manual  8.5.0dev(2025)-c070206eb1
ellipse.c
Go to the documentation of this file.
1 /*!
2  \file lib/proj/ellipse.c
3 
4  \brief GProj library - Functions for reading datum parameters from the
5  location database
6 
7  \author Paul Kelly <paul-grass stjohnspoint.co.uk>
8 
9  (C) 2003-2008 by the GRASS Development Team
10 
11  This program is free software under the GNU General Public
12  License (>=v2). Read the file COPYING that comes with GRASS
13  for details.
14  */
15 
16 #include <unistd.h>
17 #include <ctype.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include <math.h> /* for sqrt() */
21 #include <grass/gis.h>
22 #include <grass/glocale.h>
23 #include <grass/gprojects.h>
24 #include "local_proto.h"
25 
26 static int get_a_e2_rf(const char *, const char *, double *, double *,
27  double *);
28 
29 /*!
30  * \brief Get the ellipsoid parameters from the database.
31  *
32  * If the PROJECTION_FILE exists in the PERMANENT mapset, read info from
33  * that file, otherwise return WGS 84 values.
34  *
35  * Dies with diagnostic if there is an error.
36  *
37  * \param[out] a semi-major axis
38  * \param[out] e2 first eccentricity squared
39  * \param[out] rf reciprocal of the ellipsoid flattening term
40  *
41  * \return 1 on success
42  * \return 0 default values used.
43  */
44 int GPJ_get_ellipsoid_params(double *a, double *e2, double *rf)
45 {
46  int ret;
47  struct Key_Value *proj_keys = G_get_projinfo();
48 
49  if (proj_keys == NULL)
50  proj_keys = G_create_key_value();
51 
52  ret = GPJ__get_ellipsoid_params(proj_keys, a, e2, rf);
53  G_free_key_value(proj_keys);
54 
55  return ret;
56 }
57 
58 /*!
59  * \brief Get the ellipsoid parameters from proj keys structure.
60  *
61  * If the PROJECTION_FILE exists in the PERMANENT mapset, read info from
62  * that file, otherwise return WGS 84 values.
63  *
64  * Dies with diagnostic if there is an error.
65  *
66  * \param proj_keys proj definition
67  * \param[out] a semi-major axis
68  * \param[out] e2 first eccentricity squared
69  * \param[out] rf reciprocal of the ellipsoid flattening term
70  *
71  * \return 1 on success
72  * \return 0 default values used.
73  */
74 int GPJ__get_ellipsoid_params(const struct Key_Value *proj_keys, double *a,
75  double *e2, double *rf)
76 {
77  struct gpj_ellps estruct;
78  struct gpj_datum dstruct;
79  const char *str, *str3;
80  char *str1, *ellps;
81 
82  str = G_find_key_value("datum", proj_keys);
83 
84  if ((str != NULL) && (GPJ_get_datum_by_name(str, &dstruct) > 0)) {
85  /* If 'datum' key is present, look up correct ellipsoid
86  * from datum.table */
87 
88  ellps = G_store(dstruct.ellps);
89  GPJ_free_datum(&dstruct);
90  }
91  else
92  /* else use ellipsoid defined in PROJ_INFO */
93  ellps = G_store(G_find_key_value("ellps", proj_keys));
94 
95  if (ellps != NULL && *ellps) {
96  if (GPJ_get_ellipsoid_by_name(ellps, &estruct) < 0)
97  G_fatal_error(_("Invalid ellipsoid <%s> in file"), ellps);
98 
99  *a = estruct.a;
100  *e2 = estruct.es;
101  *rf = estruct.rf;
102  GPJ_free_ellps(&estruct);
103  G_free(ellps);
104 
105  return 1;
106  }
107  else {
108  if (ellps) /* *ellps = '\0' */
109  G_free(ellps);
110 
111  str3 = G_find_key_value("a", proj_keys);
112  if (str3 != NULL) {
113  char *str4;
114 
115  G_asprintf(&str4, "a=%s", str3);
116  if ((str3 = G_find_key_value("es", proj_keys)) != NULL)
117  G_asprintf(&str1, "e=%s", str3);
118  else if ((str3 = G_find_key_value("f", proj_keys)) != NULL)
119  G_asprintf(&str1, "f=1/%s", str3);
120  else if ((str3 = G_find_key_value("rf", proj_keys)) != NULL)
121  G_asprintf(&str1, "f=1/%s", str3);
122  else if ((str3 = G_find_key_value("b", proj_keys)) != NULL)
123  G_asprintf(&str1, "b=%s", str3);
124  else
125  G_fatal_error(_("No secondary ellipsoid descriptor "
126  "(rf, es or b) in file"));
127 
128  if (get_a_e2_rf(str4, str1, a, e2, rf) == 0)
129  G_fatal_error(_("Invalid ellipsoid descriptors "
130  "(a, rf, es or b) in file"));
131  return 1;
132  }
133  else {
134  str = G_find_key_value("proj", proj_keys);
135  if ((str == NULL) || (strcmp(str, "ll") == 0)) {
136  *a = 6378137.0;
137  *e2 = .006694385;
138  *rf = 298.257223563;
139  return 0;
140  }
141  else {
142  G_fatal_error(_("No ellipsoid info given in file"));
143  }
144  }
145  }
146  return 1;
147 }
148 
149 /*!
150  * \brief Looks up ellipsoid in ellipsoid table and returns the a, e2
151  * parameters for the ellipsoid.
152  *
153  * \param name ellipsoid name
154  * \param[out] estruct ellipsoid
155  *
156  * \return 1 on success
157  * \return -1 if not found in table
158  */
159 int GPJ_get_ellipsoid_by_name(const char *name, struct gpj_ellps *estruct)
160 {
161  struct ellps_list *list, *listhead;
162 
163  list = listhead = read_ellipsoid_table(0);
164 
165  while (list != NULL) {
166  if (G_strcasecmp(name, list->name) == 0) {
167  estruct->name = G_store(list->name);
168  estruct->longname = G_store(list->longname);
169  estruct->a = list->a;
170  estruct->es = list->es;
171  estruct->rf = list->rf;
172  free_ellps_list(listhead);
173  return 1;
174  }
175  list = list->next;
176  }
177  free_ellps_list(listhead);
178  return -1;
179 }
180 
181 int get_a_e2_rf(const char *s1, const char *s2, double *a, double *e2,
182  double *recipf)
183 {
184  double b, f;
185 
186  if (sscanf(s1, "a=%lf", a) != 1)
187  return 0;
188 
189  if (*a <= 0.0)
190  return 0;
191 
192  if (sscanf(s2, "e=%lf", e2) == 1) {
193  f = 1.0 - sqrt(1.0 - *e2);
194  *recipf = 1.0 / f;
195  return (*e2 >= 0.0);
196  }
197 
198  if (sscanf(s2, "f=1/%lf", recipf) == 1) {
199  if (*recipf <= 0.0)
200  return 0;
201  f = 1.0 / *recipf;
202  *e2 = f * (2 - f);
203  return (*e2 >= 0.0);
204  }
205 
206  if (sscanf(s2, "b=%lf", &b) == 1) {
207  if (b <= 0.0)
208  return 0;
209  if (b == *a) {
210  f = 0.0;
211  *e2 = 0.0;
212  }
213  else {
214  f = (*a - b) / *a;
215  *e2 = f * (2 - f);
216  }
217  *recipf = 1.0 / f;
218  return (*e2 >= 0.0);
219  }
220  return 0;
221 }
222 
223 struct ellps_list *read_ellipsoid_table(int fatal)
224 {
225  FILE *fd;
226  char file[GPATH_MAX];
227  char buf[4096];
228  char name[100], descr[1024], buf1[1024], buf2[1024];
229  char badlines[1024];
230  int line;
231  int err;
232  struct ellps_list *current = NULL, *outputlist = NULL;
233  double a, e2, rf;
234 
235  snprintf(file, sizeof(file), "%s%s", G_gisbase(), ELLIPSOIDTABLE);
236  fd = fopen(file, "r");
237 
238  if (!fd) {
239  (fatal ? G_fatal_error : G_warning)(
240  _("Unable to open ellipsoid table file <%s>"), file);
241  return NULL;
242  }
243 
244  err = 0;
245  *badlines = 0;
246  for (line = 1; G_getl2(buf, sizeof buf, fd); line++) {
247  G_strip(buf);
248  if (*buf == 0 || *buf == '#')
249  continue;
250 
251  if (sscanf(buf, "%s \"%1023[^\"]\" %s %s", name, descr, buf1, buf2) !=
252  4) {
253  err++;
254  snprintf(buf, sizeof(buf), " %d", line);
255  if (*badlines)
256  strcat(badlines, ",");
257  strcat(badlines, buf);
258  continue;
259  }
260 
261  if (get_a_e2_rf(buf1, buf2, &a, &e2, &rf) ||
262  get_a_e2_rf(buf2, buf1, &a, &e2, &rf)) {
263  if (current == NULL)
264  current = outputlist = G_malloc(sizeof(struct ellps_list));
265  else
266  current = current->next = G_malloc(sizeof(struct ellps_list));
267  current->name = G_store(name);
268  current->longname = G_store(descr);
269  current->a = a;
270  current->es = e2;
271  current->rf = rf;
272  current->next = NULL;
273  }
274  else {
275  err++;
276  snprintf(buf, sizeof(buf), " %d", line);
277  if (*badlines)
278  strcat(badlines, ",");
279  strcat(badlines, buf);
280  continue;
281  }
282  }
283 
284  fclose(fd);
285 
286  if (!err)
287  return outputlist;
288 
289  (fatal ? G_fatal_error : G_warning)(
290  n_(("Line%s of ellipsoid table file <%s> is invalid"),
291  ("Lines%s of ellipsoid table file <%s> are invalid"), err),
292  badlines, file);
293 
294  return outputlist;
295 }
296 
297 /*!
298  \brief Free ellipsoid data structure.
299 
300  \param estruct data structure to be freed
301  */
302 void GPJ_free_ellps(struct gpj_ellps *estruct)
303 {
304  G_free(estruct->name);
305  G_free(estruct->longname);
306  return;
307 }
308 
309 void free_ellps_list(struct ellps_list *elist)
310 {
311  struct ellps_list *old;
312 
313  while (elist != NULL) {
314  G_free(elist->name);
315  G_free(elist->longname);
316  old = elist;
317  elist = old->next;
318  G_free(old);
319  }
320 
321  return;
322 }
#define NULL
Definition: ccmath.h:32
int G_getl2(char *, int, FILE *)
Gets a line of text from a file of any pedigree.
Definition: getl.c:60
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:147
struct Key_Value * G_get_projinfo(void)
Gets projection information for location.
Definition: get_projinfo.c:61
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
Definition: key_value1.c:85
#define G_malloc(n)
Definition: defs/gis.h:94
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
Definition: key_value1.c:104
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition: strings.c:300
int G_asprintf(char **, const char *,...) __attribute__((format(printf
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
Definition: strings.c:47
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition: gisbase.c:39
struct Key_Value * G_create_key_value(void)
Allocate and initialize Key_Value structure.
Definition: key_value1.c:23
char * G_store(const char *)
Copy string to allocated memory.
Definition: strings.c:87
void GPJ_free_datum(struct gpj_datum *)
Free the memory used for the strings in a gpj_datum struct.
Definition: proj/datum.c:396
int GPJ_get_datum_by_name(const char *, struct gpj_datum *)
Look up a string in datum.table file to see if it is a valid datum name and if so place its informati...
Definition: proj/datum.c:38
int GPJ_get_ellipsoid_by_name(const char *name, struct gpj_ellps *estruct)
Looks up ellipsoid in ellipsoid table and returns the a, e2 parameters for the ellipsoid.
Definition: ellipse.c:159
int GPJ__get_ellipsoid_params(const struct Key_Value *proj_keys, double *a, double *e2, double *rf)
Get the ellipsoid parameters from proj keys structure.
Definition: ellipse.c:74
struct ellps_list * read_ellipsoid_table(int fatal)
Definition: ellipse.c:223
void free_ellps_list(struct ellps_list *elist)
Definition: ellipse.c:309
void GPJ_free_ellps(struct gpj_ellps *estruct)
Free ellipsoid data structure.
Definition: ellipse.c:302
int GPJ_get_ellipsoid_params(double *a, double *e2, double *rf)
Get the ellipsoid parameters from the database.
Definition: ellipse.c:44
#define GPATH_MAX
Definition: gis.h:199
#define n_(strs, strp, num)
Definition: glocale.h:11
#define _(str)
Definition: glocale.h:10
#define ELLIPSOIDTABLE
Definition: gprojects.h:64
#define file
const char * name
Definition: named_colr.c:6
double b
Definition: r_raster.c:39
struct list * list
Definition: read_list.c:24
Definition: gis.h:534
char * ellps
Definition: gprojects.h:86
double es
Definition: gprojects.h:109
char * name
Definition: gprojects.h:108
double a
Definition: gprojects.h:109
double rf
Definition: gprojects.h:109
char * longname
Definition: gprojects.h:108
Definition: manage.h:4
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:216