23 #if PROJ_VERSION_MAJOR>=6 30 QList< QgsDatumTransform::TransformDetails > res;
31 #if PROJ_VERSION_MAJOR<6 33 Q_UNUSED( destination )
34 Q_UNUSED( includeSuperseded )
36 if ( !source.projObject() || !destination.projObject() )
41 PJ_OPERATION_FACTORY_CONTEXT *operationContext = proj_create_operation_factory_context( pjContext,
nullptr );
44 proj_operation_factory_context_set_grid_availability_use( pjContext, operationContext, PROJ_GRID_AVAILABILITY_IGNORED );
47 proj_operation_factory_context_set_spatial_criterion( pjContext, operationContext, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION );
49 #if PROJ_VERSION_MAJOR>6 || (PROJ_VERSION_MAJOR==6 && PROJ_VERSION_MINOR>=2) 50 if ( includeSuperseded )
51 proj_operation_factory_context_set_discard_superseded( pjContext, operationContext,
false );
53 Q_UNUSED( includeSuperseded )
55 if ( PJ_OBJ_LIST *ops = proj_create_operations( pjContext, source.projObject(), destination.projObject(), operationContext ) )
57 int count = proj_list_get_count( ops );
58 for (
int i = 0; i < count; ++i )
60 QgsProjUtils::proj_pj_unique_ptr op( proj_list_get( pjContext, ops, i ) );
64 res.push_back( transformDetailsFromPj( op.get() ) );
66 proj_list_destroy( ops );
68 proj_operation_factory_context_destroy( operationContext );
75 QList< QgsDatumTransform::TransformPair > transformations;
80 if ( srcGeoId.isEmpty() || destGeoId.isEmpty() )
82 return transformations;
85 QStringList srcSplit = srcGeoId.split(
':' );
86 QStringList destSplit = destGeoId.split(
':' );
88 if ( srcSplit.size() < 2 || destSplit.size() < 2 )
90 return transformations;
93 int srcAuthCode = srcSplit.at( 1 ).toInt();
94 int destAuthCode = destSplit.at( 1 ).toInt();
96 if ( srcAuthCode == destAuthCode )
98 return transformations;
101 QList<int> directTransforms;
102 searchDatumTransform( QStringLiteral(
"SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code=%1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( destAuthCode ),
104 QList<int> reverseDirectTransforms;
105 searchDatumTransform( QStringLiteral(
"SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code = %1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( srcAuthCode ),
106 reverseDirectTransforms );
107 QList<int> srcToWgs84;
108 searchDatumTransform( QStringLiteral(
"SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( 4326 ),
110 QList<int> destToWgs84;
111 searchDatumTransform( QStringLiteral(
"SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( 4326 ),
115 for (
int transform : qgis::as_const( directTransforms ) )
121 for (
int transform : qgis::as_const( reverseDirectTransforms ) )
126 for (
int srcTransform : qgis::as_const( srcToWgs84 ) )
128 for (
int destTransform : qgis::as_const( destToWgs84 ) )
134 return transformations;
137 void QgsDatumTransform::searchDatumTransform(
const QString &sql, QList< int > &transforms )
141 if ( openResult != SQLITE_OK )
148 statement = database.
prepare( sql, prepareRes );
149 if ( prepareRes != SQLITE_OK )
155 while ( statement.
step() == SQLITE_ROW )
158 transforms.push_back( cOpCode.toInt() );
164 QString transformString;
168 if ( openResult != SQLITE_OK )
170 return transformString;
174 QString sql = QStringLiteral(
"SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7 FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( datumTransform );
176 statement = database.
prepare( sql, prepareRes );
177 if ( prepareRes != SQLITE_OK )
179 return transformString;
182 if ( statement.
step() == SQLITE_ROW )
186 if ( methodCode == 9615 )
188 transformString =
"+nadgrids=" + statement.
columnAsText( 1 );
190 else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 )
192 transformString += QLatin1String(
"+towgs84=" );
200 if ( methodCode == 9603 )
202 transformString += QStringLiteral(
"%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) );
206 transformString += QStringLiteral(
"%1,%2,%3,%4,%5,%6,%7" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ), QString::number( p4 ), QString::number( p5 ), QString::number( p6 ), QString::number( p7 ) );
211 return transformString;
218 if ( openResult != SQLITE_OK )
224 QString sql = QStringLiteral(
"SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7,coord_op_code FROM tbl_datum_transform" );
226 statement = database.
prepare( sql, prepareRes );
227 if ( prepareRes != SQLITE_OK )
232 while ( statement.
step() == SQLITE_ROW )
234 QString transformString;
237 if ( methodCode == 9615 )
239 transformString =
"+nadgrids=" + statement.
columnAsText( 1 );
241 else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 )
243 transformString += QLatin1String(
"+towgs84=" );
251 if ( methodCode == 9603 )
253 transformString += QStringLiteral(
"%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) );
257 transformString += QStringLiteral(
"%1,%2,%3,%4,%5,%6,%7" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ), QString::number( p4 ), QString::number( p5 ), QString::number( p6 ), QString::number( p7 ) );
261 if ( transformString.compare(
string, Qt::CaseInsensitive ) == 0 )
276 if ( openResult != SQLITE_OK )
282 QString sql = QStringLiteral(
"SELECT epsg_nr,source_crs_code,target_crs_code,remarks,scope,preferred,deprecated FROM tbl_datum_transform WHERE coord_op_code=%1" ).arg( datumTransform );
284 statement = database.
prepare( sql, prepareRes );
285 if ( prepareRes != SQLITE_OK )
290 int srcCrsId, destCrsId;
291 if ( statement.
step() != SQLITE_ROW )
315 #if PROJ_VERSION_MAJOR>=6 323 QgsProjUtils::proj_pj_unique_ptr normalized( proj_normalize_for_visualization( pjContext, op ) );
325 details.
proj = QString( proj_as_proj_string( pjContext, normalized.get(), PJ_PROJ_5, nullptr ) );
327 if ( details.
proj.isEmpty() )
328 details.
proj = QString( proj_as_proj_string( pjContext, op, PJ_PROJ_5,
nullptr ) );
329 details.
name = QString( proj_get_name( op ) );
330 details.
accuracy = proj_coordoperation_get_accuracy( pjContext, op );
331 details.
isAvailable = proj_coordoperation_is_instantiable( pjContext, op );
333 details.
authority = QString( proj_get_id_auth_name( op, 0 ) );
334 details.
code = QString( proj_get_id_code( op, 0 ) );
336 const char *areaOfUseName =
nullptr;
341 if ( proj_get_area_of_use( pjContext, op, &westLon, &southLat, &eastLon, &northLat, &areaOfUseName ) )
343 details.
areaOfUse = QString( areaOfUseName );
351 #if PROJ_VERSION_MAJOR>6 || (PROJ_VERSION_MAJOR==6 && PROJ_VERSION_MINOR>=2) 352 details.
remarks = QString( proj_get_remarks( op ) );
353 details.
scope = QString( proj_get_scope( op ) );
356 for (
int j = 0; j < proj_coordoperation_get_grid_used_count( pjContext, op ); ++j )
358 const char *shortName =
nullptr;
359 const char *fullName =
nullptr;
360 const char *packageName =
nullptr;
361 const char *url =
nullptr;
362 int directDownload = 0;
365 proj_coordoperation_get_grid_used( pjContext, op, j, &shortName, &fullName, &packageName, &url, &directDownload, &openLicense, &isAvailable );
367 gridDetails.
shortName = QString( shortName );
368 gridDetails.
fullName = QString( fullName );
370 gridDetails.
url = QString( url );
375 details.
grids.append( gridDetails );
378 #if PROJ_VERSION_MAJOR>6 || (PROJ_VERSION_MAJOR==6 && PROJ_VERSION_MINOR>=2) 379 for (
int j = 0; j < proj_concatoperation_get_step_count( pjContext, op ); ++j )
381 QgsProjUtils::proj_pj_unique_ptr step( proj_concatoperation_get_step( pjContext, op, j ) );
385 singleOpDetails.
remarks = QString( proj_get_remarks( step.get() ) );
386 singleOpDetails.
scope = QString( proj_get_scope( step.get() ) );
387 singleOpDetails.
authority = QString( proj_get_id_auth_name( step.get(), 0 ) );
388 singleOpDetails.
code = QString( proj_get_id_code( step.get(), 0 ) );
390 const char *areaOfUseName =
nullptr;
391 if ( proj_get_area_of_use( pjContext, step.get(),
nullptr,
nullptr,
nullptr,
nullptr, &areaOfUseName ) )
393 singleOpDetails.
areaOfUse = QString( areaOfUseName );
QString geographicCrsAuthId() const
Returns auth id of related geographic CRS.
void setXMaximum(double x)
Set the maximum x value.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
void setYMinimum(double y)
Set the minimum y value.
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
void setYMaximum(double y)
Set the maximum y value.
This class represents a coordinate reference system (CRS).
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
static PJ_CONTEXT * get()
Returns a thread local instance of a proj context, safe for use in the current thread.
double columnAsDouble(int column) const
Gets column value from the current statement row as a double.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
QString authid() const
Returns the authority identifier for the CRS.
void setXMinimum(double x)
Set the minimum x value.