27 #include "local_proto.h" 
   30 #define CSVDIR "/etc/proj/ogr_csv" 
   32 static void DatumNameMassage(
char **);
 
   44     {
"km", 
"1000.", 
"Kilometer", 1000.0},
 
   45     {
"m", 
"1.", 
"Meter", 1.0},
 
   46     {
"dm", 
"1/10", 
"Decimeter", 0.1},
 
   47     {
"cm", 
"1/100", 
"Centimeter", 0.01},
 
   48     {
"mm", 
"1/1000", 
"Millimeter", 0.001},
 
   49     {
"kmi", 
"1852.0", 
"International Nautical Mile", 1852.0},
 
   50     {
"in", 
"0.0254", 
"International Inch", 0.0254},
 
   51     {
"ft", 
"0.3048", 
"International Foot", 0.3048},
 
   52     {
"yd", 
"0.9144", 
"International Yard", 0.9144},
 
   53     {
"mi", 
"1609.344", 
"International Statute Mile", 1609.344},
 
   54     {
"fath", 
"1.8288", 
"International Fathom", 1.8288},
 
   55     {
"ch", 
"20.1168", 
"International Chain", 20.1168},
 
   56     {
"link", 
"0.201168", 
"International Link", 0.201168},
 
   57     {
"us-in", 
"1./39.37", 
"U.S. Surveyor's Inch", 0.0254},
 
   58     {
"us-ft", 
"0.304800609601219", 
"U.S. Surveyor's Foot", 0.304800609601219},
 
   59     {
"us-yd", 
"0.914401828803658", 
"U.S. Surveyor's Yard", 0.914401828803658},
 
   60     {
"us-ch", 
"20.11684023368047", 
"U.S. Surveyor's Chain", 20.11684023368047},
 
   61     {
"us-mi", 
"1609.347218694437", 
"U.S. Surveyor's Statute Mile",
 
   63     {
"ind-yd", 
"0.91439523", 
"Indian Yard", 0.91439523},
 
   64     {
"ind-ft", 
"0.30479841", 
"Indian Foot", 0.30479841},
 
   65     {
"ind-ch", 
"20.11669506", 
"Indian Chain", 20.11669506},
 
   68 static char *grass_to_wkt(
const struct Key_Value *proj_info,
 
   70                           const struct Key_Value *proj_epsg, 
int esri_style,
 
   74     OGRSpatialReferenceH hSRS;
 
   75     char *wkt, *local_wkt;
 
   86         OSRExportToPrettyWkt(hSRS, &wkt, 0);
 
   88         OSRExportToWkt(hSRS, &wkt);
 
   92     OSRDestroySpatialReference(hSRS);
 
   96     G_warning(
_(
"GRASS is not compiled with OGR support"));
 
  120                        const struct Key_Value *proj_units, 
int esri_style,
 
  123     return grass_to_wkt(proj_info, proj_units, 
NULL, esri_style, prettify);
 
  152                         const struct Key_Value *proj_epsg, 
int esri_style,
 
  155     return grass_to_wkt(proj_info, proj_units, proj_epsg, esri_style, prettify);
 
  172     char *proj4, *proj4mod, *
wkt, *modwkt, *startmod, *lastpart;
 
  173     OGRSpatialReferenceH hSRS, hSRS2;
 
  178     const char *ellpskv, *unit, *unfact;
 
  179     char *ellps, *ellpslong, *datum, *params, *towgs84, *datumlongname, *start,
 
  181     const char *sysname, *osrunit;
 
  185     if ((proj_info == 
NULL) || (proj_units == 
NULL))
 
  188     hSRS = OSRNewSpatialReference(
NULL);
 
  191     if (
pj_get_kv(&pjinfo, proj_info, proj_units) < 0) {
 
  192         G_warning(
_(
"Unable parse GRASS PROJ_INFO file"));
 
  198     if ((proj4 = pjinfo.
def) == 
NULL) {
 
  199         G_warning(
_(
"Unable get PROJ.4-style parameter string"));
 
  203     proj_destroy(pjinfo.
pj);
 
  210     if (unfact != 
NULL && (strcmp(pjinfo.
proj, 
"ll") != 0))
 
  211         G_asprintf(&proj4mod, 
"%s +to_meter=%s", proj4, unfact);
 
  216     if ((errcode = OSRImportFromProj4(hSRS, proj4mod)) != OGRERR_NONE) {
 
  217         G_warning(
_(
"OGR can't parse PROJ.4-style parameter string: " 
  218                     "%s (OGR Error code was %d)"),
 
  230     if ((errcode = OSRExportToWkt(hSRS, &wkt)) != OGRERR_NONE) {
 
  231         G_warning(
_(
"OGR can't get WKT-style parameter string " 
  232                     "(OGR Error code was %d)"),
 
  247         datumlongname = 
G_store(
"unknown");
 
  257     G_debug(3, 
"GPJ_grass_to_osr: datum: <%s>", datum);
 
  261         DatumNameMassage(&ellpslong);
 
  267     startmod = strstr(wkt, 
"GEOGCS");
 
  268     lastpart = strstr(wkt, 
"PRIMEM");
 
  269     len = strlen(wkt) - strlen(startmod);
 
  271     if (haveparams == 2) {
 
  274         char *paramkey, *paramvalue;
 
  276         paramkey = strtok(params, 
"=");
 
  277         paramvalue = params + strlen(paramkey) + 1;
 
  279             G_asprintf(&towgs84, 
",TOWGS84[%s]", paramvalue);
 
  287     sysname = OSRGetAttrValue(hSRS, 
"PROJCS", 0);
 
  288     if (sysname == 
NULL) {
 
  294         if ((strcmp(sysname, 
"unnamed") == 0) &&
 
  301         osrunit = OSRGetAttrValue(hSRS, 
"UNIT", 0);
 
  307             double unfactf = atof(unfact);
 
  311             startmod = strstr(lastpart, buff);
 
  312             len = strlen(lastpart) - strlen(startmod);
 
  313             lastpart[len] = 
'\0';
 
  318             G_asprintf(&end, 
",UNIT[\"%s\",%.16g]]", unit, unfactf);
 
  321     OSRDestroySpatialReference(hSRS);
 
  324         "%sGEOGCS[\"%s\",DATUM[\"%s\",SPHEROID[\"%s\",%.16g,%.16g]%s],%s%s",
 
  325         start, ellps, datumlongname, ellpslong, 
a, 
rf, towgs84, lastpart, end);
 
  326     hSRS2 = OSRNewSpatialReference(modwkt);
 
  369             epsgcode = atoi(epsgstr);
 
  374         OGRSpatialReferenceH hSRS;
 
  376         hSRS = OSRNewSpatialReference(
NULL);
 
  378         OSRImportFromEPSG(hSRS, epsgcode);
 
  385             double df[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
  390                 df[i] = atof(tokens[i]);
 
  393             OSRSetTOWGS84(hSRS, df[0], df[1], df[2], df[3], df[4], df[5],
 
  426                      struct Key_Value **projunits, OGRSpatialReferenceH hSRS1,
 
  429     struct Key_Value *temp_projinfo, *temp_projinfo_ext;
 
  430     char *pszProj4 = 
NULL, *pszRemaining;
 
  431     char *pszProj = 
NULL;
 
  432     const char *pszProjCS = 
NULL;
 
  434     char *proj4_unit = 
NULL;
 
  437     OGRSpatialReferenceH hSRS;
 
  438     int use_proj_extension;
 
  453     OSRMorphFromESRI(hSRS);
 
  456     use_proj_extension = 0;
 
  459     ograttr = OSRGetAttrValue(hSRS, 
"EXTENSION", 0);
 
  460     if (ograttr && *ograttr && strcmp(ograttr, 
"PROJ4") == 0) {
 
  461         ograttr = OSRGetAttrValue(hSRS, 
"EXTENSION", 1);
 
  462         G_debug(3, 
"proj4 extension:");
 
  465         if (ograttr && *ograttr) {
 
  467             OGRSpatialReferenceH hSRS2;
 
  469             hSRS2 = OSRNewSpatialReference(
NULL);
 
  473             if (OSRImportFromProj4(hSRS2, proj4ext) != OGRERR_NONE) {
 
  474                 G_warning(
_(
"Updating spatial reference with embedded proj4 " 
  475                             "definition failed. " 
  476                             "Proj4 definition: <%s>"),
 
  478                 OSRDestroySpatialReference(hSRS2);
 
  485                 G_warning(
_(
"Updating spatial reference with embedded proj4 " 
  493                 pszProjCS = OSRGetAttrValue(hSRS, 
"PROJCS", 0);
 
  495                     pszProjCS = OSRGetAttrValue(hSRS, 
"GEOGCS", 0);
 
  507                     snprintf(
path, 
sizeof(
path), 
"%s/etc/proj/projections",
 
  518                 use_proj_extension = 1;
 
  527     if (!OSRIsGeographic(hSRS) && !OSRIsProjected(hSRS))
 
  533         if (OSRIsGeographic(hSRS)) {
 
  537         else if (OSRGetUTMZone(hSRS, &bNorth) != 0) {
 
  539             cellhd->
zone = OSRGetUTMZone(hSRS, &bNorth);
 
  552     if (OSRExportToProj4(hSRS, &pszProj4) != OGRERR_NONE)
 
  564     pszRemaining = 
G_store(pszProj4);
 
  566     pszProj4 = pszRemaining;
 
  567     while ((pszRemaining = strstr(pszRemaining, 
"+")) != 
NULL) {
 
  568         char *pszToken, *pszValue;
 
  573         pszToken = pszRemaining;
 
  574         while (*pszRemaining != 
' ' && *pszRemaining != 
'\0')
 
  577         if (*pszRemaining == 
' ') {
 
  578             *pszRemaining = 
'\0';
 
  583         if (strstr(pszToken, 
"=") != 
NULL) {
 
  584             pszValue = strstr(pszToken, 
"=");
 
  589             pszValue = 
"defined";
 
  616             proj4_unit = 
G_store(pszValue);
 
  623         G_warning(
_(
"No projection name! Projection parameters likely to be " 
  630         pszProjCS = OSRGetAttrValue(hSRS, 
"PROJCS", 0);
 
  632             pszProjCS = OSRGetAttrValue(hSRS, 
"GEOGCS", 0);
 
  643             snprintf(
path, 
sizeof(
path), 
"%s/etc/proj/projections",
 
  659         const char *pszDatumNameConst;
 
  660         struct datum_list *
list, *listhead;
 
  661         char *dum1, *dum2, *pszDatumName;
 
  664         if (!use_proj_extension)
 
  665             pszDatumNameConst = OSRGetAttrValue(hSRS, 
"DATUM", 0);
 
  669         if (pszDatumNameConst) {
 
  673             pszDatumName = 
G_store(pszDatumNameConst);
 
  674             DatumNameMassage(&pszDatumName);
 
  675             G_debug(3, 
"GPJ_osr_to_grass: pszDatumNameConst: <%s>",
 
  690                 if (paramspresent < 2)
 
  693                             "Datum <%s> not recognised by GRASS and no " 
  700                 if (paramspresent < 2) {
 
  704                     char *params, *chosenparams = 
NULL;
 
  712                                 "Datum <%s> apparently recognised by GRASS but " 
  713                                 "no parameters found. " 
  714                                 "You may want to look into this.",
 
  716                     else if (datumtrans > paramsets) {
 
  720                             "Invalid transformation number %d; valid range is " 
  722                             "Leaving datum transform parameters unspecified.",
 
  723                             datumtrans, paramsets);
 
  734                                 if (tlist->
count == datumtrans)
 
  739                             } 
while (tlist != 
NULL);
 
  743                     if (chosenparams != 
NULL) {
 
  744                         char *paramkey, *paramvalue;
 
  746                         paramkey = strtok(chosenparams, 
"=");
 
  747                         paramvalue = chosenparams + strlen(paramkey) + 1;
 
  771     else if (!use_proj_extension) {
 
  774         const char *pszSemiMajor = OSRGetAttrValue(hSRS, 
"SPHEROID", 1);
 
  775         const char *pszInvFlat = OSRGetAttrValue(hSRS, 
"SPHEROID", 2);
 
  777         if (pszSemiMajor != 
NULL && pszInvFlat != 
NULL) {
 
  779             struct ellps_list *
list, *listhead;
 
  780             double a = atof(pszSemiMajor), invflat = atof(pszInvFlat), flat;
 
  790             es = flat * (2.0 - flat);
 
  799                 if ((a == 
list->a || fabs(a - 
list->a) < 0.1 ||
 
  800                      fabs(1 - a / 
list->a) < 0.0000001) &&
 
  801                     ((es == 0 && 
list->es == 0) ||
 
  803                      (invflat == 
list->rf ||
 
  804                       fabs(invflat - 
list->rf) < 0.0000001))) {
 
  810             if (listhead != 
NULL)
 
  820                 snprintf(es_str, 
sizeof(es_str), 
"%.16g", es);
 
  830     else if (use_proj_extension) {
 
  836             snprintf(parmstr, 
sizeof(parmstr), 
"%.16g", a);
 
  838             snprintf(parmstr, 
sizeof(parmstr), 
"%.16g", es);
 
  850         for (i = 0; i < temp_projinfo->
nitems; i++)
 
  865     if (OSRIsGeographic(hSRS)) {
 
  872         char szFormatBuf[256];
 
  873         char *pszUnitsName = 
NULL;
 
  875         char *pszUnitsPlural, *pszStringEnd;
 
  877         dfToMeters = OSRGetLinearUnits(hSRS, &pszUnitsName);
 
  887         if ((
G_strcasecmp(pszUnitsName, 
"unknown") == 0) && (dfToMeters == 1.))
 
  895         if (dfToMeters != 1. && proj4_unit) {
 
  900                 if (strcmp(proj4_unit, 
gpj_units[i].
id) == 0) {
 
  912         pszUnitsPlural = 
G_malloc(strlen(pszUnitsName) + 3);
 
  913         strcpy(pszUnitsPlural, pszUnitsName);
 
  914         pszStringEnd = pszUnitsPlural + strlen(pszUnitsPlural) - 4;
 
  917             pszStringEnd[1] = 
'e';
 
  918             pszStringEnd[2] = 
'e';
 
  922             pszStringEnd[4] = 
'e';
 
  923             pszStringEnd[5] = 
's';
 
  924             pszStringEnd[6] = 
'\0';
 
  928             pszStringEnd[4] = 
's';
 
  929             pszStringEnd[5] = 
'\0';
 
  935         snprintf(szFormatBuf, 
sizeof(szFormatBuf), 
"%.16g", dfToMeters);
 
  940         OSRDestroySpatialReference(hSRS);
 
  948     if (cellhd != 
NULL) {
 
  958     if (hSRS != 
NULL && hSRS != hSRS1)
 
  959         OSRDestroySpatialReference(hSRS);
 
  985                      struct Key_Value **projunits, 
const char *wkt,
 
  995         OGRSpatialReferenceH hSRS;
 
 1000         hSRS = OSRNewSpatialReference(wkt);
 
 1003         OSRDestroySpatialReference(hSRS);
 
 1019     static char *buf = 
NULL;
 
 1052 static const char *papszDatumEquiv[] = {
 
 1053     "Militar_Geographische_Institute",
 
 1054     "Militar_Geographische_Institut",
 
 1055     "World_Geodetic_System_1984",
 
 1057     "World_Geodetic_System_1972",
 
 1059     "European_Terrestrial_Reference_System_89",
 
 1060     "European_Terrestrial_Reference_System_1989",
 
 1061     "European_Reference_System_1989",
 
 1062     "European_Terrestrial_Reference_System_1989",
 
 1064     "European_Terrestrial_Reference_System_1989",
 
 1066     "European_Terrestrial_Reference_System_1989",
 
 1068     "European_Terrestrial_Reference_System_1989",
 
 1070     "New_Zealand_Geodetic_Datum_2000",
 
 1075     "Campo_Inchauspe_1969",
 
 1078     "System_Jednotne_Trigonometricke_Site_Katastralni",
 
 1080     "Militar_Geographische_Institut",
 
 1082     "Deutsches_Hauptdreiecksnetz",
 
 1083     "Rauenberg_Datum_83",
 
 1084     "Deutsches_Hauptdreiecksnetz",
 
 1085     "South_American_1969",
 
 1086     "South_American_Datum_1969",
 
 1087     "International_Terrestrial_Reference_Frame_1992",
 
 1101 static void DatumNameMassage(
char **ppszDatum)
 
 1104     char *pszDatum = *ppszDatum;
 
 1106     G_debug(3, 
"DatumNameMassage: Raw string found <%s>", (
char *)pszDatum);
 
 1110     for (i = 0; pszDatum[i] != 
'\0'; i++) {
 
 1111         if (!(pszDatum[i] >= 
'A' && pszDatum[i] <= 
'Z') &&
 
 1112             !(pszDatum[i] >= 
'a' && pszDatum[i] <= 
'z') &&
 
 1113             !(pszDatum[i] >= 
'0' && pszDatum[i] <= 
'9')) {
 
 1121     for (i = 1, j = 0; pszDatum[i] != 
'\0'; i++) {
 
 1122         if (pszDatum[j] == 
'_' && pszDatum[i] == 
'_')
 
 1125         pszDatum[++j] = pszDatum[i];
 
 1127     if (pszDatum[j] == 
'_')
 
 1130         pszDatum[j + 1] = 
'\0';
 
 1136     G_debug(3, 
"DatumNameMassage: Search for datum equivalences of <%s>",
 
 1138     for (i = 0; papszDatumEquiv[i] != 
NULL; i += 2) {
 
 1139         if (
EQUAL(*ppszDatum, papszDatumEquiv[i])) {
 
 1141             *ppszDatum = 
G_store(papszDatumEquiv[i + 1]);
 
struct gpj_units gpj_units[]
OGRSpatialReferenceH GPJ_grass_to_osr2(const struct Key_Value *proj_info, const struct Key_Value *proj_units, const struct Key_Value *proj_epsg)
Converts a GRASS co-ordinate system to an OGRSpatialReferenceH object. EPSG code is preferred if avai...
const char * GPJ_set_csv_loc(const char *name)
int GPJ_osr_to_grass(struct Cell_head *cellhd, struct Key_Value **projinfo, struct Key_Value **projunits, OGRSpatialReferenceH hSRS1, int datumtrans)
Converts an OGRSpatialReferenceH object to a GRASS co-ordinate system.
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.
char * GPJ_grass_to_wkt2(const struct Key_Value *proj_info, const struct Key_Value *proj_units, const struct Key_Value *proj_epsg, int esri_style, int prettify)
Converts a GRASS co-ordinate system representation to WKT style. EPSG code is preferred if available.
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.
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.
void G_free(void *)
Free allocated memory.
void G_warning(const char *,...) __attribute__((format(printf
const char * G_find_key_value(const char *, const struct Key_Value *)
Find given key (case sensitive)
void G_free_key_value(struct Key_Value *)
Free allocated Key_Value structure.
void G_set_key_value(const char *, const char *, struct Key_Value *)
Set value for given key.
int G_lookup_key_value_from_file(const char *, const char *, char[], int)
Look up for key in file.
void G_free_tokens(char **)
Free memory allocated to tokens.
int G_asprintf(char **, const char *,...) __attribute__((format(printf
int G_number_of_tokens(char **)
Return number of tokens.
int int G_strcasecmp(const char *, const char *)
String compare ignoring case (upper or lower)
const char * G_gisbase(void)
Get full path name of the top level module directory.
struct Key_Value * G_create_key_value(void)
Allocate and initialize Key_Value structure.
int G_debug(int, const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
char ** G_tokenize(const char *, const char *)
Tokenize string.
struct gpj_datum_transform_list * GPJ_get_datum_transform_by_name(const char *)
Internal function to find all possible sets of transformation parameters for a particular datum.
void GPJ_free_datum(struct gpj_datum *)
Free the memory used for the strings in a gpj_datum struct.
int GPJ_get_ellipsoid_by_name(const char *, struct gpj_ellps *)
Looks up ellipsoid in ellipsoid table and returns the a, e2 parameters for the ellipsoid.
int GPJ_get_datum_by_name(const char *, struct gpj_datum *)
Look up a string in datum.table file to see if it is a valid datum name and if so place its informati...
void GPJ_free_ellps(struct gpj_ellps *)
Free ellipsoid data structure.
int GPJ_get_default_datum_params_by_name(const char *, char **)
"Last resort" function to retrieve a "default" set of datum parameters for a datum (N....
int GPJ__get_datum_params(const struct Key_Value *, char **, char **)
Extract the datum transformation-related parameters from a set of general PROJ_INFO parameters.
int pj_get_kv(struct pj_info *, const struct Key_Value *, const struct Key_Value *)
Create a pj_info struct Co-ordinate System definition from a set of PROJ_INFO / PROJ_UNITS-style key-...
int GPJ__get_ellipsoid_params(const struct Key_Value *, double *, double *, double *)
Get the ellipsoid parameters from proj keys structure.
void GPJ_free_datum_transform(struct gpj_datum_transform_list *)
Free the memory used by a gpj_datum_transform_list struct.
struct ellps_list * read_ellipsoid_table(int fatal)
void free_ellps_list(struct ellps_list *elist)
#define PROJECTION_OTHER
Projection code - other projection (other then noted above)
#define PROJECTION_XY
Projection code - XY coordinate system (unreferenced data)
#define PROJECTION_UTM
Projection code - UTM.
#define PROJECTION_LL
Projection code - Latitude-Longitude.
void free_datum_list(struct datum_list *dstruct)
Free the memory used by a datum_list linked list structure.
struct datum_list * read_datum_table(void)
Read the current GRASS datum.table from disk and store in memory.
2D/3D raster map header (used also for region)
int zone
Projection zone (UTM)