GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
proj/datum.c
Go to the documentation of this file.
1 
16 #include <unistd.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <stdlib.h>
20 
21 #include <grass/gis.h>
22 #include <grass/glocale.h>
23 #include <grass/gprojects.h>
24 #include "local_proto.h"
25 
37 int GPJ_get_datum_by_name(const char *name, struct gpj_datum *dstruct)
38 {
39  struct datum_list *list, *listhead;
40 
41  list = listhead = read_datum_table();
42 
43  while (list != NULL) {
44  if (G_strcasecmp(name, list->name) == 0) {
45  dstruct->name = G_store(list->name);
46  dstruct->longname = G_store(list->longname);
47  dstruct->ellps = G_store(list->ellps);
48  dstruct->dx = list->dx;
49  dstruct->dy = list->dy;
50  dstruct->dz = list->dz;
51  free_datum_list(listhead);
52  return 1;
53  }
54  list = list->next;
55  }
56  free_datum_list(listhead);
57  return -1;
58 }
59 
85 int GPJ_get_default_datum_params_by_name(const char *name, char **params)
86 {
87  struct gpj_datum_transform_list *list, *old;
88  int count = 0;
89 
91 
92  if (list == NULL) {
93  *params = NULL;
94  return -1;
95  }
96 
97  /* Take the first parameter set in the list as the default
98  * (will normally be a 3-parameter transformation) */
99  *params = G_store(list->params);
100 
101  while (list != NULL) {
102  count++;
103  old = list;
104  list = list->next;
106  }
107 
108  return count;
109 
110 }
111 
135 int GPJ_get_datum_params(char **name, char **params)
136 {
137  int ret;
138  struct Key_Value *proj_keys = G_get_projinfo();
139 
140  ret = GPJ__get_datum_params(proj_keys, name, params);
141  G_free_key_value(proj_keys);
142 
143  return ret;
144 }
145 
173 int GPJ__get_datum_params(struct Key_Value *projinfo,
174  char **datumname, char **params)
175 {
176  int returnval = -1;
177 
178  if (NULL != G_find_key_value("datum", projinfo)) {
179  *datumname = G_store(G_find_key_value("datum", projinfo));
180  returnval = 1;
181  }
182  else
183  *datumname = NULL;
184 
185  if (G_find_key_value("datumparams", projinfo) != NULL) {
186  *params = G_store(G_find_key_value("datumparams", projinfo));
187  returnval = 2;
188  }
189  else if (G_find_key_value("nadgrids", projinfo) != NULL) {
190  const char *gisbase = G_gisbase();
191 
192  G_asprintf(params, "nadgrids=%s%s/%s", gisbase, GRIDDIR,
193  G_find_key_value("nadgrids", projinfo));
194  returnval = 2;
195  }
196  else if (G_find_key_value("towgs84", projinfo) != NULL) {
197  G_asprintf(params, "towgs84=%s",
198  G_find_key_value("towgs84", projinfo));
199  returnval = 2;
200  }
201  else if (G_find_key_value("dx", projinfo) != NULL
202  && G_find_key_value("dy", projinfo) != NULL
203  && G_find_key_value("dz", projinfo) != NULL) {
204  G_asprintf(params, "towgs84=%s,%s,%s",
205  G_find_key_value("dx", projinfo),
206  G_find_key_value("dy", projinfo),
207  G_find_key_value("dz", projinfo));
208  returnval = 2;
209  }
210  else
211  *params = NULL;
212 
213  return returnval;
214 
215 }
216 
239 int GPJ_ask_datum_params(const char *datumname, char **params)
240 {
241  char buff[1024], answer[100];
242  char *Tmp_file;
243  FILE *Tmp_fd = NULL;
244  struct gpj_datum_transform_list *list, *listhead, *old;
245  int transformcount, currenttransform;
246 
247  if (G_strcasecmp(datumname, "custom") != 0) {
248  Tmp_file = G_tempfile();
249  if (NULL == (Tmp_fd = fopen(Tmp_file, "w"))) {
250  G_warning(_("Unable to open temporary file"));
251  }
252 
253  fprintf(Tmp_fd, "Number\tDetails\t\n---\n");
254  listhead = GPJ_get_datum_transform_by_name(datumname);
255  list = listhead;
256  transformcount = 0;
257  while (list != NULL) {
258  /* Count how many sets of transformation paramters have been
259  * defined for this datum and print them to a temporary file
260  * in case the user asks for them to be displayed */
261  fprintf(Tmp_fd,
262  "%d\tUsed in %s\n\t(PROJ.4 Params %s)\n\t%s\n---\n",
263  list->count, list->where_used, list->params,
264  list->comment);
265  list = list->next;
266  transformcount++;
267  }
268  fclose(Tmp_fd);
269 
270  for (;;) {
271  do {
272  fprintf(stderr,
273  ("\nNow select Datum Transformation Parameters\n"));
274  fprintf(stderr,
275  ("Please think carefully about the area covered by your data\n"
276  "and the accuracy you require before making your selection.\n"));
277  fprintf(stderr,
278  ("\nEnter 'list' to see the list of available Parameter sets\n"));
279  fprintf(stderr,
280  ("Enter the corresponding number, or <RETURN> to cancel request\n"));
281  fprintf(stderr, ">");
282  } while (!G_gets(answer));
283  G_strip(answer);
284  if (strlen(answer) == 0) {
285  remove(Tmp_file);
286  G_free(Tmp_file);
287  return -1;
288  }
289  if (strcmp(answer, "list") == 0) {
290  char *pager;
291 
292  pager = getenv("GRASS_PAGER");
293  if (!pager || strlen(pager) == 0)
294  pager = "cat";
295 
296  /* Always print interactive output to stderr */
297  sprintf(buff, "%s \"%s\" 1>&2", pager,
298  G_convert_dirseps_to_host(Tmp_file));
299  G_system(buff);
300  }
301  else {
302  if ((sscanf(answer, "%d", &currenttransform) != 1) ||
303  currenttransform > transformcount ||
304  currenttransform < 1) {
305 
306  /* If a number was not typed, was less than 0 or greater
307  * than the number of sets of parameters, ask again */
308  fprintf(stderr, ("\ninvalid transformation number\n"));
309  }
310  else
311  break;
312  }
313 
314  }
315  remove(Tmp_file);
316  G_free(Tmp_file);
317 
318  list = listhead;
319  while (list != NULL) {
320  /* Search through the linked list to find the parameter string
321  * that corresponds to the number entered */
322  if (list->count == currenttransform)
323  G_asprintf(params, list->params);
324 
325  /* Continue to end of list even after we find it, to free all
326  * the memory used */
327  old = list;
328  list = old->next;
329  G_free(old);
330  }
331  }
332  else {
333  /* Here we ask the user to enter customised parameters */
334  for (;;) {
335  do {
336  fprintf(stderr,
337  ("\nPlease specify datum transformation parameters in PROJ.4 syntax. Examples:\n"));
338  fprintf(stderr,
339  ("\ttowgs84=dx,dy,dz\t(3-parameter transformation)\n"));
340  fprintf(stderr,
341  ("\ttowgs84=dx,dy,dz,rx,ry,rz,m\t(7-parameter transformation)\n"));
342  fprintf(stderr,
343  ("\tnadgrids=alaska\t(Tables-based grid-shifting transformation)\n"));
344  fprintf(stderr, _("Hit RETURN to cancel request\n"));
345  fprintf(stderr, ">");
346  } while (!G_gets(answer));
347  G_strip(answer);
348  if (strlen(answer) == 0)
349  return -1;
350  G_asprintf(params, answer);
351  sprintf(buff,
352  "Parameters to be used are:\n\"%s\"\nIs this correct?",
353  *params);
354  if (G_yes(buff, 1))
355  break;
356 
357  }
358 
359  }
360 
361  return 1;
362 
363 }
364 
377 struct gpj_datum_transform_list *GPJ_get_datum_transform_by_name(const char
378  *inputname)
379 {
380  FILE *fd;
381  char file[GPATH_MAX];
382  char buf[1024];
383  int line;
384  struct gpj_datum_transform_list *current = NULL, *outputlist = NULL;
385  struct gpj_datum dstruct;
386  int count = 0;
387 
388  GPJ_get_datum_by_name(inputname, &dstruct);
389  if (dstruct.dx < 99999 && dstruct.dy < 99999 && dstruct.dz < 99999) {
390  /* Include the old-style dx dy dz parameters from datum.table at the
391  * start of the list, unless these have been set to all 99999 to
392  * indicate only entries in datumtransform.table should be used */
393  if (current == NULL)
394  current = outputlist =
395  G_malloc(sizeof(struct gpj_datum_transform_list));
396  else
397  current = current->next =
398  G_malloc(sizeof(struct gpj_datum_transform_list));
399  G_asprintf(&(current->params), "towgs84=%.3f,%.3f,%.3f", dstruct.dx,
400  dstruct.dy, dstruct.dz);
401  G_asprintf(&(current->where_used), "whole %s region", inputname);
402  G_asprintf(&(current->comment),
403  "Default 3-Parameter Transformation (May not be optimum for "
404  "older datums; use this only if no more appropriate options "
405  "are available.)");
406  count++;
407  current->count = count;
408  current->next = NULL;
409  }
410  GPJ_free_datum(&dstruct);
411 
412  /* Now check for additional parameters in datumtransform.table */
413 
414  sprintf(file, "%s%s", G_gisbase(), DATUMTRANSFORMTABLE);
415 
416  fd = fopen(file, "r");
417  if (!fd) {
418  G_warning(_("Unable to open datum table file <%s>"), file);
419  return outputlist;
420  }
421 
422  for (line = 1; G_getl2(buf, sizeof(buf), fd); line++) {
423  char name[100], params[1024], where_used[1024], comment[1024];
424 
425  G_strip(buf);
426  if (*buf == '\0' || *buf == '#')
427  continue;
428 
429  if (sscanf(buf, "%99s \"%1023[^\"]\" \"%1023[^\"]\" \"%1023[^\"]\"",
430  name, params, where_used, comment) != 4) {
431  G_warning(_("Error in datum table file <%s>, line %d"), file,
432  line);
433  continue;
434  }
435 
436  if (G_strcasecmp(inputname, name) == 0) {
437  /* If the datum name in this line matches the one we are
438  * looking for, add an entry to the linked list */
439  if (current == NULL)
440  current = outputlist =
441  G_malloc(sizeof(struct gpj_datum_transform_list));
442  else
443  current = current->next =
444  G_malloc(sizeof(struct gpj_datum_transform_list));
445  current->params = G_store(params);
446  current->where_used = G_store(where_used);
447  current->comment = G_store(comment);
448  count++;
449  current->count = count;
450  current->next = NULL;
451  }
452  }
453 
454  fclose(fd);
455 
456  return outputlist;
457 
458 }
459 
466 void GPJ_free_datum_transform(struct gpj_datum_transform_list *item)
467 {
468  G_free(item->params);
469  G_free(item->where_used);
470  G_free(item->comment);
471  G_free(item);
472  return;
473 }
474 
486 {
487  FILE *fd;
488  char file[GPATH_MAX];
489  char buf[4096];
490  int line;
491  struct datum_list *current = NULL, *outputlist = NULL;
492  int count = 0;
493 
494  sprintf(file, "%s%s", G_gisbase(), DATUMTABLE);
495 
496  fd = fopen(file, "r");
497  if (!fd) {
498  G_warning(_("Unable to open datum table file <%s>"), file);
499  return NULL;
500  }
501 
502  for (line = 1; G_getl2(buf, sizeof(buf), fd); line++) {
503  char name[100], descr[1024], ellps[100];
504  double dx, dy, dz;
505 
506  G_strip(buf);
507  if (*buf == '\0' || *buf == '#')
508  continue;
509 
510  if (sscanf(buf, "%s \"%1023[^\"]\" %s dx=%lf dy=%lf dz=%lf",
511  name, descr, ellps, &dx, &dy, &dz) != 6) {
512  G_warning(_("Error in datum table file <%s>, line %d"), file,
513  line);
514  continue;
515  }
516 
517  if (current == NULL)
518  current = outputlist = G_malloc(sizeof(struct datum_list));
519  else
520  current = current->next = G_malloc(sizeof(struct datum_list));
521  current->name = G_store(name);
522  current->longname = G_store(descr);
523  current->ellps = G_store(ellps);
524  current->dx = dx;
525  current->dy = dy;
526  current->dz = dz;
527  current->next = NULL;
528 
529  count++;
530  }
531 
532  fclose(fd);
533 
534  return outputlist;
535 }
536 
543 void GPJ_free_datum(struct gpj_datum *dstruct)
544 {
545  G_free(dstruct->name);
546  G_free(dstruct->longname);
547  G_free(dstruct->ellps);
548  return;
549 }
550 
557 void free_datum_list(struct datum_list *dstruct)
558 {
559  struct datum_list *old;
560 
561  while (dstruct != NULL) {
562  G_free(dstruct->name);
563  G_free(dstruct->longname);
564  G_free(dstruct->ellps);
565  old = dstruct;
566  dstruct = old->next;
567  G_free(old);
568  }
569 
570  return;
571 }
char * G_find_key_value(const char *key, const struct Key_Value *kv)
Find given key.
Definition: key_value1.c:128
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition: strings.c:192
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
void GPJ_free_datum(struct gpj_datum *dstruct)
Free the memory used for the strings in a gpj_datum struct.
Definition: proj/datum.c:543
char * G_store(const char *s)
Copy string to allocated memory.
Definition: store.c:32
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:466
int G_gets(char *buf)
Definition: gets.c:39
FILE * fd
Definition: g3dcolor.c:368
#define DATUMTABLE
Definition: gis/datum.c:17
string name
Definition: render.py:1314
char * G_convert_dirseps_to_host(char *path)
Converts directory separator characters in a string to the native host separator character (/ on Unix...
Definition: paths.c:73
int G_yes(const char *question, int dflt)
Ask a yes/no question.
Definition: yes.c:39
int G_free_key_value(struct Key_Value *kv)
Free allocated Key_Value structure.
Definition: key_value1.c:145
int count
char * G_tempfile(void)
Returns a temporary file name.
Definition: tempfile.c:47
int G_asprintf(char **out, const char *fmt,...)
Definition: asprintf.c:116
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:377
tuple gisbase
Definition: forms.py:59
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:37
char * getenv()
char buff[1024]
Definition: g3dcats.c:89
int G_getl2(char *buf, int n, FILE *fd)
gets a line of text from a file of any pedigree
Definition: getl.c:52
void free_datum_list(struct datum_list *dstruct)
Free the memory used by a datum_list linked list structure.
Definition: proj/datum.c:557
int GPJ_get_datum_params(char **name, char **params)
Extract the datum transformation-related parameters for the current location.
Definition: proj/datum.c:135
int G_strip(char *buf)
Removes all leading and trailing white space from string.
Definition: strings.c:389
struct Key_Value * G_get_projinfo(void)
Gets projection information for location.
Definition: get_projinfo.c:52
struct datum_list * read_datum_table(void)
Read the current GRASS datum.table from disk and store in memory.
Definition: proj/datum.c:485
char buf[GNAME_MAX+sizeof(G3D_DIRECTORY)+2]
Definition: g3drange.c:62
return NULL
Definition: dbfopen.c:1394
int GPJ__get_datum_params(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:173
G_warning("category support for [%s] in mapset [%s] %s", name, mapset, type)
fclose(fd)
int GPJ_get_default_datum_params_by_name(const char *name, char **params)
&quot;Last resort&quot; function to retrieve a &quot;default&quot; set of datum parameters for a datum (N...
Definition: proj/datum.c:85
#define file
struct datum_list * next
char * G_gisbase(void)
top level module directory
Definition: gisbase.c:42
int old
Definition: g3dcats.c:92
int G_system(const char *command)
Run a shell level command.
Definition: system.c:51
int GPJ_ask_datum_params(const char *datumname, char **params)
Interactively ask for datum parameters for a particular datum.
Definition: proj/datum.c:239