GRASS GIS 7 Programmer's Manual  7.0.2(2015)-r00000
convert.c
Go to the documentation of this file.
1 
16 #include <grass/config.h>
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #include <grass/gis.h>
23 #include <grass/gprojects.h>
24 #include <grass/glocale.h>
25 
26 #ifdef HAVE_OGR
27 #include <cpl_csv.h>
28 #include "local_proto.h"
29 
30 /* GRASS relative location of OGR co-ordinate system lookup tables */
31 #define CSVDIR "/etc/proj/ogr_csv"
32 
33 static void DatumNameMassage(char **);
34 #endif
35 
55 char *GPJ_grass_to_wkt(const struct Key_Value *proj_info,
56  const struct Key_Value *proj_units,
57  int esri_style, int prettify)
58 {
59 #ifdef HAVE_OGR
60  OGRSpatialReferenceH hSRS;
61  char *wkt, *local_wkt;
62 
63  hSRS = GPJ_grass_to_osr(proj_info, proj_units);
64 
65  if (hSRS == NULL)
66  return NULL;
67 
68  if (esri_style)
69  OSRMorphToESRI(hSRS);
70 
71  if (prettify)
72  OSRExportToPrettyWkt(hSRS, &wkt, 0);
73  else
74  OSRExportToWkt(hSRS, &wkt);
75 
76  local_wkt = G_store(wkt);
77  CPLFree(wkt);
78  OSRDestroySpatialReference(hSRS);
79 
80  return local_wkt;
81 #else
82  G_warning(_("GRASS is not compiled with OGR support"));
83  return NULL;
84 #endif
85 }
86 
87 #ifdef HAVE_OGR
88 
97 OGRSpatialReferenceH GPJ_grass_to_osr(const struct Key_Value * proj_info,
98  const struct Key_Value * proj_units)
99 {
100  struct pj_info pjinfo;
101  char *proj4, *proj4mod, *wkt, *modwkt, *startmod, *lastpart;
102  OGRSpatialReferenceH hSRS, hSRS2;
103  OGRErr errcode;
104  struct gpj_datum dstruct;
105  struct gpj_ellps estruct;
106  size_t len;
107  const char *ellpskv, *unit, *unfact;
108  char *ellps, *ellpslong, *datum, *params, *towgs84, *datumlongname,
109  *start, *end;
110  const char *sysname, *osrunit, *osrunfact;
111  double a, es, rf;
112  int haveparams = 0;
113 
114  if ((proj_info == NULL) || (proj_units == NULL))
115  return NULL;
116 
117  hSRS = OSRNewSpatialReference(NULL);
118 
119  if (pj_get_kv(&pjinfo, proj_info, proj_units) < 0) {
120  G_warning(_("Unable parse GRASS PROJ_INFO file"));
121  return NULL;
122  }
123 
124  if ((proj4 = pj_get_def(pjinfo.pj, 0)) == NULL) {
125  G_warning(_("Unable get PROJ.4-style parameter string"));
126  return NULL;
127  }
128  pj_free(pjinfo.pj);
129 
130  unit = G_find_key_value("unit", proj_units);
131  unfact = G_find_key_value("meters", proj_units);
132  if (unfact != NULL && (strcmp(pjinfo.proj, "ll") != 0))
133  G_asprintf(&proj4mod, "%s +to_meter=%s", proj4, unfact);
134  else
135  proj4mod = G_store(proj4);
136  pj_dalloc(proj4);
137 
138  if ((errcode = OSRImportFromProj4(hSRS, proj4mod)) != OGRERR_NONE) {
139  G_warning(_("OGR can't parse PROJ.4-style parameter string: "
140  "%s (OGR Error code was %d)"), proj4mod, errcode);
141  return NULL;
142  }
143  G_free(proj4mod);
144 
145  if ((errcode = OSRExportToWkt(hSRS, &wkt)) != OGRERR_NONE) {
146  G_warning(_("OGR can't get WKT-style parameter string "
147  "(OGR Error code was %d)"), errcode);
148  return NULL;
149  }
150 
151  ellpskv = G_find_key_value("ellps", proj_info);
152  GPJ__get_ellipsoid_params(proj_info, &a, &es, &rf);
153  haveparams = GPJ__get_datum_params(proj_info, &datum, &params);
154 
155  if(ellpskv != NULL)
156  ellps = G_store(ellpskv);
157  else
158  ellps = NULL;
159 
160  if ((datum == NULL) || (GPJ_get_datum_by_name(datum, &dstruct) < 0)) {
161  datumlongname = G_store("unknown");
162  if (ellps == NULL)
163  ellps = G_store("unnamed");
164  }
165  else {
166  datumlongname = G_store(dstruct.longname);
167  if (ellps == NULL)
168  ellps = G_store(dstruct.ellps);
169  GPJ_free_datum(&dstruct);
170  }
171  G_free(datum);
172  if (GPJ_get_ellipsoid_by_name(ellps, &estruct) > 0) {
173  ellpslong = G_store(estruct.longname);
174  DatumNameMassage(&ellpslong);
175  GPJ_free_ellps(&estruct);
176  }
177  else
178  ellpslong = G_store(ellps);
179 
180  startmod = strstr(wkt, "GEOGCS");
181  lastpart = strstr(wkt, "PRIMEM");
182  len = strlen(wkt) - strlen(startmod);
183  wkt[len] = '\0';
184  if (haveparams == 2) {
185  /* Only put datum params into the WKT if they were specifically
186  * specified in PROJ_INFO */
187  char *paramkey, *paramvalue;
188 
189  paramkey = strtok(params, "=");
190  paramvalue = params + strlen(paramkey) + 1;
191  if (G_strcasecmp(paramkey, "towgs84") == 0)
192  G_asprintf(&towgs84, ",TOWGS84[%s]", paramvalue);
193  else
194  towgs84 = G_store("");
195  G_free(params);
196  }
197  else
198  towgs84 = G_store("");
199 
200  sysname = OSRGetAttrValue(hSRS, "PROJCS", 0);
201  if (sysname == NULL) {
202  /* Not a projected co-ordinate system */
203  start = G_store("");
204  end = G_store("");
205  }
206  else {
207  if ((strcmp(sysname, "unnamed") == 0) &&
208  (G_find_key_value("name", proj_info) != NULL))
209  G_asprintf(&start, "PROJCS[\"%s\",",
210  G_find_key_value("name", proj_info));
211  else
212  start = G_store(wkt);
213 
214  osrunit = OSRGetAttrValue(hSRS, "UNIT", 0);
215  osrunfact = OSRGetAttrValue(hSRS, "UNIT", 1);
216 
217  if ((unfact == NULL) || (G_strcasecmp(osrunit, "unknown") != 0))
218  end = G_store("");
219  else {
220  char *buff;
221  double unfactf = atof(unfact);
222 
223  G_asprintf(&buff, ",UNIT[\"%s\",", osrunit);
224 
225  startmod = strstr(lastpart, buff);
226  len = strlen(lastpart) - strlen(startmod);
227  lastpart[len] = '\0';
228  G_free(buff);
229 
230  if (unit == NULL)
231  unit = "unknown";
232  G_asprintf(&end, ",UNIT[\"%s\",%.16g]]", unit, unfactf);
233  }
234 
235  }
236  OSRDestroySpatialReference(hSRS);
237  G_asprintf(&modwkt,
238  "%sGEOGCS[\"%s\",DATUM[\"%s\",SPHEROID[\"%s\",%.16g,%.16g]%s],%s%s",
239  start, ellps, datumlongname, ellpslong, a, rf, towgs84,
240  lastpart, end);
241  hSRS2 = OSRNewSpatialReference(modwkt);
242  G_free(modwkt);
243 
244  CPLFree(wkt);
245  G_free(start);
246  G_free(ellps);
247  G_free(datumlongname);
248  G_free(ellpslong);
249  G_free(towgs84);
250  G_free(end);
251 
252  return hSRS2;
253 }
254 
274 int GPJ_osr_to_grass(struct Cell_head *cellhd, struct Key_Value **projinfo,
275  struct Key_Value **projunits, OGRSpatialReferenceH hSRS,
276  int datumtrans)
277 {
278  struct Key_Value *temp_projinfo;
279  char *pszProj4 = NULL, *pszRemaining;
280  char *pszProj = NULL;
281  char *datum = NULL;
282  struct gpj_datum dstruct;
283 
284  if (hSRS == NULL)
285  goto default_to_xy;
286 
287  /* Set finder function for locating OGR csv co-ordinate system tables */
288  SetCSVFilenameHook(GPJ_set_csv_loc);
289 
290  /* Hopefully this doesn't do any harm if it wasn't in ESRI format
291  * to start with... */
292  OSRMorphFromESRI(hSRS);
293 
294  /* -------------------------------------------------------------------- */
295  /* Set cellhd for well known coordinate systems. */
296  /* -------------------------------------------------------------------- */
297  if (!OSRIsGeographic(hSRS) && !OSRIsProjected(hSRS))
298  goto default_to_xy;
299 
300  if (cellhd) {
301  int bNorth;
302 
303  if (OSRIsGeographic(hSRS)) {
304  cellhd->proj = PROJECTION_LL;
305  cellhd->zone = 0;
306  }
307  else if (OSRGetUTMZone(hSRS, &bNorth) != 0) {
308  cellhd->proj = PROJECTION_UTM;
309  cellhd->zone = OSRGetUTMZone(hSRS, &bNorth);
310  if (!bNorth)
311  cellhd->zone *= -1;
312  }
313  else {
314  cellhd->proj = PROJECTION_OTHER;
315  cellhd->zone = 0;
316  }
317  }
318 
319  /* -------------------------------------------------------------------- */
320  /* Get the coordinate system definition in PROJ.4 format. */
321  /* -------------------------------------------------------------------- */
322  if (OSRExportToProj4(hSRS, &pszProj4) != OGRERR_NONE)
323  goto default_to_xy;
324 
325  /* -------------------------------------------------------------------- */
326  /* Parse the PROJ.4 string into key/value pairs. Do a bit of */
327  /* extra work to "GRASSify" the result. */
328  /* -------------------------------------------------------------------- */
329  temp_projinfo = G_create_key_value();
330 
331  /* Create "local" copy of proj4 string so we can modify and free it
332  * using GRASS functions */
333  pszRemaining = G_store(pszProj4);
334  CPLFree(pszProj4);
335  pszProj4 = pszRemaining;
336  while ((pszRemaining = strstr(pszRemaining, "+")) != NULL) {
337  char *pszToken, *pszValue;
338 
339  pszRemaining++;
340 
341  /* Advance pszRemaining to end of this token[=value] pair */
342  pszToken = pszRemaining;
343  while (*pszRemaining != ' ' && *pszRemaining != '\0')
344  pszRemaining++;
345 
346  if (*pszRemaining == ' ') {
347  *pszRemaining = '\0';
348  pszRemaining++;
349  }
350 
351  /* parse token, and value */
352  if (strstr(pszToken, "=") != NULL) {
353  pszValue = strstr(pszToken, "=");
354  *pszValue = '\0';
355  pszValue++;
356  }
357  else
358  pszValue = "defined";
359 
360 
361  if (G_strcasecmp(pszToken, "proj") == 0) {
362  /* The ll projection is known as longlat in PROJ.4 */
363  if (G_strcasecmp(pszValue, "longlat") == 0)
364  pszValue = "ll";
365 
366  pszProj = pszValue;
367  continue;
368  }
369 
370  /* Ellipsoid and datum handled separately below */
371  if (G_strcasecmp(pszToken, "ellps") == 0
372  || G_strcasecmp(pszToken, "a") == 0
373  || G_strcasecmp(pszToken, "b") == 0
374  || G_strcasecmp(pszToken, "es") == 0
375  || G_strcasecmp(pszToken, "rf") == 0
376  || G_strcasecmp(pszToken, "datum") == 0)
377  continue;
378 
379  /* We will handle units separately */
380  if (G_strcasecmp(pszToken, "to_meter") == 0
381  || G_strcasecmp(pszToken, "units") == 0)
382  continue;
383 
384  G_set_key_value(pszToken, pszValue, temp_projinfo);
385  }
386 
387  *projinfo = G_create_key_value();
388 
389  /* -------------------------------------------------------------------- */
390  /* Derive the user name for the projection. */
391  /* -------------------------------------------------------------------- */
392  if (pszProj) {
393  char path[4095];
394  char name[80];
395 
396  sprintf(path, "%s/etc/proj/projections", G_gisbase());
397  if (G_lookup_key_value_from_file(path, pszProj, name, sizeof(name)) >
398  0)
399  G_set_key_value("name", name, *projinfo);
400  else
401  G_set_key_value("name", pszProj, *projinfo);
402 
403  G_set_key_value("proj", pszProj, *projinfo);
404  }
405  else
406  G_warning(_("No projection name! Projection parameters likely to be meaningless."));
407 
408 
409  /* -------------------------------------------------------------------- */
410  /* Find the GRASS datum name and choose parameters either */
411  /* interactively or not. */
412  /* -------------------------------------------------------------------- */
413 
414  {
415  const char *pszDatumNameConst = OSRGetAttrValue(hSRS, "DATUM", 0);
416  struct datum_list *list, *listhead;
417  char *dum1, *dum2, *pszDatumName;
418  int paramspresent =
419  GPJ__get_datum_params(temp_projinfo, &dum1, &dum2);
420 
421  if (pszDatumNameConst) {
422  /* Need to make a new copy of the string so we don't mess
423  * around with the memory inside the OGRSpatialReferenceH? */
424 
425  pszDatumName = G_store(pszDatumNameConst);
426  DatumNameMassage(&pszDatumName);
427 
428  list = listhead = read_datum_table();
429 
430  while (list != NULL) {
431  if (G_strcasecmp(pszDatumName, list->longname) == 0) {
432  datum = G_store(list->name);
433  break;
434  }
435  list = list->next;
436  }
437  free_datum_list(listhead);
438 
439  if (datum == NULL) {
440  if (paramspresent < 2)
441  /* Only give warning if no parameters present */
442  G_warning(_("Datum <%s> not recognised by GRASS and no parameters found"),
443  pszDatumName);
444  }
445  else {
446  G_set_key_value("datum", datum, *projinfo);
447 
448  if (paramspresent < 2) {
449  /* If no datum parameters were imported from the OSR
450  * object then we should use the set specified by datumtrans */
451  char *params, *chosenparams = NULL;
452  int paramsets;
453 
454  paramsets =
455  GPJ_get_default_datum_params_by_name(datum, &params);
456 
457  if (paramsets < 0)
458  G_warning(_("Datum <%s> apparently recognised by GRASS but no parameters found. "
459  "You may want to look into this."), datum);
460  else if (datumtrans > paramsets) {
461 
462  G_warning(_("Invalid transformation number %d; valid range is 1 to %d. "
463  "Leaving datum transform parameters unspecified."),
464  datumtrans, paramsets);
465  datumtrans = 0;
466  }
467 
468  if (paramsets > 0) {
469  struct gpj_datum_transform_list *list, *old;
470 
471  list = GPJ_get_datum_transform_by_name(datum);
472 
473  if (list != NULL) {
474  do {
475  if (list->count == datumtrans)
476  chosenparams = G_store(list->params);
477  old = list;
478  list = list->next;
480  } while (list != NULL);
481  }
482  }
483 
484  if (chosenparams != NULL) {
485  char *paramkey, *paramvalue;
486 
487  paramkey = strtok(chosenparams, "=");
488  paramvalue = chosenparams + strlen(paramkey) + 1;
489  G_set_key_value(paramkey, paramvalue, *projinfo);
490  G_free(chosenparams);
491  }
492 
493  if (paramsets > 0)
494  G_free(params);
495  }
496 
497  }
498  G_free(pszDatumName);
499  }
500  }
501 
502  /* -------------------------------------------------------------------- */
503  /* Determine an appropriate GRASS ellipsoid name if possible, or */
504  /* else just put a and es values into PROJ_INFO */
505  /* -------------------------------------------------------------------- */
506 
507  if ((datum != NULL) && (GPJ_get_datum_by_name(datum, &dstruct) > 0)) {
508  /* Use ellps name associated with datum */
509  G_set_key_value("ellps", dstruct.ellps, *projinfo);
510  GPJ_free_datum(&dstruct);
511  G_free(datum);
512  }
513  else {
514  /* If we can't determine the ellipsoid from the datum, derive it
515  * directly from "SPHEROID" parameters in WKT */
516  const char *pszSemiMajor = OSRGetAttrValue(hSRS, "SPHEROID", 1);
517  const char *pszInvFlat = OSRGetAttrValue(hSRS, "SPHEROID", 2);
518 
519  if (pszSemiMajor != NULL && pszInvFlat != NULL) {
520  char *ellps = NULL;
521  struct ellps_list *list, *listhead;
522  double a = atof(pszSemiMajor), invflat = atof(pszInvFlat), flat;
523  double es;
524 
525  /* Allow for incorrect WKT describing a sphere where InvFlat
526  * is given as 0 rather than inf */
527  if (invflat > 0)
528  flat = 1 / invflat;
529  else
530  flat = 0;
531 
532  es = flat * (2.0 - flat);
533 
534  list = listhead = read_ellipsoid_table(0);
535 
536  while (list != NULL) {
537  /* Try and match a and es against GRASS defined ellipsoids;
538  * accept first one that matches. These numbers were found
539  * by trial and error and could be fine-tuned, or possibly
540  * a direct comparison of IEEE floating point values used. */
541  if ((a == list->a || fabs(a - list->a) < 0.1 || fabs(1 - a / list->a) < 0.0000001) && ((es == 0 && list->es == 0) || /* Special case for sphere */
542  (invflat == list->rf || fabs(invflat - list->rf) < 0.0000001))) {
543  ellps = G_store(list->name);
544  break;
545  }
546  list = list->next;
547  }
548  if (listhead != NULL)
549  free_ellps_list(listhead);
550 
551  if (ellps == NULL) {
552  /* If we weren't able to find a matching ellps name, set
553  * a and es values directly from WKT-derived data */
554  char es_str[100];
555 
556  G_set_key_value("a", (char *)pszSemiMajor, *projinfo);
557 
558  sprintf(es_str, "%.16g", es);
559  G_set_key_value("es", es_str, *projinfo);
560  }
561  else {
562  /* else specify the GRASS ellps name for readability */
563  G_set_key_value("ellps", ellps, *projinfo);
564  G_free(ellps);
565  }
566 
567  }
568 
569  }
570 
571  /* -------------------------------------------------------------------- */
572  /* Finally append the detailed projection parameters to the end */
573  /* -------------------------------------------------------------------- */
574 
575  {
576  int i;
577 
578  for (i = 0; i < temp_projinfo->nitems; i++)
579  G_set_key_value(temp_projinfo->key[i],
580  temp_projinfo->value[i], *projinfo);
581 
582  G_free_key_value(temp_projinfo);
583  }
584 
585  G_free(pszProj4);
586 
587  /* -------------------------------------------------------------------- */
588  /* Set the linear units. */
589  /* -------------------------------------------------------------------- */
590  *projunits = G_create_key_value();
591 
592  if (OSRIsGeographic(hSRS)) {
593  /* We assume degrees ... someday we will be wrong! */
594  G_set_key_value("unit", "degree", *projunits);
595  G_set_key_value("units", "degrees", *projunits);
596  G_set_key_value("meters", "1.0", *projunits);
597  }
598  else {
599  char szFormatBuf[256];
600  char *pszUnitsName = NULL;
601  double dfToMeters;
602  char *pszUnitsPlural, *pszStringEnd;
603 
604  dfToMeters = OSRGetLinearUnits(hSRS, &pszUnitsName);
605 
606  /* Workaround for the most obvious case when unit name is unknown */
607  if ((G_strcasecmp(pszUnitsName, "unknown") == 0) &&
608  (dfToMeters == 1.))
609  G_asprintf(&pszUnitsName, "meter");
610 
611  if ((G_strcasecmp(pszUnitsName, "metre") == 0))
612  G_asprintf(&pszUnitsName, "meter");
613  if ((G_strcasecmp(pszUnitsName, "kilometre") == 0))
614  G_asprintf(&pszUnitsName, "kilometer");
615 
616  G_set_key_value("unit", pszUnitsName, *projunits);
617 
618  /* Attempt at plural formation (WKT format doesn't store plural
619  * form of unit name) */
620  pszUnitsPlural = G_malloc(strlen(pszUnitsName) + 3);
621  strcpy(pszUnitsPlural, pszUnitsName);
622  pszStringEnd = pszUnitsPlural + strlen(pszUnitsPlural) - 4;
623  if (G_strcasecmp(pszStringEnd, "foot") == 0) {
624  /* Special case for foot - change two o's to e's */
625  pszStringEnd[1] = 'e';
626  pszStringEnd[2] = 'e';
627  }
628  else if (G_strcasecmp(pszStringEnd, "inch") == 0) {
629  /* Special case for inch - add es */
630  pszStringEnd[4] = 'e';
631  pszStringEnd[5] = 's';
632  pszStringEnd[6] = '\0';
633  }
634  else {
635  /* For anything else add an s at the end */
636  pszStringEnd[4] = 's';
637  pszStringEnd[5] = '\0';
638  }
639 
640  G_set_key_value("units", pszUnitsPlural, *projunits);
641  G_free(pszUnitsPlural);
642 
643  sprintf(szFormatBuf, "%.16g", dfToMeters);
644  G_set_key_value("meters", szFormatBuf, *projunits);
645 
646  }
647 
648  return 2;
649 
650  /* -------------------------------------------------------------------- */
651  /* Fallback to returning an ungeoreferenced definition. */
652  /* -------------------------------------------------------------------- */
653  default_to_xy:
654  if (cellhd != NULL) {
655  cellhd->proj = PROJECTION_XY;
656  cellhd->zone = 0;
657  }
658 
659  *projinfo = NULL;
660  *projunits = NULL;
661 
662  return 1;
663 }
664 #endif
665 
686 int GPJ_wkt_to_grass(struct Cell_head *cellhd, struct Key_Value **projinfo,
687  struct Key_Value **projunits, const char *wkt,
688  int datumtrans)
689 {
690 #ifdef HAVE_OGR
691  int retval;
692 
693  if (wkt == NULL)
694  retval =
695  GPJ_osr_to_grass(cellhd, projinfo, projunits, NULL, datumtrans);
696  else {
697  OGRSpatialReferenceH hSRS;
698 
699  /* Set finder function for locating OGR csv co-ordinate system tables */
700  SetCSVFilenameHook(GPJ_set_csv_loc);
701 
702  hSRS = OSRNewSpatialReference(wkt);
703  retval =
704  GPJ_osr_to_grass(cellhd, projinfo, projunits, hSRS, datumtrans);
705  OSRDestroySpatialReference(hSRS);
706  }
707 
708  return retval;
709 #else
710  return -1;
711 #endif
712 }
713 
714 #ifdef HAVE_OGR
715 /* GPJ_set_csv_loc()
716  * 'finder function' for use with OGR SetCSVFilenameHook() function */
717 
718 const char *GPJ_set_csv_loc(const char *name)
719 {
720  const char *gisbase = G_gisbase();
721  static char *buf = NULL;
722 
723  if (buf != NULL)
724  G_free(buf);
725 
726  G_asprintf(&buf, "%s%s/%s", gisbase, CSVDIR, name);
727 
728  return buf;
729 }
730 
731 
732 /* The list below is only for files that use a non-standard name for a
733  * datum that is already supported in GRASS. The number of entries must be even;
734  * they are all in pairs. The first one in the pair is the non-standard name;
735  * the second is the GRASS name. If a name appears more than once (as for
736  * European_Terrestrial_Reference_System_1989) then it means there was more
737  * than one non-standard name for it that needs to be accounted for.
738  *
739  * N.B. The order of these pairs is different from that in
740  * ogr/ogrfromepsg.cpp in the GDAL source tree! GRASS uses the EPSG
741  * names in its WKT representation except WGS_1984 and WGS_1972 as
742  * these shortened versions seem to be standard
743  */
744 
745 static const char *papszDatumEquiv[] = {
746  "Militar_Geographische_Institute",
747  "Militar_Geographische_Institut",
748  "World_Geodetic_System_1984",
749  "WGS_1984",
750  "World_Geodetic_System_1972",
751  "WGS_1972",
752  "European_Terrestrial_Reference_System_89",
753  "European_Terrestrial_Reference_System_1989",
754  "European_Reference_System_1989",
755  "European_Terrestrial_Reference_System_1989",
756  "ETRS_1989",
757  "European_Terrestrial_Reference_System_1989",
758  "ETRS89",
759  "European_Terrestrial_Reference_System_1989",
760  "ETRF_1989",
761  "European_Terrestrial_Reference_System_1989",
762  "NZGD_2000",
763  "New_Zealand_Geodetic_Datum_2000",
764  "Monte_Mario_Rome",
765  "Monte_Mario",
766  "MONTROME",
767  "Monte_Mario",
768  "Campo_Inchauspe_1969",
769  "Campo_Inchauspe",
770  "S_JTSK_Ferro",
771  "Militar_Geographische_Institut",
772  "Potsdam_Datum_83",
773  "Deutsches_Hauptdreiecksnetz",
774  "South_American_1969",
775  "South_American_Datum_1969",
776  "ITRF_1992",
777  "ITRF92",
778  NULL
779 };
780 
781 /************************************************************************/
782 /* OGREPSGDatumNameMassage() */
783 /* */
784 /* Massage an EPSG datum name into WMT format. Also transform */
785 /* specific exception cases into WKT versions. */
786 
787 /************************************************************************/
788 
789 static void DatumNameMassage(char **ppszDatum)
790 {
791  int i, j;
792  char *pszDatum = *ppszDatum;
793 
794  /* -------------------------------------------------------------------- */
795  /* Translate non-alphanumeric values to underscores. */
796  /* -------------------------------------------------------------------- */
797  for (i = 0; pszDatum[i] != '\0'; i++) {
798  if (!(pszDatum[i] >= 'A' && pszDatum[i] <= 'Z')
799  && !(pszDatum[i] >= 'a' && pszDatum[i] <= 'z')
800  && !(pszDatum[i] >= '0' && pszDatum[i] <= '9')) {
801  pszDatum[i] = '_';
802  }
803  }
804 
805  /* -------------------------------------------------------------------- */
806  /* Remove repeated and trailing underscores. */
807  /* -------------------------------------------------------------------- */
808  for (i = 1, j = 0; pszDatum[i] != '\0'; i++) {
809  if (pszDatum[j] == '_' && pszDatum[i] == '_')
810  continue;
811 
812  pszDatum[++j] = pszDatum[i];
813  }
814  if (pszDatum[j] == '_')
815  pszDatum[j] = '\0';
816  else
817  pszDatum[j + 1] = '\0';
818 
819  /* -------------------------------------------------------------------- */
820  /* Search for datum equivalences. Specific massaged names get */
821  /* mapped to OpenGIS specified names. */
822  /* -------------------------------------------------------------------- */
823  for (i = 0; papszDatumEquiv[i] != NULL; i += 2) {
824  if (EQUAL(*ppszDatum, papszDatumEquiv[i])) {
825  G_free(*ppszDatum);
826  *ppszDatum = G_store(papszDatumEquiv[i + 1]);
827  break;
828  }
829  }
830 }
831 
832 #endif /* HAVE_OGR */
int GPJ_wkt_to_grass(struct Cell_head *cellhd, struct Key_Value **projinfo, struct Key_Value **projunits, const char *wkt, int datumtrans)
Converts a WKT projection description to a GRASS co-ordinate system.
Definition: convert.c:686
int G_strcasecmp(const char *x, const char *y)
String compare ignoring case (upper or lower)
Definition: strings.c:46
const char * G_find_key_value(const char *key, const struct Key_Value *kv)
Find given key (case sensitive)
Definition: key_value1.c:84
void GPJ_free_datum(struct gpj_datum *dstruct)
Free the memory used for the strings in a gpj_datum struct.
Definition: proj/datum.c:395
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:173
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:318
struct ellps_list * read_ellipsoid_table(int fatal)
Definition: ellipse.c:201
int GPJ_osr_to_grass(struct Cell_head *cellhd, struct Key_Value **projinfo, struct Key_Value **projunits, OGRSpatialReferenceH hSRS, int datumtrans)
Converts an OGRSpatialReferenceH object to a GRASS co-ordinate system.
Definition: convert.c:274
char * GPJ_grass_to_wkt(const struct Key_Value *proj_info, const struct Key_Value *proj_units, int esri_style, int prettify)
Converts a GRASS co-ordinate system representation to WKT style.
Definition: convert.c:55
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:86
int G_asprintf(char **out, const char *fmt,...)
Definition: asprintf.c:70
#define NULL
Definition: ccmath.h:32
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:229
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
void G_free_key_value(struct Key_Value *kv)
Free allocated Key_Value structure.
Definition: key_value1.c:103
int GPJ__get_ellipsoid_params(const struct Key_Value *proj_keys, double *a, double *e2, double *rf)
Definition: ellipse.c:52
int G_lookup_key_value_from_file(const char *file, const char *key, char value[], int n)
Look up for key in file.
Definition: key_value4.c:48
#define EQUAL(a, b)
Definition: gsdrape.c:64
void free_datum_list(struct datum_list *dstruct)
Free the memory used by a datum_list linked list structure.
Definition: proj/datum.c:409
struct list * list
Definition: read_list.c:24
#define CSVDIR
Definition: convert.c:31
const char * GPJ_set_csv_loc(const char *name)
Definition: convert.c:718
void GPJ_free_ellps(struct gpj_ellps *estruct)
Definition: ellipse.c:281
OGRSpatialReferenceH GPJ_grass_to_osr(const struct Key_Value *proj_info, const struct Key_Value *proj_units)
Converts a GRASS co-ordinate system to an OGRSpatialReferenceH object.
Definition: convert.c:97
struct datum_list * read_datum_table(void)
Read the current GRASS datum.table from disk and store in memory.
Definition: proj/datum.c:337
int pj_get_kv(struct pj_info *info, const struct Key_Value *in_proj_keys, const 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:59
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:85
Definition: path.h:16
void G_set_key_value(const char *key, const char *value, struct Key_Value *kv)
Set value for given key.
Definition: key_value1.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:136
const char * name
Definition: named_colr.c:7
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
const char * G_gisbase(void)
Get full path name of the top level module directory.
Definition: gisbase.c:41
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:203
struct Key_Value * G_create_key_value(void)
Allocate and initialize Key_Value structure.
Definition: key_value1.c:23
void free_ellps_list(struct ellps_list *elist)
Definition: ellipse.c:288