15 changes: 15 additions & 0 deletions python/core/qgscoordinatereferencesystem.sip
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ class QgsCoordinateReferenceSystem
*/
bool createFromString( const QString theDefinition );

/*! Set up this srs from a various text formats.
*
* Valid formats: WKT string, "EPSG:n", "EPSGA:n", "AUTO:proj_id,unit_id,lon0,lat0",
* "urn:ogc:def:crs:EPSG::n", PROJ.4 string, filename (with WKT, XML or PROJ.4 string),
* well known name (such as NAD27, NAD83, WGS84 or WGS72),
* ESRI::[WKT string] (directly or in a file), "IGNF:xxx"
*
* For more details on supported formats see OGRSpatialReference::SetFromUserInput()
* ( http://www.gdal.org/ogr/classOGRSpatialReference.html#aec3c6a49533fe457ddc763d699ff8796 )
* @note this function generates a WKT string using OSRSetFromUserInput() and
* passes it to createFromWkt() function.
* @param theDefinition A String containing a coordinate reference system definition.
*/
bool createFromUserInput( const QString theDefinition );

/*! Set up this srs by fetching the appropriate information from the
* sqlite backend. First the system level read only srs.db will be checked
* and then the users ~/.qgis/qgis.db database will be checked for a match.
Expand Down
78 changes: 64 additions & 14 deletions src/core/qgscoordinatereferencesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,54 @@ bool QgsCoordinateReferenceSystem::createFromString( const QString theDefinition
return result;
}

bool QgsCoordinateReferenceSystem::createFromUserInput( const QString theDefinition )
{
QString theWkt;
char *wkt = NULL;
OGRSpatialReferenceH crs = OSRNewSpatialReference( NULL );

// make sure towgs84 parameter is loaded if using an ESRI definition and gdal >= 1.9
#if GDAL_VERSION_NUM >= 1900
if ( theDefinition.startsWith( "ESRI::" ) )
{
setupESRIWktFix();
}
#endif

if ( OSRSetFromUserInput( crs, theDefinition.toLocal8Bit().constData() ) == OGRERR_NONE )
{
if ( OSRExportToWkt( crs, &wkt ) == OGRERR_NONE )
{
theWkt = wkt;
OGRFree( wkt );
}
OSRDestroySpatialReference( crs );
}
//QgsDebugMsg( "theDefinition: " + theDefinition + " theWkt = " + theWkt );
return createFromWkt( theWkt );
}

void QgsCoordinateReferenceSystem::setupESRIWktFix( )
{
// make sure towgs84 parameter is loaded if gdal >= 1.9
// this requires setting GDAL_FIX_ESRI_WKT=GEOGCS (see qgis bug #5598 and gdal bug #4673)
#if GDAL_VERSION_NUM >= 1900
const char* configOld = CPLGetConfigOption( "GDAL_FIX_ESRI_WKT", "" );
const char* configNew = "GEOGCS";
// only set if it was not set, to let user change the value if needed
if ( strcmp( configOld, "" ) == 0 )
{
CPLSetConfigOption( "GDAL_FIX_ESRI_WKT", configNew );
if ( strcmp( configNew, CPLGetConfigOption( "GDAL_FIX_ESRI_WKT", "" ) ) != 0 )
QgsLogger::warning( QString( "GDAL_FIX_ESRI_WKT could not be set to %1 : %2"
).arg( configNew ).arg( CPLGetConfigOption( "GDAL_FIX_ESRI_WKT", "" ) ) ) ;
QgsDebugMsg( QString( "set GDAL_FIX_ESRI_WKT : %1" ).arg( configNew ) );
}
else
QgsDebugMsg( QString( "GDAL_FIX_ESRI_WKT was already set : %1" ).arg( configNew ) );
#endif
}

bool QgsCoordinateReferenceSystem::createFromOgcWmsCrs( QString theCrs )
{
QRegExp re( "(user|custom|qgis):(\\d+)", Qt::CaseInsensitive );
Expand Down Expand Up @@ -396,12 +444,13 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
// +proj=lcc +lat_1=46.8 +lat_0=46.8 +lon_0=2.337229166666664 +k_0=0.99987742
// +x_0=600000 +y_0=2200000 +a=6378249.2 +b=6356515.000000472 +units=m +no_defs
//
QgsDebugMsg( "proj4: " + theProj4String );
QString myProj4String = theProj4String.trimmed();
QgsDebugMsg( "proj4: " + myProj4String );
mIsValidFlag = false;
mWkt.clear();

QRegExp myProjRegExp( "\\+proj=(\\S+)" );
int myStart = myProjRegExp.indexIn( theProj4String );
int myStart = myProjRegExp.indexIn( myProj4String );
if ( myStart == -1 )
{
QgsDebugMsg( "proj string supplied has no +proj argument" );
Expand All @@ -411,7 +460,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
mProjectionAcronym = myProjRegExp.cap( 1 );

QRegExp myEllipseRegExp( "\\+ellps=(\\S+)" );
myStart = myEllipseRegExp.indexIn( theProj4String );
myStart = myEllipseRegExp.indexIn( myProj4String );
if ( myStart == -1 )
{
QgsDebugMsg( "proj string supplied has no +ellps argument" );
Expand All @@ -423,7 +472,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
}

QRegExp myAxisRegExp( "\\+a=(\\S+)" );
myStart = myAxisRegExp.indexIn( theProj4String );
myStart = myAxisRegExp.indexIn( myProj4String );
if ( myStart == -1 )
{
QgsDebugMsg( "proj string supplied has no +a argument" );
Expand All @@ -444,7 +493,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
* - if the above does not match perform a whole text search on proj4 string (if not null)
*/
// QgsDebugMsg( "wholetext match on name failed, trying proj4string match" );
myRecord = getRecord( "select * from tbl_srs where parameters=" + quotedValue( theProj4String.trimmed() ) + " order by deprecated" );
myRecord = getRecord( "select * from tbl_srs where parameters=" + quotedValue( myProj4String ) + " order by deprecated" );
if ( myRecord.empty() )
{
// Ticket #722 - aaronr
Expand All @@ -458,20 +507,20 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
int myLength2 = 0;
QString lat1Str = "";
QString lat2Str = "";
myStart1 = myLat1RegExp.indexIn( theProj4String, myStart1 );
myStart2 = myLat2RegExp.indexIn( theProj4String, myStart2 );
myStart1 = myLat1RegExp.indexIn( myProj4String, myStart1 );
myStart2 = myLat2RegExp.indexIn( myProj4String, myStart2 );
if ( myStart1 != -1 && myStart2 != -1 )
{
myLength1 = myLat1RegExp.matchedLength();
myLength2 = myLat2RegExp.matchedLength();
lat1Str = theProj4String.mid( myStart1 + LAT_PREFIX_LEN, myLength1 - LAT_PREFIX_LEN );
lat2Str = theProj4String.mid( myStart2 + LAT_PREFIX_LEN, myLength2 - LAT_PREFIX_LEN );
lat1Str = myProj4String.mid( myStart1 + LAT_PREFIX_LEN, myLength1 - LAT_PREFIX_LEN );
lat2Str = myProj4String.mid( myStart2 + LAT_PREFIX_LEN, myLength2 - LAT_PREFIX_LEN );
}
// If we found the lat_1 and lat_2 we need to swap and check to see if we can find it...
if ( lat1Str != "" && lat2Str != "" )
{
// Make our new string to check...
QString theProj4StringModified = theProj4String;
QString theProj4StringModified = myProj4String;
// First just swap in the lat_2 value for lat_1 value
theProj4StringModified.replace( myStart1 + LAT_PREFIX_LEN, myLength1 - LAT_PREFIX_LEN, lat2Str );
// Now we have to find the lat_2 location again since it has potentially moved...
Expand All @@ -497,7 +546,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
// split on spaces followed by a plus sign (+) to deal
// also with parameters containing spaces (e.g. +nadgrids)
// make sure result is trimmed (#5598)
foreach( QString param, theProj4String.split( QRegExp( "\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
foreach( QString param, myProj4String.split( QRegExp( "\\s+(?=\\+)" ), QString::SkipEmptyParts ) )
{
QString arg = QString( "' '||parameters||' ' LIKE %1" ).arg( quotedValue( QString( "% %1 %" ).arg( param.trimmed() ) ) );
if ( param.startsWith( "+datum=" ) )
Expand Down Expand Up @@ -536,7 +585,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
{
// Last ditch attempt to piece together what we know of the projection to find a match...
QgsDebugMsg( "globbing search for srsid from this proj string" );
setProj4String( theProj4String );
setProj4String( myProj4String );
mySrsId = findMatchingProj();
QgsDebugMsg( "globbing search for srsid returned srsid: " + QString::number( mySrsId ) );
if ( mySrsId > 0 )
Expand All @@ -553,7 +602,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
if ( !mIsValidFlag )
{
QgsDebugMsg( "Projection is not found in databases." );
setProj4String( theProj4String );
setProj4String( myProj4String );

// Is the SRS is valid now, we know it's a decent +proj string that can be entered into the srs.db
if ( mIsValidFlag )
Expand Down Expand Up @@ -815,7 +864,7 @@ void QgsCoordinateReferenceSystem::setProj4String( QString theProj4String )
OSRDestroySpatialReference( mCRS );
mCRS = OSRNewSpatialReference( NULL );
mIsValidFlag =
OSRImportFromProj4( mCRS, theProj4String.toLatin1().constData() )
OSRImportFromProj4( mCRS, theProj4String.trimmed().toLatin1().constData() )
== OGRERR_NONE;
mWkt.clear();
setMapUnits();
Expand Down Expand Up @@ -1516,6 +1565,7 @@ int QgsCoordinateReferenceSystem::syncDb()
if ( proj4.startsWith( input ) )
{
proj4 = proj4.mid( input.size() );
proj4 = proj4.trimmed();
}
}
else
Expand Down
26 changes: 26 additions & 0 deletions src/core/qgscoordinatereferencesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,32 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
*/
bool createFromString( const QString theDefinition );

/*! Set up this srs from a various text formats.
*
* Valid formats: WKT string, "EPSG:n", "EPSGA:n", "AUTO:proj_id,unit_id,lon0,lat0",
* "urn:ogc:def:crs:EPSG::n", PROJ.4 string, filename (with WKT, XML or PROJ.4 string),
* well known name (such as NAD27, NAD83, WGS84 or WGS72),
* ESRI::[WKT string] (directly or in a file), "IGNF:xxx"
*
* For more details on supported formats see OGRSpatialReference::SetFromUserInput()
* ( http://www.gdal.org/ogr/classOGRSpatialReference.html#aec3c6a49533fe457ddc763d699ff8796 )
* @note this function generates a WKT string using OSRSetFromUserInput() and
* passes it to createFromWkt() function.
* @param theDefinition A String containing a coordinate reference system definition.
*/
bool createFromUserInput( const QString theDefinition );

/*! Make sure that ESRI WKT import is done properly.
* This is required for proper shapefile CRS import when using gdal>= 1.9.
* @note This function is called by createFromUserInput() and QgsOgrProvider::crs(), there is usually
* no need to call it from elsewhere.
* @note This function sets CPL config option GDAL_FIX_ESRI_WKT to a proper value,
* unless it has been set by the user through the commandline or an environment variable.
* For more details refer to OGRSpatialReference::morphFromESRI() .
* @note added in 1.8
*/
static void setupESRIWktFix();

/*! Find out whether this CRS is correctly initialised and usable */
bool isValid() const;

Expand Down
3 changes: 2 additions & 1 deletion src/providers/ogr/qgsogrprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2157,7 +2157,8 @@ QgsCoordinateReferenceSystem QgsOgrProvider::crs()
}
}

CPLSetConfigOption( "GDAL_FIX_ESRI_WKT", "TOWGS84" ); // add towgs84 parameter
// add towgs84 parameter
QgsCoordinateReferenceSystem::setupESRIWktFix();

OGRSpatialReferenceH mySpatialRefSys = OGR_L_GetSpatialRef( ogrLayer );
if ( mySpatialRefSys )
Expand Down
Loading