GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
get_proj.c
Go to the documentation of this file.
1 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <ctype.h>
20 #include <math.h>
21 #include <string.h>
22 #include <grass/gis.h>
23 #include <grass/gprojects.h>
24 #include <grass/glocale.h>
25 
26 #define MAIN
27 
28 /* Finder function for datum conversion lookup tables */
29 #define FINDERFUNC set_proj_lib
30 #define PERMANENT "PERMANENT"
31 #define MAX_PARGS 100
32 
33 static void alloc_options(char *);
34 
35 static char *opt_in[MAX_PARGS];
36 static int nopt1;
37 
61 int pj_get_kv(struct pj_info *info, struct Key_Value *in_proj_keys,
62  struct Key_Value *in_units_keys)
63 {
64  char *str;
65  int i;
66  double a, es, rf;
67  int returnval = 1;
68  char buffa[300], factbuff[50];
69  char proj_in[50], *datum, *params;
70  projPJ *pj;
71 
72  proj_in[0] = '\0';
73  info->zone = 0;
74  info->meters = 1.0;
75  info->proj[0] = '\0';
76 
77  str = G_find_key_value("meters", in_units_keys);
78  if (str != NULL) {
79  strcpy(factbuff, str);
80  if (strlen(factbuff) > 0)
81  sscanf(factbuff, "%lf", &(info->meters));
82  }
83  str = G_find_key_value("name", in_proj_keys);
84  if (str != NULL) {
85  sprintf(proj_in, "%s", str);
86  }
87  str = G_find_key_value("proj", in_proj_keys);
88  if (str != NULL) {
89  sprintf(info->proj, "%s", str);
90  }
91  if (strlen(info->proj) <= 0)
92  sprintf(info->proj, "ll");
93 
94  nopt1 = 0;
95  for (i = 0; i < in_proj_keys->nitems; i++) {
96  /* the name parameter is just for grasses use */
97  if (strcmp(in_proj_keys->key[i], "name") == 0) {
98  continue;
99 
100  /* zone handled separately at end of loop */
101  }
102  else if (strcmp(in_proj_keys->key[i], "zone") == 0) {
103  continue;
104 
105  /* Datum and ellipsoid-related parameters will be handled
106  * separately after end of this loop PK */
107 
108  }
109  else if (strcmp(in_proj_keys->key[i], "datum") == 0
110  || strcmp(in_proj_keys->key[i], "dx") == 0
111  || strcmp(in_proj_keys->key[i], "dy") == 0
112  || strcmp(in_proj_keys->key[i], "dz") == 0
113  || strcmp(in_proj_keys->key[i], "datumparams") == 0
114  || strcmp(in_proj_keys->key[i], "nadgrids") == 0
115  || strcmp(in_proj_keys->key[i], "towgs84") == 0
116  || strcmp(in_proj_keys->key[i], "ellps") == 0
117  || strcmp(in_proj_keys->key[i], "a") == 0
118  || strcmp(in_proj_keys->key[i], "b") == 0
119  || strcmp(in_proj_keys->key[i], "es") == 0
120  || strcmp(in_proj_keys->key[i], "f") == 0
121  || strcmp(in_proj_keys->key[i], "rf") == 0) {
122  continue;
123 
124  /* PROJ.4 uses longlat instead of ll as 'projection name' */
125 
126  }
127  else if (strcmp(in_proj_keys->key[i], "proj") == 0) {
128  if (strcmp(in_proj_keys->value[i], "ll") == 0)
129  sprintf(buffa, "proj=longlat");
130  else
131  sprintf(buffa, "proj=%s", in_proj_keys->value[i]);
132 
133  /* 'One-sided' PROJ.4 flags will have the value in
134  * the key-value pair set to 'defined' and only the
135  * key needs to be passed on. */
136  }
137  else if (strcmp(in_proj_keys->value[i], "defined") == 0)
138  sprintf(buffa, "%s", in_proj_keys->key[i]);
139 
140  else
141  sprintf(buffa, "%s=%s",
142  in_proj_keys->key[i], in_proj_keys->value[i]);
143 
144  alloc_options(buffa);
145  }
146 
147  str = G_find_key_value("zone", in_proj_keys);
148  if (str != NULL) {
149  if (sscanf(str, "%d", &(info->zone)) != 1) {
150  G_fatal_error(_("Invalid zone %s specified"), str);
151  }
152  if (info->zone < 0) {
153 
154  /* if zone is negative, write abs(zone) and define south */
155  info->zone = -info->zone;
156 
157  if (G_find_key_value("south", in_proj_keys) == NULL) {
158  sprintf(buffa, "south");
159  alloc_options(buffa);
160  }
161  }
162  sprintf(buffa, "zone=%d", info->zone);
163  alloc_options(buffa);
164  }
165 
166  if ((GPJ__get_ellipsoid_params(in_proj_keys, &a, &es, &rf) == 0)
167  && (str = G_find_key_value("ellps", in_proj_keys)) != NULL) {
168  /* Default values were returned but an ellipsoid name not recognised
169  * by GRASS is present---perhaps it will be recognised by
170  * PROJ.4 even though it wasn't by GRASS */
171  sprintf(buffa, "ellps=%s", str);
172  alloc_options(buffa);
173  }
174  else {
175  sprintf(buffa, "a=%.16g", a);
176  alloc_options(buffa);
177  /* Cannot use es directly because the OSRImportFromProj4()
178  * function in OGR only accepts b or rf as the 2nd parameter */
179  if (es == 0)
180  sprintf(buffa, "b=%.16g", a);
181  else
182  sprintf(buffa, "rf=%.16g", rf);
183  alloc_options(buffa);
184 
185  }
186  /* Workaround to stop PROJ reading values from defaults file when
187  * rf (and sometimes ellps) is not specified */
188  if (G_find_key_value("no_defs", in_proj_keys) == NULL) {
189  sprintf(buffa, "no_defs");
190  alloc_options(buffa);
191  }
192 
193  /* If datum parameters are present in the PROJ_INFO keys, pass them on */
194  if (GPJ__get_datum_params(in_proj_keys, &datum, &params) == 2) {
195  sprintf(buffa, "%s", params);
196  alloc_options(buffa);
197  G_free(params);
198 
199  /* else if a datum name is present take it and look up the parameters
200  * from the datum.table file */
201  }
202  else if (datum != NULL) {
203 
204  if (GPJ_get_default_datum_params_by_name(datum, &params) > 0) {
205  sprintf(buffa, "%s", params);
206  alloc_options(buffa);
207  returnval = 2;
208  G_free(params);
209 
210  /* else just pass the datum name on and hope it is recognised by
211  * PROJ.4 even though it isn't recognised by GRASS */
212  }
213  else {
214  sprintf(buffa, "datum=%s", datum);
215  alloc_options(buffa);
216  returnval = 3;
217  }
218  G_free(datum);
219  /* else there'll be no datum transformation taking place here... */
220  }
221  else {
222  returnval = 4;
223  }
224 
225  /* Set finder function for locating datum conversion tables PK */
226  pj_set_finder(FINDERFUNC);
227 
228  if (!(pj = pj_init(nopt1, opt_in))) {
229  strcpy(buffa,
230  _("Unable to initialise PROJ.4 with the following parameter list:"));
231  for (i = 0; i < nopt1; i++) {
232  char err[50];
233 
234  sprintf(err, " +%s", opt_in[i]);
235  strcat(buffa, err);
236  }
237  G_warning(buffa);
238  G_warning(_("The error message: %s"), pj_strerrno(pj_errno));
239  return -1;
240  }
241  info->pj = pj;
242 
243  return returnval;
244 }
245 
246 static void alloc_options(char *buffa)
247 {
248  int nsize;
249 
250  nsize = strlen(buffa);
251  opt_in[nopt1++] = (char *)G_malloc(nsize + 1);
252  sprintf(opt_in[nopt1 - 1], "%s", buffa);
253  return;
254 }
255 
256 int pj_get_string(struct pj_info *info, char *str)
257 {
258  char *opt_in[MAX_PARGS];
259  char *s;
260  int nopt = 0;
261  int nsize;
262  char zonebuff[50], buffa[300];
263  projPJ *pj;
264 
265  info->zone = 0;
266  info->proj[0] = '\0';
267  info->meters = 1.0;
268 
269  if ((str == NULL) || (str[0] == '\0')) {
270  /* Null Pointer or empty string is supplied for parameters,
271  * implying latlong projection; just need to set proj
272  * parameter and call pj_init PK */
273  sprintf(info->proj, "ll");
274  sprintf(buffa, "proj=latlong ellps=WGS84");
275  nsize = strlen(buffa);
276  opt_in[nopt] = (char *)G_malloc(nsize + 1);
277  sprintf(opt_in[nopt++], "%s", buffa);
278  }
279  else {
280  /* Parameters have been provided; parse through them but don't
281  * bother with most of the checks in pj_get_kv; assume the
282  * programmer knows what he / she is doing when using this
283  * function rather than reading a PROJ_INFO file PK */
284  s = str;
285  while (s = strtok(s, " \t\n"), s) {
286  if (strncmp(s, "+unfact=", 8) == 0) {
287  s = s + 8;
288  info->meters = atof(s);
289  }
290  else {
291  if (strncmp(s, "+", 1) == 0)
292  ++s;
293  if (nsize = strlen(s), nsize) {
294  if (nopt >= MAX_PARGS) {
295  fprintf(stderr, "nopt = %d, s=%s\n", nopt, str);
296  G_fatal_error(_("Option input overflowed option table"));
297  }
298 
299  if (strncmp("zone=", s, 5) == 0) {
300  sprintf(zonebuff, "%s", s + 5);
301  sscanf(zonebuff, "%d", &(info->zone));
302  }
303 
304  if (strncmp("proj=", s, 5) == 0) {
305  sprintf(info->proj, "%s", s + 5);
306  if (strcmp(info->proj, "ll") == 0)
307  sprintf(buffa, "proj=latlong");
308  else
309  sprintf(buffa, "%s", s);
310  }
311  else {
312  sprintf(buffa, "%s", s);
313  }
314  nsize = strlen(buffa);
315  opt_in[nopt] = (char *)G_malloc(nsize + 1);
316  sprintf(opt_in[nopt++], "%s", buffa);
317  }
318  }
319  s = 0;
320  }
321  }
322 
323  /* Set finder function for locating datum conversion tables PK */
324  pj_set_finder(FINDERFUNC);
325 
326  if (!(pj = pj_init(nopt, opt_in))) {
327  G_warning(_("Unable to initialize pj cause: %s"),
328  pj_strerrno(pj_errno));
329  return -1;
330  }
331  info->pj = pj;
332 
333  return 1;
334 }
335 
352 int GPJ_get_equivalent_latlong(struct pj_info *pjnew, struct pj_info *pjold)
353 {
354  pjnew->meters = 1.;
355  pjnew->zone = 0;
356  sprintf(pjnew->proj, "ll");
357  if ((pjnew->pj = pj_latlong_from_proj(pjold->pj)) == NULL)
358  return -1;
359  else
360  return 1;
361 }
362 
363 /* set_proj_lib()
364  * 'finder function' for use with PROJ.4 pj_set_finder() function */
365 
366 const char *set_proj_lib(const char *name)
367 {
368  const char *gisbase = G_gisbase();
369  static char *buf = NULL;
370  static size_t buf_len;
371  size_t len = strlen(gisbase) + sizeof(GRIDDIR) + strlen(name) + 1;
372 
373  if (buf_len < len) {
374  if (buf != NULL)
375  G_free(buf);
376  buf_len = len + 20;
377  buf = G_malloc(buf_len);
378  }
379 
380  sprintf(buf, "%s%s/%s", gisbase, GRIDDIR, name);
381 
382  return buf;
383 }
384 
396 int pj_print_proj_params(struct pj_info *iproj, struct pj_info *oproj)
397 {
398  char *str;
399 
400  if (iproj) {
401  str = pj_get_def(iproj->pj, 1);
402  if (str != NULL) {
403  fprintf(stderr, "%s: %s\n", _("Input Projection Parameters"),
404  str);
405  pj_dalloc(str);
406  fprintf(stderr, "%s: %.16g\n", _("Input Unit Factor"),
407  iproj->meters);
408  }
409  else
410  return -1;
411  }
412 
413  if (oproj) {
414  str = pj_get_def(oproj->pj, 1);
415  if (str != NULL) {
416  fprintf(stderr, "%s: %s\n", _("Output Projection Parameters"),
417  str);
418  pj_dalloc(str);
419  fprintf(stderr, "%s: %.16g\n", _("Output Unit Factor"),
420  oproj->meters);
421  }
422  else
423  return -1;
424  }
425 
426  return 1;
427 }
def info
Display an informational message using g.message -i
Definition: core.py:339
char * G_find_key_value(const char *key, const struct Key_Value *kv)
Find given key.
Definition: key_value1.c:128
sprintf(buf2,"%s", G3D_CATS_ELEMENT)
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
int pj_get_kv(struct pj_info *info, struct Key_Value *in_proj_keys, struct Key_Value *in_units_keys)
Create a pj_info struct Co-ordinate System definition from a set of PROJ_INFO / PROJ_UNITS-style key-...
Definition: get_proj.c:61
int GPJ_get_equivalent_latlong(struct pj_info *pjnew, struct pj_info *pjold)
Define a latitude / longitude co-ordinate system with the same ellipsoid and datum parameters as an e...
Definition: get_proj.c:352
int pj_print_proj_params(struct pj_info *iproj, struct pj_info *oproj)
Print projection parameters as used by PROJ.4 for input and output co-ordinate systems.
Definition: get_proj.c:396
string name
Definition: render.py:1314
const char * err
Definition: g3dcolor.c:50
tuple gisbase
Definition: forms.py:59
const char * set_proj_lib(const char *name)
Definition: get_proj.c:366
int GPJ__get_ellipsoid_params(struct Key_Value *proj_keys, double *a, double *e2, double *rf)
Definition: ellipse.c:52
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)
#define MAX_PARGS
Definition: get_proj.c:31
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
char * G_gisbase(void)
top level module directory
Definition: gisbase.c:42
#define FINDERFUNC
Definition: get_proj.c:29
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
int pj_get_string(struct pj_info *info, char *str)
Definition: get_proj.c:256