1 /*
2 ****************************************************************************
3 *
4 * MODULE: gis library
5 * AUTHOR(S): Andreas Lange - andreas.lange@rhein-main.de
6 * Paul Kelly - paul-grass@stjohnspoint.co.uk
7 * PURPOSE: provide functions for reading datum parameters from the
8 * location database.
9 * COPYRIGHT: (C) 2000, 2003 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
17 #define DATUMTABLE "/etc/proj/datum.table"
18
19 #include <unistd.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include <stdlib.h>
23
24 #include <grass/gis.h>
25 #include <grass/glocale.h>
26
27 static struct table
28 {
29 struct datum
30 {
31 char *name; /* Short Name / acronym of map datum */
32 char *descr; /* Long Name for map datum */
33 char *ellps; /* acronym for ellipsoid used with this datum */
34 double dx; /* delta x */
35 double dy; /* delta y */
36 double dz; /* delta z */
37 } *datums;
38 int size;
39 int count;
40 int initialized;
41 } table;
42
43 static int compare_table_names(const void *, const void *);
44
G_get_datum_by_name(const char * name)45 int G_get_datum_by_name(const char *name)
46 {
47 int i;
48
49 G_read_datum_table();
50
51 for (i = 0; i < table.count; i++)
52 if (G_strcasecmp(name, table.datums[i].name) == 0)
53 return i;
54
55 return -1;
56 }
57
G_datum_name(int n)58 const char *G_datum_name(int n)
59 {
60 G_read_datum_table();
61
62 if (n < 0 || n >= table.count)
63 return NULL;
64
65 return table.datums[n].name;
66 }
67
G_datum_description(int n)68 const char *G_datum_description(int n)
69 {
70 G_read_datum_table();
71
72 if (n < 0 || n >= table.count)
73 return NULL;
74
75 return table.datums[n].descr;
76 }
77
G_datum_ellipsoid(int n)78 const char *G_datum_ellipsoid(int n)
79 {
80 G_read_datum_table();
81
82 if (n < 0 || n >= table.count)
83 return NULL;
84
85 return table.datums[n].ellps;
86 }
87
88 /***********************************************************
89 * G_get_datumparams_from_projinfo(projinfo, datumname, params)
90 * struct Key_Value *projinfo Set of key_value pairs containing
91 * projection information in PROJ_INFO file
92 * format
93 * char *datumname Pointer into which a string containing
94 * the datum name (if present) will be
95 * placed.
96 * char *params Pointer into which a string containing
97 * the datum parameters (if present) will
98 * be placed.
99 *
100 * Extract the datum transformation-related parameters from a
101 * set of general PROJ_INFO parameters.
102 * This function can be used to test if a location set-up
103 * supports datum transformation.
104 *
105 * returns: -1 error or no datum information found,
106 * 1 only datum name found, 2 params found
107 ************************************************************/
108
G_get_datumparams_from_projinfo(const struct Key_Value * projinfo,char * datumname,char * params)109 int G_get_datumparams_from_projinfo(const struct Key_Value *projinfo,
110 char *datumname, char *params)
111 {
112 int returnval = -1;
113
114 if (NULL != G_find_key_value("datum", projinfo)) {
115 sprintf(datumname, "%s", G_find_key_value("datum", projinfo));
116 returnval = 1;
117 }
118
119 if (G_find_key_value("datumparams", projinfo) != NULL) {
120 sprintf(params, "%s", G_find_key_value("datumparams", projinfo));
121 returnval = 2;
122 }
123 else if (G_find_key_value("nadgrids", projinfo) != NULL) {
124 sprintf(params, "nadgrids=%s",
125 G_find_key_value("nadgrids", projinfo));
126 returnval = 2;
127 }
128 else if (G_find_key_value("towgs84", projinfo) != NULL) {
129 sprintf(params, "towgs84=%s", G_find_key_value("towgs84", projinfo));
130 returnval = 2;
131 }
132 else if (G_find_key_value("dx", projinfo) != NULL
133 && G_find_key_value("dy", projinfo) != NULL
134 && G_find_key_value("dz", projinfo) != NULL) {
135 sprintf(params, "towgs84=%s,%s,%s",
136 G_find_key_value("dx", projinfo),
137 G_find_key_value("dy", projinfo),
138 G_find_key_value("dz", projinfo));
139 returnval = 2;
140 }
141
142 return returnval;
143
144 }
145
G_read_datum_table(void)146 void G_read_datum_table(void)
147 {
148 FILE *fd;
149 char file[GPATH_MAX];
150 char buf[1024];
151 int line;
152
153 if (G_is_initialized(&table.initialized))
154 return;
155
156 sprintf(file, "%s%s", G_gisbase(), DATUMTABLE);
157
158 fd = fopen(file, "r");
159 if (!fd) {
160 G_warning(_("unable to open datum table file: %s"), file);
161 G_initialize_done(&table.initialized);
162 return;
163 }
164
165 for (line = 1; G_getl2(buf, sizeof(buf), fd); line++) {
166 char name[100], descr[100], ellps[100];
167 struct datum *t;
168
169 G_strip(buf);
170 if (*buf == '\0' || *buf == '#')
171 continue;
172
173 if (table.count >= table.size) {
174 table.size += 50;
175 table.datums = G_realloc(table.datums, table.size * sizeof(struct datum));
176 }
177
178 t = &table.datums[table.count];
179
180 if (sscanf(buf, "%s \"%99[^\"]\" %s dx=%lf dy=%lf dz=%lf",
181 name, descr, ellps, &t->dx, &t->dy, &t->dz) != 6) {
182 G_warning(_("error in datum table file, line %d"), line);
183 continue;
184 }
185
186 t->name = G_store(name);
187 t->descr = G_store(descr);
188 t->ellps = G_store(ellps);
189
190 table.count++;
191 }
192
193 qsort(table.datums, table.count, sizeof(struct datum), compare_table_names);
194
195 G_initialize_done(&table.initialized);
196 }
197
compare_table_names(const void * aa,const void * bb)198 static int compare_table_names(const void *aa, const void *bb)
199 {
200 const struct datum *a = aa;
201 const struct datum *b = bb;
202
203 return G_strcasecmp(a->name, b->name);
204 }
205