GRASS 8 Programmer's Manual 8.6.0dev(2026)-4bb960b182
Loading...
Searching...
No Matches
proj/datum.c
Go to the documentation of this file.
1/**
2 \file lib/proj/datum.c
3
4 \brief GProj library - Functions for reading datum parameters from the
5location database
6
7 \author Andreas Lange <andreas.lange rhein-main.de>, Paul Kelly <paul-grass
8stjohnspoint.co.uk>
9
10 SPDX-FileCopyrightText: 2003-2008 GRASS Development Team
11 SPDX-License-Identifier: GPL-2.0-or-later
12**/
13
14#include <unistd.h>
15#include <string.h>
16#include <ctype.h>
17#include <stdlib.h>
18
19#include <grass/gis.h>
20#include <grass/glocale.h>
21#include <grass/gprojects.h>
22#include "local_proto.h"
23
24/**
25 * \brief Look up a string in datum.table file to see if it is a valid datum
26 * name and if so place its information into a gpj_datum struct
27 *
28 * \param name String containing datum name to look up
29 * \param dstruct gpj_datum struct into which datum parameters will be placed
30 * if found
31 *
32 * \return 1 if datum found, -1 if not
33 **/
34
36{
37 struct datum_list *list, *listhead;
38
40
41 while (list != NULL) {
42 if (G_strcasecmp(name, list->name) == 0) {
43 dstruct->name = G_store(list->name);
44 dstruct->longname = G_store(list->longname);
45 dstruct->ellps = G_store(list->ellps);
46 dstruct->dx = list->dx;
47 dstruct->dy = list->dy;
48 dstruct->dz = list->dz;
50 return 1;
51 }
52 list = list->next;
53 }
55 return -1;
56}
57
58/**
59 * \brief "Last resort" function to retrieve a "default" set of datum
60 * parameters for a datum (N.B. there really is no such thing as a
61 * catch-all default!)
62 *
63 * Kind of a "last resort" function as there really is no such thing
64 * as a default set of datum transformation parameters. Only should
65 * really be used where user interaction to choose a set of parameters
66 * is not desirable. Use of this function is not likely to result in
67 * selection of the optimum set of datum transformation parameters
68 * for the location
69 *
70 * \param name String containing GRASS datum name for which default
71 * parameters are to be retrieved
72 *
73 * \param params Pointer to a pointer which will have memory
74 * allocated and into which a string containing
75 * the datum parameters (if present) will
76 * be placed
77 *
78 * \return The number of possible parameter sets GRASS knows
79 * about for this datum
80 *
81 **/
82
83int GPJ_get_default_datum_params_by_name(const char *name, char **params)
84{
85 struct gpj_datum_transform_list *list, *old;
86 int count = 0;
87
89
90 if (list == NULL) {
91 *params = NULL;
92 return -1;
93 }
94
95 /* Take the first parameter set in the list as the default
96 * (will normally be a 3-parameter transformation) */
97 *params = G_store(list->params);
98
99 while (list != NULL) {
100 count++;
101 old = list;
102 list = list->next;
104 }
105
106 return count;
107}
108
109/**
110 *
111 * \brief Extract the datum transformation-related parameters for
112 * the current location.
113 *
114 * This function can be used to test if a location's co-ordinate
115 * system set-up supports datum transformation.
116 *
117 * \param name Pointer to a pointer which will have memory
118 * allocated and into which a string containing the
119 * datum name (if present) will be placed. Otherwise
120 * set to NULL.
121 *
122 * \param params Pointer to a pointer which will have memory
123 * allocated and into which a string containing
124 * the datum parameters (if present) will
125 * be placed. Otherwise set to NULL.
126 *
127 * \return -1 error or no datum information found,
128 * 1 only datum name found, 2 params found
129 *
130 **/
131
133{
134 int ret;
136
139
140 return ret;
141}
142
143/**
144 *
145 * \brief Extract the datum transformation-related parameters from a
146 * set of general PROJ_INFO parameters.
147 *
148 * This function can be used to test if a location's co-ordinate
149 * system set-up supports datum transformation.
150 *
151 * \param projinfo Set of key_value pairs containing
152 * projection information in PROJ_INFO file
153 * format
154 *
155 * \param datumname Pointer to a pointer which will have memory
156 * allocated and into which a string containing the
157 * datum name (if present) will be placed. Otherwise
158 * set to NULL.
159 *
160 * \param params Pointer to a pointer which will have memory
161 * allocated and into which a string containing
162 * the datum parameters (if present) will
163 * be placed. Otherwise set to NULL.
164 *
165 * \return -1 error or no datum information found,
166 * 1 only datum name found, 2 params found
167 *
168 **/
169
170int GPJ__get_datum_params(const struct Key_Value *projinfo, char **datumname,
171 char **params)
172{
173 int returnval = -1;
174
175 if (NULL != G_find_key_value("datum", projinfo)) {
176 *datumname = G_store(G_find_key_value("datum", projinfo));
177 G_debug(3, "GPJ__get_datum_params: datumname: <%s>",
178 G_find_key_value("datum", projinfo));
179 returnval = 1;
180 }
181 else
182 *datumname = NULL;
183
184 if (G_find_key_value("datumparams", projinfo) != NULL) {
185 *params = G_store(G_find_key_value("datumparams", projinfo));
186 G_debug(3, "GPJ__get_datum_params: datumparams: <%s>",
187 G_find_key_value("datumparams", projinfo));
188 returnval = 2;
189 }
190 else if (G_find_key_value("nadgrids", projinfo) != NULL) {
191 /* 1. beware of '@', do not create something like
192 * /usr/share/proj/@null, correct is @null or
193 * @/usr/share/proj/null
194 * 2. do not add path to the grid, there might already be a
195 * path, and it is safer to use pj_set_finder with PROJ.4 in
196 * datum.c */
197
198 G_asprintf(params, "nadgrids=%s",
199 G_find_key_value("nadgrids", projinfo));
200
201 returnval = 2;
202 }
203 else if (G_find_key_value("towgs84", projinfo) != NULL) {
204 G_asprintf(params, "towgs84=%s", G_find_key_value("towgs84", projinfo));
205 returnval = 2;
206 }
207 else if (G_find_key_value("dx", projinfo) != NULL &&
208 G_find_key_value("dy", projinfo) != NULL &&
209 G_find_key_value("dz", projinfo) != NULL) {
210 G_asprintf(params, "towgs84=%s,%s,%s", G_find_key_value("dx", projinfo),
211 G_find_key_value("dy", projinfo),
212 G_find_key_value("dz", projinfo));
213 returnval = 2;
214 }
215 else
216 *params = NULL;
217
218 return returnval;
219}
220
221/**
222 * \brief Internal function to find all possible sets of
223 * transformation parameters for a particular datum
224 *
225 * \param inputname String containing the datum name we
226 * are going to look up parameters for
227 *
228 * \return Pointer to struct gpj_datum_transform_list (a linked
229 * list containing transformation parameters),
230 * or NULL if no suitable parameters were found.
231 **/
232
235{
236 FILE *fd;
237 char file[GPATH_MAX];
238 char buf[1024];
239 int line;
240 struct gpj_datum_transform_list *current = NULL, *outputlist = NULL;
241 struct gpj_datum dstruct;
242 int count = 0;
243
245 if (dstruct.dx < 99999 && dstruct.dy < 99999 && dstruct.dz < 99999) {
246 /* Include the old-style dx dy dz parameters from datum.table at the
247 * start of the list, unless these have been set to all 99999 to
248 * indicate only entries in datumtransform.table should be used */
249 if (current == NULL)
250 current = outputlist =
251 G_malloc(sizeof(struct gpj_datum_transform_list));
252 else
253 current = current->next =
254 G_malloc(sizeof(struct gpj_datum_transform_list));
255 G_asprintf(&(current->params), "towgs84=%.3f,%.3f,%.3f", dstruct.dx,
256 dstruct.dy, dstruct.dz);
257 G_asprintf(&(current->where_used), "whole %s region", inputname);
258 G_asprintf(&(current->comment),
259 "Default 3-Parameter Transformation (May not be optimum for "
260 "older datums; use this only if no more appropriate options "
261 "are available.)");
262 count++;
263 current->count = count;
264 current->next = NULL;
265 }
267
268 /* Now check for additional parameters in datumtransform.table */
269
270 snprintf(file, sizeof(file), "%s%s", G_gisbase(), DATUMTRANSFORMTABLE);
271
272 fd = fopen(file, "r");
273 if (!fd) {
274 G_warning(_("Unable to open datum table file <%s>"), file);
275 return outputlist;
276 }
277
278 for (line = 1; G_getl2(buf, sizeof(buf), fd); line++) {
279 char name[100], params[1024], where_used[1024], comment[1024];
280
281 G_strip(buf);
282 if (*buf == '\0' || *buf == '#')
283 continue;
284
285 if (sscanf(buf, "%99s \"%1023[^\"]\" \"%1023[^\"]\" \"%1023[^\"]\"",
286 name, params, where_used, comment) != 4) {
287 G_warning(_("Error in datum table file <%s>, line %d"), file, line);
288 continue;
289 }
290
291 if (G_strcasecmp(inputname, name) == 0) {
292 /* If the datum name in this line matches the one we are
293 * looking for, add an entry to the linked list */
294 if (current == NULL)
295 current = outputlist =
296 G_malloc(sizeof(struct gpj_datum_transform_list));
297 else
298 current = current->next =
299 G_malloc(sizeof(struct gpj_datum_transform_list));
300 current->params = G_store(params);
301 current->where_used = G_store(where_used);
302 current->comment = G_store(comment);
303 count++;
304 current->count = count;
305 current->next = NULL;
306 }
307 }
308
309 fclose(fd);
310
311 return outputlist;
312}
313
314/**
315 * \brief Free the memory used by a gpj_datum_transform_list struct
316 *
317 * \param item gpj_datum_transform_list struct to be freed
318 **/
319
321{
322 G_free(item->params);
323 G_free(item->where_used);
324 G_free(item->comment);
325 G_free(item);
326 return;
327}
328
329/**
330 * \brief Read the current GRASS datum.table from disk and store in
331 * memory
332 *
333 * The datum information is stored in a datum_list linked list structure.
334 *
335 * \return Pointer to first datum_list element in linked list, or NULL
336 * if unable to open datum.table file
337 **/
338
340{
341 FILE *fd;
342 char file[GPATH_MAX];
343 char buf[4096];
344 int line;
345 struct datum_list *current = NULL, *outputlist = NULL;
346
347 snprintf(file, sizeof(file), "%s%s", G_gisbase(), DATUMTABLE);
348
349 fd = fopen(file, "r");
350 if (!fd) {
351 G_warning(_("Unable to open datum table file <%s>"), file);
352 return NULL;
353 }
354
355 for (line = 1; G_getl2(buf, sizeof(buf), fd); line++) {
356 char name[100], descr[1024], ellps[100];
357 double dx, dy, dz;
358
359 G_strip(buf);
360 if (*buf == '\0' || *buf == '#')
361 continue;
362
363 if (sscanf(buf, "%s \"%1023[^\"]\" %s dx=%lf dy=%lf dz=%lf", name,
364 descr, ellps, &dx, &dy, &dz) != 6) {
365 G_warning(_("Error in datum table file <%s>, line %d"), file, line);
366 continue;
367 }
368
369 if (current == NULL)
370 current = outputlist = G_malloc(sizeof(struct datum_list));
371 else
372 current = current->next = G_malloc(sizeof(struct datum_list));
373 current->name = G_store(name);
374 current->longname = G_store(descr);
375 current->ellps = G_store(ellps);
376 current->dx = dx;
377 current->dy = dy;
378 current->dz = dz;
379 current->next = NULL;
380 }
381
382 fclose(fd);
383
384 return outputlist;
385}
386
387/**
388 * \brief Free the memory used for the strings in a gpj_datum struct
389 *
390 * \param dstruct gpj_datum struct to be freed
391 **/
392
394{
396 G_free(dstruct->longname);
397 G_free(dstruct->ellps);
398 return;
399}
400
401/**
402 * \brief Free the memory used by a datum_list linked list structure
403 *
404 * \param dstruct datum_list struct to be freed
405 **/
406
408{
409 struct datum_list *old;
410
411 while (dstruct != NULL) {
413 G_free(dstruct->longname);
414 G_free(dstruct->ellps);
415 old = dstruct;
416 dstruct = old->next;
417 G_free(old);
418 }
419
420 return;
421}
#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
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
struct Key_Value * G_get_projinfo(void)
Gets projection information for location.
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
#define G_malloc(n)
Definition defs/gis.h:136
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
Definition key_value1.c:102
void G_strip(char *)
Removes all leading and trailing white space from string.
Definition strings.c:298
int G_asprintf(char **, 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:83
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_debug(int, const char *,...) __attribute__((format(printf
#define GPATH_MAX
Definition gis.h:196
#define _(str)
Definition glocale.h:10
#define DATUMTABLE
Definition gprojects.h:32
#define DATUMTRANSFORMTABLE
Definition gprojects.h:33
int count
#define file
const char * name
Definition named_colr.c:6
int GPJ_get_default_datum_params_by_name(const char *name, char **params)
"Last resort" function to retrieve a "default" set of datum parameters for a datum (N....
Definition proj/datum.c:83
void GPJ_free_datum_transform(struct gpj_datum_transform_list *item)
Free the memory used by a gpj_datum_transform_list struct.
Definition proj/datum.c:320
void GPJ_free_datum(struct gpj_datum *dstruct)
Free the memory used for the strings in a gpj_datum struct.
Definition proj/datum.c:393
struct gpj_datum_transform_list * GPJ_get_datum_transform_by_name(const char *inputname)
Internal function to find all possible sets of transformation parameters for a particular datum.
Definition proj/datum.c:234
void free_datum_list(struct datum_list *dstruct)
Free the memory used by a datum_list linked list structure.
Definition proj/datum.c:407
int GPJ__get_datum_params(const struct Key_Value *projinfo, char **datumname, char **params)
Extract the datum transformation-related parameters from a set of general PROJ_INFO parameters.
Definition proj/datum.c:170
int GPJ_get_datum_by_name(const char *name, struct gpj_datum *dstruct)
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:35
int GPJ_get_datum_params(char **name, char **params)
Extract the datum transformation-related parameters for the current location.
Definition proj/datum.c:132
struct datum_list * read_datum_table(void)
Read the current GRASS datum.table from disk and store in memory.
Definition proj/datum.c:339
struct gpj_datum_transform_list * next
Definition gprojects.h:65
Definition manage.h:4