EVOLUTION-MANAGER
Edit File: geotiff_proj4.c
/****************************************************************************** * $Id: geotiff_proj4.c 2741 2016-09-04 18:50:49Z rouault $ * * Project: libgeotiff * Purpose: Code to convert a normalized GeoTIFF definition into a PROJ.4 * (OGDI) compatible projection string. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 1999, Frank Warmerdam * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. ****************************************************************************** */ #include "cpl_serv.h" #include "geotiff.h" #include "geo_normalize.h" #include "geovalues.h" #include "geo_tiffp.h" /************************************************************************/ /* OSRProj4Tokenize() */ /* */ /* Custom tokenizing function for PROJ.4 strings. The main */ /* reason we can't just use CSLTokenizeString is to handle */ /* strings with a + sign in the exponents of parameter values. */ /************************************************************************/ static char **OSRProj4Tokenize( const char *pszFull ) { char *pszStart = NULL; char *pszFullWrk; char **papszTokens; int i; int nTokens = 0; static const int nMaxTokens = 200; if( pszFull == NULL ) return NULL; papszTokens = (char **) calloc(sizeof(char*),nMaxTokens); pszFullWrk = CPLStrdup(pszFull); for( i=0; pszFullWrk[i] != '\0' && nTokens != nMaxTokens-1; i++ ) { switch( pszFullWrk[i] ) { case '+': if( i == 0 || pszFullWrk[i-1] == '\0' ) { if( pszStart != NULL ) { if( strstr(pszStart,"=") != NULL ) { papszTokens[nTokens++] = CPLStrdup(pszStart); } else { char szAsBoolean[100]; strncpy( szAsBoolean,pszStart, sizeof(szAsBoolean)-1-4); szAsBoolean[sizeof(szAsBoolean)-1-4] = '\0'; strcat( szAsBoolean,"=yes" ); papszTokens[nTokens++] = CPLStrdup(szAsBoolean); } } pszStart = pszFullWrk + i + 1; } break; case ' ': case '\t': case '\n': pszFullWrk[i] = '\0'; break; default: break; } } if( pszStart != NULL && strlen(pszStart) > 0 ) { if (nTokens != 199) papszTokens[nTokens++] = CPLStrdup(pszStart); } CPLFree( pszFullWrk ); return papszTokens; } /************************************************************************/ /* OSR_GSV() */ /************************************************************************/ static const char *OSR_GSV( char **papszNV, const char * pszField ) { size_t field_len = strlen(pszField); int i; if( !papszNV ) return NULL; for( i = 0; papszNV[i] != NULL; i++ ) { if( EQUALN(papszNV[i],pszField,field_len) ) { if( papszNV[i][field_len] == '=' ) return papszNV[i] + field_len + 1; if( strlen(papszNV[i]) == field_len ) return ""; } } return NULL; } /************************************************************************/ /* OSR_GDV() */ /* */ /* Fetch a particular parameter out of the parameter list, or */ /* the indicated default if it isn't available. This is a */ /* helper function for importFromProj4(). */ /************************************************************************/ static double OSR_GDV( char **papszNV, const char * pszField, double dfDefaultValue ) { const char *pszValue = OSR_GSV( papszNV, pszField ); /* special hack to use k_0 if available. */ if( pszValue == NULL && EQUAL(pszField,"k") ) return OSR_GDV( papszNV, "k_0", dfDefaultValue ); if( pszValue == NULL ) return dfDefaultValue; else return GTIFAtof(pszValue); } /************************************************************************/ /* OSRFreeStringList() */ /************************************************************************/ static void OSRFreeStringList( char ** list ) { int i; for( i = 0; list != NULL && list[i] != NULL; i++ ) free( list[i] ); free(list); } /************************************************************************/ /* GTIFSetFromProj4() */ /************************************************************************/ int GTIFSetFromProj4( GTIF *gtif, const char *proj4 ) { char **papszNV = OSRProj4Tokenize( proj4 ); short nSpheroid = KvUserDefined; double dfSemiMajor=0.0, dfSemiMinor=0.0, dfInvFlattening=0.0; int nDatum = KvUserDefined; int nGCS = KvUserDefined; const char *value; /* -------------------------------------------------------------------- */ /* Get the ellipsoid definition. */ /* -------------------------------------------------------------------- */ value = OSR_GSV( papszNV, "ellps" ); if( value == NULL ) { /* nothing */; } else if( EQUAL(value,"WGS84") ) nSpheroid = Ellipse_WGS_84; else if( EQUAL(value,"clrk66") ) nSpheroid = Ellipse_Clarke_1866; else if( EQUAL(value,"clrk80") ) nSpheroid = Ellipse_Clarke_1880; else if( EQUAL(value,"GRS80") ) nSpheroid = Ellipse_GRS_1980; if( nSpheroid == KvUserDefined ) { dfSemiMajor = OSR_GDV(papszNV,"a",0.0); dfSemiMinor = OSR_GDV(papszNV,"b",0.0); dfInvFlattening = OSR_GDV(papszNV,"rf",0.0); if( dfSemiMinor != 0.0 && dfInvFlattening == 0.0 ) dfInvFlattening = -1.0 / (dfSemiMinor/dfSemiMajor - 1.0); } /* -------------------------------------------------------------------- */ /* Get the GCS/Datum code. */ /* -------------------------------------------------------------------- */ value = OSR_GSV( papszNV, "datum" ); if( value == NULL ) { } else if( EQUAL(value,"WGS84") ) { nGCS = GCS_WGS_84; nDatum = Datum_WGS84; } else if( EQUAL(value,"NAD83") ) { nGCS = GCS_NAD83; nDatum = Datum_North_American_Datum_1983; } else if( EQUAL(value,"NAD27") ) { nGCS = GCS_NAD27; nDatum = Datum_North_American_Datum_1927; } /* -------------------------------------------------------------------- */ /* Operate on the basis of the projection name. */ /* -------------------------------------------------------------------- */ value = OSR_GSV(papszNV,"proj"); if( value == NULL ) { OSRFreeStringList( papszNV ); return FALSE; } else if( EQUAL(value,"longlat") || EQUAL(value,"latlong") ) { } else if( EQUAL(value,"tmerc") ) { GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_TransverseMercator ); GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lat_0", 0.0 ) ); GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lon_0", 0.0 ) ); GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "k", 1.0 ) ); GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "x_0", 0.0 ) ); GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"utm") ) { int nZone = (int) OSR_GDV(papszNV,"zone",0); const char *south = OSR_GSV(papszNV,"south"); GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_TransverseMercator ); GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, 0.0 ); GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, nZone * 6 - 183.0 ); GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, 0.9996 ); GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, 500000.0 ); if( south != NULL ) GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, 10000000.0 ); else GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, 0.0 ); } else if( EQUAL(value,"lcc") && OSR_GDV(papszNV, "lat_0", 0.0 ) == OSR_GDV(papszNV, "lat_1", 0.0 ) ) { GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_LambertConfConic_1SP ); GTIFKeySet(gtif, ProjNatOriginLatGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lat_0", 0.0 ) ); GTIFKeySet(gtif, ProjNatOriginLongGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lon_0", 0.0 ) ); GTIFKeySet(gtif, ProjScaleAtNatOriginGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "k", 1.0 ) ); GTIFKeySet(gtif, ProjFalseEastingGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "x_0", 0.0 ) ); GTIFKeySet(gtif, ProjFalseNorthingGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"lcc") ) { GTIFKeySet(gtif, GTModelTypeGeoKey, TYPE_SHORT, 1, ModelTypeProjected); GTIFKeySet(gtif, ProjectedCSTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjectionGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet(gtif, ProjCoordTransGeoKey, TYPE_SHORT, 1, CT_LambertConfConic_2SP ); GTIFKeySet(gtif, ProjFalseOriginLatGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lat_0", 0.0 ) ); GTIFKeySet(gtif, ProjFalseOriginLongGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lon_0", 0.0 ) ); GTIFKeySet(gtif, ProjStdParallel1GeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lat_1", 0.0 ) ); GTIFKeySet(gtif, ProjStdParallel2GeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "lat_2", 0.0 ) ); GTIFKeySet(gtif, ProjFalseOriginEastingGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "x_0", 0.0 ) ); GTIFKeySet(gtif, ProjFalseOriginNorthingGeoKey, TYPE_DOUBLE, 1, OSR_GDV( papszNV, "y_0", 0.0 ) ); } #ifdef notdef else if( EQUAL(value,"bonne") ) { SetBonne( OSR_GDV( papszNV, "lat_1", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"cass") ) { SetCS( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"nzmg") ) { SetNZMG( OSR_GDV( papszNV, "lat_0", -41.0 ), OSR_GDV( papszNV, "lon_0", 173.0 ), OSR_GDV( papszNV, "x_0", 2510000.0 ), OSR_GDV( papszNV, "y_0", 6023150.0 ) ); } else if( EQUAL(value,"cea") ) { SetCEA( OSR_GDV( papszNV, "lat_ts", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"merc") /* 2SP form */ && OSR_GDV(papszNV, "lat_ts", 1000.0) < 999.0 ) { SetMercator2SP( OSR_GDV( papszNV, "lat_ts", 0.0 ), 0.0, OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"merc") ) /* 1SP form */ { SetMercator( 0.0, OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "k", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"stere") && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) - 90) < 0.001 ) { SetPS( OSR_GDV( papszNV, "lat_ts", 90.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "k", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"stere") && ABS(OSR_GDV( papszNV, "lat_0", 0.0 ) + 90) < 0.001 ) { SetPS( OSR_GDV( papszNV, "lat_ts", -90.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "k", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUALN(value,"stere",5) /* mostly sterea */ && CSLFetchNameValue(papszNV,"k") != NULL ) { SetOS( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "k", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"stere") ) { SetStereographic( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), 1.0, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"eqc") ) { if( OSR_GDV( papszNV, "lat_0", 0.0 ) != OSR_GDV( papszNV, "lat_ts", 0.0 ) ) SetEquirectangular2( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 )+dfFromGreenwich, OSR_GDV( papszNV, "lat_ts", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); else SetEquirectangular( OSR_GDV( papszNV, "lat_ts", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 )+dfFromGreenwich, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"glabsgm") ) { SetGaussLabordeReunion( OSR_GDV( papszNV, "lat_0", -21.116666667 ), OSR_GDV( papszNV, "lon_0", 55.53333333309)+dfFromGreenwich, OSR_GDV( papszNV, "k_0", 1.0 ), OSR_GDV( papszNV, "x_0", 160000.000 ), OSR_GDV( papszNV, "y_0", 50000.000 ) ); } else if( EQUAL(value,"gnom") ) { SetGnomonic( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"ortho") ) { SetOrthographic( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"laea") ) { SetLAEA( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"aeqd") ) { SetAE( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"eqdc") ) { SetEC( OSR_GDV( papszNV, "lat_1", 0.0 ), OSR_GDV( papszNV, "lat_2", 0.0 ), OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"mill") ) { SetMC( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"moll") ) { SetMollweide( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"eck4") ) { SetEckertIV( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"eck6") ) { SetEckertVI( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"poly") ) { SetPolyconic( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"aea") ) { SetACEA( OSR_GDV( papszNV, "lat_1", 0.0 ), OSR_GDV( papszNV, "lat_2", 0.0 ), OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"robin") ) { SetRobinson( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"vandg") ) { SetVDG( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"sinu") ) { SetSinusoidal( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"gall") ) { SetGS( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"goode") ) { SetGH( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"geos") ) { SetGEOS( OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "h", 35785831.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"lcc") ) { if( OSR_GDV(papszNV, "lat_0", 0.0 ) == OSR_GDV(papszNV, "lat_1", 0.0 ) ) { /* 1SP form */ SetLCC1SP( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "k_0", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else { /* 2SP form */ SetLCC( OSR_GDV( papszNV, "lat_1", 0.0 ), OSR_GDV( papszNV, "lat_2", 0.0 ), OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } } else if( EQUAL(value,"omerc") ) { SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lonc", 0.0 ), OSR_GDV( papszNV, "alpha", 0.0 ), 0.0, /* ??? */ OSR_GDV( papszNV, "k", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"somerc") ) { SetHOM( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), 90.0, 90.0, OSR_GDV( papszNV, "k", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"krovak") ) { SetKrovak( OSR_GDV( papszNV, "lat_0", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "alpha", 0.0 ), 0.0, /* pseudo_standard_parallel_1 */ OSR_GDV( papszNV, "k", 1.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "iwm_p") ) { SetIWMPolyconic( OSR_GDV( papszNV, "lat_1", 0.0 ), OSR_GDV( papszNV, "lat_2", 0.0 ), OSR_GDV( papszNV, "lon_0", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "wag1") ) { SetWagner( 1, 0.0, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "wag2") ) { SetWagner( 2, 0.0, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "wag3") ) { SetWagner( 3, OSR_GDV( papszNV, "lat_ts", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "wag1") ) { SetWagner( 4, 0.0, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "wag1") ) { SetWagner( 5, 0.0, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "wag1") ) { SetWagner( 6, 0.0, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value, "wag1") ) { SetWagner( 7, 0.0, OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } else if( EQUAL(value,"tpeqd") ) { SetTPED( OSR_GDV( papszNV, "lat_1", 0.0 ), OSR_GDV( papszNV, "lon_1", 0.0 ), OSR_GDV( papszNV, "lat_2", 0.0 ), OSR_GDV( papszNV, "lon_2", 0.0 ), OSR_GDV( papszNV, "x_0", 0.0 ), OSR_GDV( papszNV, "y_0", 0.0 ) ); } #endif else { /* unsupported coordinate system */ OSRFreeStringList( papszNV ); return FALSE; } /* -------------------------------------------------------------------- */ /* Write the GCS if we have it, otherwise write the datum. */ /* -------------------------------------------------------------------- */ if( nGCS != KvUserDefined ) { GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, nGCS ); } else { GTIFKeySet( gtif, GeographicTypeGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( gtif, GeogGeodeticDatumGeoKey, TYPE_SHORT, 1, nDatum ); } /* -------------------------------------------------------------------- */ /* Write the ellipsoid if we don't know the GCS. */ /* -------------------------------------------------------------------- */ if( nGCS == KvUserDefined ) { if( nSpheroid != KvUserDefined ) GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, nSpheroid ); else { GTIFKeySet( gtif, GeogEllipsoidGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( gtif, GeogSemiMajorAxisGeoKey, TYPE_DOUBLE, 1, dfSemiMajor ); if( dfInvFlattening == 0.0 ) GTIFKeySet( gtif, GeogSemiMinorAxisGeoKey, TYPE_DOUBLE, 1, dfSemiMajor ); else GTIFKeySet( gtif, GeogInvFlatteningGeoKey, TYPE_DOUBLE, 1, dfInvFlattening ); } } /* -------------------------------------------------------------------- */ /* Linear units translation */ /* -------------------------------------------------------------------- */ value = OSR_GSV( papszNV, "units" ); if( value == NULL ) { value = OSR_GSV( papszNV, "to_meter" ); if( value ) { GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, KvUserDefined ); GTIFKeySet( gtif, ProjLinearUnitSizeGeoKey, TYPE_DOUBLE, 1, GTIFAtof(value) ); } } else if( EQUAL(value,"meter") || EQUAL(value,"m") ) { GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Meter ); } else if( EQUAL(value,"us-ft") ) { GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Foot_US_Survey ); } else if( EQUAL(value,"ft") ) { GTIFKeySet( gtif, ProjLinearUnitsGeoKey, TYPE_SHORT, 1, Linear_Foot ); } OSRFreeStringList( papszNV ); return TRUE; } /************************************************************************/ /* GTIFGetProj4Defn() */ /************************************************************************/ char * GTIFGetProj4Defn( GTIFDefn * psDefn ) { char szProjection[512]; char szUnits[64]; double dfFalseEasting, dfFalseNorthing; if( psDefn == NULL || !psDefn->DefnSet ) return CPLStrdup(""); szProjection[0] = '\0'; /* ==================================================================== */ /* Translate the units of measure. */ /* */ /* Note that even with a +units, or +to_meter in effect, it is */ /* still assumed that all the projection parameters are in */ /* meters. */ /* ==================================================================== */ if( psDefn->UOMLength == Linear_Meter ) { strcpy( szUnits, "+units=m " ); } else if( psDefn->UOMLength == Linear_Foot ) { strcpy( szUnits, "+units=ft " ); } else if( psDefn->UOMLength == Linear_Foot_US_Survey ) { strcpy( szUnits, "+units=us-ft " ); } else if( psDefn->UOMLength == Linear_Foot_Indian ) { strcpy( szUnits, "+units=ind-ft " ); } else if( psDefn->UOMLength == Linear_Link ) { strcpy( szUnits, "+units=link " ); } else if( psDefn->UOMLength == Linear_Yard_Indian) { strcpy( szUnits, "+units=ind-yd " ); } else if( psDefn->UOMLength == Linear_Fathom ) { strcpy( szUnits, "+units=fath " ); } else if( psDefn->UOMLength == Linear_Mile_International_Nautical ) { strcpy( szUnits, "+units=kmi " ); } else { sprintf( szUnits, "+to_meter=%.10f", psDefn->UOMLengthInMeters ); } /* -------------------------------------------------------------------- */ /* false easting and northing are in meters and that is what */ /* PROJ.4 wants regardless of the linear units. */ /* -------------------------------------------------------------------- */ dfFalseEasting = psDefn->ProjParm[5]; dfFalseNorthing = psDefn->ProjParm[6]; /* ==================================================================== */ /* Handle general projection methods. */ /* ==================================================================== */ /* -------------------------------------------------------------------- */ /* Geographic. */ /* -------------------------------------------------------------------- */ if(psDefn->Model==ModelTypeGeographic) { sprintf(szProjection+strlen(szProjection),"+proj=latlong "); } /* -------------------------------------------------------------------- */ /* UTM - special case override on transverse mercator so things */ /* will be more meaningful to the user. */ /* -------------------------------------------------------------------- */ else if( psDefn->MapSys == MapSys_UTM_North ) { sprintf( szProjection+strlen(szProjection), "+proj=utm +zone=%d ", psDefn->Zone ); } /* -------------------------------------------------------------------- */ /* Transverse Mercator */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_TransverseMercator ) { sprintf( szProjection+strlen(szProjection), "+proj=tmerc +lat_0=%.9f +lon_0=%.9f +k=%f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[4], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Mercator */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Mercator ) { if( psDefn->ProjParm[2] != 0.0 ) /* Mercator 2SP: FIXME we need a better way of detecting it */ sprintf( szProjection+strlen(szProjection), "+proj=merc +lat_ts=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[2], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); else sprintf( szProjection+strlen(szProjection), "+proj=merc +lat_ts=%.9f +lon_0=%.9f +k=%f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[4], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Cassini/Soldner */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_CassiniSoldner ) { sprintf( szProjection+strlen(szProjection), "+proj=cass +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Oblique Stereographic - Should this really map onto */ /* Stereographic? */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_ObliqueStereographic ) { sprintf( szProjection+strlen(szProjection), "+proj=stere +lat_0=%.9f +lon_0=%.9f +k=%f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[4], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Stereographic */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Stereographic ) { sprintf( szProjection+strlen(szProjection), "+proj=stere +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Polar Stereographic */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_PolarStereographic ) { if( psDefn->ProjParm[0] > 0.0 ) sprintf( szProjection+strlen(szProjection), "+proj=stere +lat_0=90 +lat_ts=%.9f +lon_0=%.9f " "+k=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[4], dfFalseEasting, dfFalseNorthing ); else sprintf( szProjection+strlen(szProjection), "+proj=stere +lat_0=-90 +lat_ts=%.9f +lon_0=%.9f " "+k=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[4], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Equirectangular */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Equirectangular ) { sprintf( szProjection+strlen(szProjection), "+proj=eqc +lat_0=%.9f +lon_0=%.9f +lat_ts=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[2], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Gnomonic */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Gnomonic ) { sprintf( szProjection+strlen(szProjection), "+proj=gnom +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Orthographic */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Orthographic ) { sprintf( szProjection+strlen(szProjection), "+proj=ortho +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Lambert Azimuthal Equal Area */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_LambertAzimEqualArea ) { sprintf( szProjection+strlen(szProjection), "+proj=laea +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Azimuthal Equidistant */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_AzimuthalEquidistant ) { sprintf( szProjection+strlen(szProjection), "+proj=aeqd +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Miller Cylindrical */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_MillerCylindrical ) { sprintf( szProjection+strlen(szProjection), "+proj=mill +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f +R_A ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Polyconic */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Polyconic ) { sprintf( szProjection+strlen(szProjection), "+proj=poly +lat_0=%.9f +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* AlbersEqualArea */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_AlbersEqualArea ) { sprintf( szProjection+strlen(szProjection), "+proj=aea +lat_1=%.9f +lat_2=%.9f +lat_0=%.9f +lon_0=%.9f" " +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[2], psDefn->ProjParm[3], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* EquidistantConic */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_EquidistantConic ) { sprintf( szProjection+strlen(szProjection), "+proj=eqdc +lat_1=%.9f +lat_2=%.9f +lat_0=%.9f +lon_0=%.9f" " +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[2], psDefn->ProjParm[3], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Robinson */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Robinson ) { sprintf( szProjection+strlen(szProjection), "+proj=robin +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* VanDerGrinten */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_VanDerGrinten ) { sprintf( szProjection+strlen(szProjection), "+proj=vandg +lon_0=%.9f +x_0=%.3f +y_0=%.3f +R_A ", psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* Sinusoidal */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_Sinusoidal ) { sprintf( szProjection+strlen(szProjection), "+proj=sinu +lon_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[1], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* LambertConfConic_2SP */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_LambertConfConic_2SP ) { sprintf( szProjection+strlen(szProjection), "+proj=lcc +lat_0=%.9f +lon_0=%.9f +lat_1=%.9f +lat_2=%.9f " " +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[2], psDefn->ProjParm[3], dfFalseEasting, dfFalseNorthing ); } /* -------------------------------------------------------------------- */ /* LambertConfConic_1SP */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_LambertConfConic_1SP ) { sprintf( szProjection+strlen(szProjection), "+proj=lcc +lat_0=%.9f +lat_1=%.9f +lon_0=%.9f" " +k_0=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[4], psDefn->ProjParm[5], psDefn->ProjParm[6] ); } /* -------------------------------------------------------------------- */ /* CT_CylindricalEqualArea */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_CylindricalEqualArea ) { sprintf( szProjection+strlen(szProjection), "+proj=cea +lat_ts=%.9f +lon_0=%.9f " " +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[5], psDefn->ProjParm[6] ); } /* -------------------------------------------------------------------- */ /* NewZealandMapGrid */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_NewZealandMapGrid ) { sprintf( szProjection+strlen(szProjection), "+proj=nzmg +lat_0=%.9f +lon_0=%.9f" " +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[5], psDefn->ProjParm[6] ); } /* -------------------------------------------------------------------- */ /* Transverse Mercator - south oriented. */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_TransvMercator_SouthOriented ) { /* this appears to be an unsupported formulation with PROJ.4 */ } /* -------------------------------------------------------------------- */ /* ObliqueMercator (Hotine) */ /* -------------------------------------------------------------------- */ else if( psDefn->CTProjection == CT_ObliqueMercator ) { /* not clear how ProjParm[3] - angle from rectified to skewed grid - should be applied ... see the +not_rot flag for PROJ.4. Just ignoring for now. */ sprintf( szProjection+strlen(szProjection), "+proj=omerc +lat_0=%.9f +lonc=%.9f +alpha=%.9f" " +k=%.9f +x_0=%.3f +y_0=%.3f ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[2], psDefn->ProjParm[4], psDefn->ProjParm[5], psDefn->ProjParm[6] ); } else if( psDefn->CTProjection == CT_HotineObliqueMercatorAzimuthCenter ) { /* special case for swiss oblique mercator : see GDAL bug 423 */ if( fabs(psDefn->ProjParm[2] - 90.0) < 0.0001 && fabs(psDefn->ProjParm[3]-90.0) < 0.0001 ) { sprintf( szProjection+strlen(szProjection), "+proj=somerc +lat_0=%.16g +lon_0=%.16g" " +k_0=%.16g +x_0=%.16g +y_0=%.16g ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[4], psDefn->ProjParm[5], psDefn->ProjParm[6] ); } else { sprintf( szProjection+strlen(szProjection), "+proj=omerc +lat_0=%.16g +lonc=%.16g +alpha=%.16g" " +k=%.16g +x_0=%.16g +y_0=%.16g ", psDefn->ProjParm[0], psDefn->ProjParm[1], psDefn->ProjParm[2], psDefn->ProjParm[4], psDefn->ProjParm[5], psDefn->ProjParm[6] ); /* RSO variant - http://trac.osgeo.org/proj/ticket/62 */ /* Note that gamma is only supported by PROJ 4.8.0 and later. */ /* FIXME: how to detect that gamma isn't set to default value */ /*if( psDefn->ProjParm[3] != 0.0 ) { sprintf( szProjection+strlen(szProjection), "+gamma=%.16g ", psDefn->ProjParm[3] ); }*/ } } /* ==================================================================== */ /* Handle ellipsoid information. */ /* ==================================================================== */ if( psDefn->Ellipsoid == Ellipse_WGS_84 ) strcat( szProjection, "+ellps=WGS84 " ); else if( psDefn->Ellipsoid == Ellipse_Clarke_1866 ) strcat( szProjection, "+ellps=clrk66 " ); else if( psDefn->Ellipsoid == Ellipse_Clarke_1880 ) strcat( szProjection, "+ellps=clrk80 " ); else if( psDefn->Ellipsoid == Ellipse_GRS_1980 ) strcat( szProjection, "+ellps=GRS80 " ); else { if( psDefn->SemiMajor != 0.0 && psDefn->SemiMinor != 0.0 ) { sprintf( szProjection+strlen(szProjection), "+a=%.3f +b=%.3f ", psDefn->SemiMajor, psDefn->SemiMinor ); } } strcat( szProjection, szUnits ); /* If we don't have anything, reset */ if (strstr(szProjection, "+proj=") == NULL) { return CPLStrdup(""); } return CPLStrdup( szProjection ); } #if !defined(HAVE_LIBPROJ) int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints, double *padfX, double *padfY ) { (void) psDefn; (void) nPoints; (void) padfX; (void) padfY; #ifdef DEBUG fprintf( stderr, "GTIFProj4ToLatLong() - PROJ.4 support not compiled in.\n" ); #endif return FALSE; } int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints, double *padfX, double *padfY ) { (void) psDefn; (void) nPoints; (void) padfX; (void) padfY; #ifdef DEBUG fprintf( stderr, "GTIFProj4FromLatLong() - PROJ.4 support not compiled in.\n" ); #endif return FALSE; } #else #include "proj_api.h" /************************************************************************/ /* GTIFProj4FromLatLong() */ /* */ /* Convert lat/long values to projected coordinate for a */ /* particular definition. */ /************************************************************************/ int GTIFProj4FromLatLong( GTIFDefn * psDefn, int nPoints, double *padfX, double *padfY ) { char *pszProjection, **papszArgs; projPJ *psPJ; int i; /* -------------------------------------------------------------------- */ /* Get a projection definition. */ /* -------------------------------------------------------------------- */ pszProjection = GTIFGetProj4Defn( psDefn ); if( pszProjection == NULL ) return FALSE; /* -------------------------------------------------------------------- */ /* Parse into tokens for pj_init(), and initialize the projection. */ /* -------------------------------------------------------------------- */ papszArgs = CSLTokenizeStringComplex( pszProjection, " +", TRUE, FALSE ); free( pszProjection ); psPJ = pj_init( CSLCount(papszArgs), papszArgs ); CSLDestroy( papszArgs ); if( psPJ == NULL ) { return FALSE; } /* -------------------------------------------------------------------- */ /* Process each of the points. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nPoints; i++ ) { projUV sUV; sUV.u = padfX[i] * DEG_TO_RAD; sUV.v = padfY[i] * DEG_TO_RAD; sUV = pj_fwd( sUV, psPJ ); padfX[i] = sUV.u; padfY[i] = sUV.v; } pj_free( psPJ ); return TRUE; } /************************************************************************/ /* GTIFProj4ToLatLong() */ /* */ /* Convert projection coordinates to lat/long for a particular */ /* definition. */ /************************************************************************/ int GTIFProj4ToLatLong( GTIFDefn * psDefn, int nPoints, double *padfX, double *padfY ) { char *pszProjection, **papszArgs; projPJ *psPJ; int i; /* -------------------------------------------------------------------- */ /* Get a projection definition. */ /* -------------------------------------------------------------------- */ pszProjection = GTIFGetProj4Defn( psDefn ); if( pszProjection == NULL ) return FALSE; /* -------------------------------------------------------------------- */ /* Parse into tokens for pj_init(), and initialize the projection. */ /* -------------------------------------------------------------------- */ papszArgs = CSLTokenizeStringComplex( pszProjection, " +", TRUE, FALSE ); free( pszProjection ); psPJ = pj_init( CSLCount(papszArgs), papszArgs ); CSLDestroy( papszArgs ); if( psPJ == NULL ) { return FALSE; } /* -------------------------------------------------------------------- */ /* Process each of the points. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nPoints; i++ ) { projUV sUV; sUV.u = padfX[i]; sUV.v = padfY[i]; sUV = pj_inv( sUV, psPJ ); padfX[i] = sUV.u * RAD_TO_DEG; padfY[i] = sUV.v * RAD_TO_DEG; } pj_free( psPJ ); return TRUE; } #endif /* has proj_api.h and -lproj */