void QgsSLDConfigParser::setCrsForLayer( const QDomElement& layerElem, QgsMapLayer* ml ) const { //create CRS if specified as attribute ("epsg" or "proj") QString epsg = layerElem.attribute( QStringLiteral( "epsg" ), QLatin1String( "" ) ); if ( !epsg.isEmpty() ) { bool conversionOk; int epsgnr = epsg.toInt( &conversionOk ); if ( conversionOk ) { //set spatial ref sys QgsCoordinateReferenceSystem srs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:%1" ).arg( epsgnr ) ); ml->setCrs( srs ); } } else { QString projString = layerElem.attribute( QStringLiteral( "proj" ), QLatin1String( "" ) ); if ( !projString.isEmpty() ) { QgsCoordinateReferenceSystem srs = QgsCoordinateReferenceSystem::fromProj4( projString ); //TODO: createFromProj4 used to save to the user database any new CRS // this behavior was changed in order to separate creation and saving. // Not sure if it necessary to save it here, should be checked by someone // familiar with the code (should also give a more descriptive name to the generated CRS) if ( srs.srsid() == 0 ) { QString myName = QStringLiteral( " * %1 (%2)" ) .arg( QObject::tr( "Generated CRS", "A CRS automatically generated from layer info get this prefix for description" ), srs.toProj4() ); srs.saveAsUserCrs( myName ); } ml->setCrs( srs ); } } }
bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem parameters, const QString &name, const QString &existingId, bool newEntry ) { QString id = existingId; QString sql; int returnId; QString projectionAcronym = parameters.projectionAcronym(); QString ellipsoidAcronym = parameters.ellipsoidAcronym(); QgsDebugMsg( QString( "Saving a CRS:%1, %2, %3" ).arg( name, parameters.toProj4() ).arg( newEntry ) ); if ( newEntry ) { returnId = parameters.saveAsUserCrs( name ); if ( returnId == -1 ) return false; else id = QString::number( returnId ); } else { sql = "update tbl_srs set description=" + quotedValue( name ) + ",projection_acronym=" + quotedValue( projectionAcronym ) + ",ellipsoid_acronym=" + quotedValue( ellipsoidAcronym ) + ",parameters=" + quotedValue( parameters.toProj4() ) + ",is_geo=0" // <--shamelessly hard coded for now + " where srs_id=" + quotedValue( id ) ; QgsDebugMsg( sql ); sqlite3_database_unique_ptr database; //check if the db is available int result = database.open( QgsApplication::qgisUserDatabaseFilePath() ); if ( result != SQLITE_OK ) { QgsDebugMsg( QString( "Can't open database: %1 \n please notify QGIS developers of this error \n %2 (file name) " ).arg( database.errorMessage(), QgsApplication::qgisUserDatabaseFilePath() ) ); // XXX This will likely never happen since on open, sqlite creates the // database if it does not exist. Q_ASSERT( result == SQLITE_OK ); } sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result ); if ( result != SQLITE_OK || preparedStatement.step() != SQLITE_DONE ) { QgsDebugMsg( QString( "failed to write to database in custom projection dialog: %1 [%2]" ).arg( sql, database.errorMessage() ) ); } preparedStatement.reset(); if ( result != SQLITE_OK ) return false; } mExistingCRSparameters[id] = parameters.toProj4(); mExistingCRSnames[id] = name; QgsCoordinateReferenceSystem::invalidateCache(); QgsCoordinateTransformCache::instance()->invalidateCrs( QStringLiteral( "USER:%1" ).arg( id ) ); // If we have a projection acronym not in the user db previously, add it. // This is a must, or else we can't select it from the vw_srs table. // Actually, add it always and let the SQL PRIMARY KEY remove duplicates. insertProjection( projectionAcronym ); return true; }
bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem myCRS, const QString& myName, QString myId, bool newEntry ) { QString mySql; int return_id; QString myProjectionAcronym = myCRS.projectionAcronym(); QString myEllipsoidAcronym = myCRS.ellipsoidAcronym(); QgsDebugMsg( QString( "Saving a CRS:%1, %2, %3" ).arg( myName, myCRS.toProj4() ).arg( newEntry ) ); if ( newEntry ) { return_id = myCRS.saveAsUserCrs( myName ); if ( return_id == -1 ) return false; else myId = QString::number( return_id ); } else { mySql = "update tbl_srs set description=" + quotedValue( myName ) + ",projection_acronym=" + quotedValue( myProjectionAcronym ) + ",ellipsoid_acronym=" + quotedValue( myEllipsoidAcronym ) + ",parameters=" + quotedValue( myCRS.toProj4() ) + ",is_geo=0" // <--shamelessly hard coded for now + " where srs_id=" + quotedValue( myId ) ; QgsDebugMsg( mySql ); sqlite3 *myDatabase; const char *myTail; sqlite3_stmt *myPreparedStatement; int myResult; //check if the db is available myResult = sqlite3_open( QgsApplication::qgisUserDbFilePath().toUtf8(), &myDatabase ); if ( myResult != SQLITE_OK ) { QgsDebugMsg( QString( "Can't open database: %1 \n please notify QGIS developers of this error \n %2 (file name) " ).arg( sqlite3_errmsg( myDatabase ), QgsApplication::qgisUserDbFilePath() ) ); // XXX This will likely never happen since on open, sqlite creates the // database if it does not exist. Q_ASSERT( myResult == SQLITE_OK ); } myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail ); // XXX Need to free memory from the error msg if one is set if ( myResult != SQLITE_OK || sqlite3_step( myPreparedStatement ) != SQLITE_DONE ) { QgsDebugMsg( QString( "failed to write to database in custom projection dialog: %1 [%2]" ).arg( mySql, sqlite3_errmsg( myDatabase ) ) ); } sqlite3_finalize( myPreparedStatement ); // close sqlite3 db sqlite3_close( myDatabase ); if ( myResult != SQLITE_OK ) return false; } existingCRSparameters[myId] = myCRS.toProj4(); existingCRSnames[myId] = myName; QgsCoordinateReferenceSystem::invalidateCache(); QgsCoordinateTransformCache::instance()->invalidateCrs( QString( "USER:%1" ).arg( myId ) ); // If we have a projection acronym not in the user db previously, add it. // This is a must, or else we can't select it from the vw_srs table. // Actually, add it always and let the SQL PRIMARY KEY remove duplicates. insertProjection( myProjectionAcronym ); return true; }
bool QgsDistanceArea::setEllipsoid( const QString& ellipsoid ) { QString radius, parameter2; // // SQLITE3 stuff - get parameters for selected ellipsoid // sqlite3 *myDatabase; const char *myTail; sqlite3_stmt *myPreparedStatement; int myResult; // Shortcut if ellipsoid is none. if ( ellipsoid == GEO_NONE ) { mEllipsoid = GEO_NONE; return true; } // Check if we have a custom projection, and set from text string. // Format is "PARAMETER:<semi-major axis>:<semi minor axis> // Numbers must be with (optional) decimal point and no other separators (C locale) // Distances in meters. Flattening is calculated. if ( ellipsoid.startsWith( QLatin1String( "PARAMETER" ) ) ) { QStringList paramList = ellipsoid.split( ':' ); bool semiMajorOk, semiMinorOk; double semiMajor = paramList[1].toDouble( & semiMajorOk ); double semiMinor = paramList[2].toDouble( & semiMinorOk ); if ( semiMajorOk && semiMinorOk ) { return setEllipsoid( semiMajor, semiMinor ); } else { return false; } } // Continue with PROJ.4 list of ellipsoids. //check the db is available myResult = sqlite3_open_v2( QgsApplication::srsDatabaseFilePath().toUtf8().data(), &myDatabase, SQLITE_OPEN_READONLY, nullptr ); if ( myResult ) { QgsMessageLog::logMessage( QObject::tr( "Can't open database: %1" ).arg( sqlite3_errmsg( myDatabase ) ) ); // XXX This will likely never happen since on open, sqlite creates the // database if it does not exist. return false; } // Set up the query to retrieve the projection information needed to populate the ELLIPSOID list QString mySql = "select radius, parameter2 from tbl_ellipsoid where acronym='" + ellipsoid + '\''; myResult = sqlite3_prepare( myDatabase, mySql.toUtf8(), mySql.toUtf8().length(), &myPreparedStatement, &myTail ); // XXX Need to free memory from the error msg if one is set if ( myResult == SQLITE_OK ) { if ( sqlite3_step( myPreparedStatement ) == SQLITE_ROW ) { radius = QString( reinterpret_cast< const char * >( sqlite3_column_text( myPreparedStatement, 0 ) ) ); parameter2 = QString( reinterpret_cast< const char * >( sqlite3_column_text( myPreparedStatement, 1 ) ) ); } } // close the sqlite3 statement sqlite3_finalize( myPreparedStatement ); sqlite3_close( myDatabase ); // row for this ellipsoid wasn't found? if ( radius.isEmpty() || parameter2.isEmpty() ) { QgsDebugMsg( QString( "setEllipsoid: no row in tbl_ellipsoid for acronym '%1'" ).arg( ellipsoid ) ); return false; } // get major semiaxis if ( radius.left( 2 ) == QLatin1String( "a=" ) ) mSemiMajor = radius.midRef( 2 ).toDouble(); else { QgsDebugMsg( QString( "setEllipsoid: wrong format of radius field: '%1'" ).arg( radius ) ); return false; } // get second parameter // one of values 'b' or 'f' is in field parameter2 // second one must be computed using formula: invf = a/(a-b) if ( parameter2.left( 2 ) == QLatin1String( "b=" ) ) { mSemiMinor = parameter2.midRef( 2 ).toDouble(); mInvFlattening = mSemiMajor / ( mSemiMajor - mSemiMinor ); } else if ( parameter2.left( 3 ) == QLatin1String( "rf=" ) ) { mInvFlattening = parameter2.midRef( 3 ).toDouble(); mSemiMinor = mSemiMajor - ( mSemiMajor / mInvFlattening ); } else { QgsDebugMsg( QString( "setEllipsoid: wrong format of parameter2 field: '%1'" ).arg( parameter2 ) ); return false; } QgsDebugMsg( QString( "setEllipsoid: a=%1, b=%2, 1/f=%3" ).arg( mSemiMajor ).arg( mSemiMinor ).arg( mInvFlattening ) ); // get spatial ref system for ellipsoid QString proj4 = "+proj=longlat +ellps=" + ellipsoid + " +no_defs"; QgsCoordinateReferenceSystem destCRS = QgsCoordinateReferenceSystem::fromProj4( proj4 ); //TODO: createFromProj4 used to save to the user database any new CRS // this behavior was changed in order to separate creation and saving. // Not sure if it necessary to save it here, should be checked by someone // familiar with the code (should also give a more descriptive name to the generated CRS) if ( destCRS.srsid() == 0 ) { QString myName = QStringLiteral( " * %1 (%2)" ) .arg( QObject::tr( "Generated CRS", "A CRS automatically generated from layer info get this prefix for description" ), destCRS.toProj4() ); destCRS.saveAsUserCrs( myName ); } // // set transformation from project CRS to ellipsoid coordinates mCoordTransform.setDestinationCrs( destCRS ); mEllipsoid = ellipsoid; // precalculate some values for area calculations computeAreaInit(); return true; }