28 QList< QgsDatumTransform::TransformDetails > res;
34 PJ_OPERATION_FACTORY_CONTEXT *operationContext = proj_create_operation_factory_context( pjContext,
nullptr );
37 proj_operation_factory_context_set_grid_availability_use( pjContext, operationContext, PROJ_GRID_AVAILABILITY_IGNORED );
40 proj_operation_factory_context_set_spatial_criterion( pjContext, operationContext, PROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION );
42 if ( includeSuperseded )
43 proj_operation_factory_context_set_discard_superseded( pjContext, operationContext,
false );
45 if ( PJ_OBJ_LIST *ops = proj_create_operations( pjContext, source.
projObject(), destination.
projObject(), operationContext ) )
47 int count = proj_list_get_count( ops );
48 for (
int i = 0; i < count; ++i )
55 if ( !details.
proj.isEmpty() )
56 res.push_back( details );
59 proj_list_destroy( ops );
61 proj_operation_factory_context_destroy( operationContext );
67 QList< QgsDatumTransform::TransformPair > transformations;
72 if ( srcGeoId.isEmpty() || destGeoId.isEmpty() )
74 return transformations;
77 QStringList srcSplit = srcGeoId.split(
':' );
78 QStringList destSplit = destGeoId.split(
':' );
80 if ( srcSplit.size() < 2 || destSplit.size() < 2 )
82 return transformations;
85 int srcAuthCode = srcSplit.at( 1 ).toInt();
86 int destAuthCode = destSplit.at( 1 ).toInt();
88 if ( srcAuthCode == destAuthCode )
90 return transformations;
93 QList<int> directTransforms;
94 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 ),
96 QList<int> reverseDirectTransforms;
97 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 ),
98 reverseDirectTransforms );
99 QList<int> srcToWgs84;
100 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 ),
102 QList<int> destToWgs84;
103 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 ),
107 for (
int transform : std::as_const( directTransforms ) )
113 for (
int transform : std::as_const( reverseDirectTransforms ) )
118 for (
int srcTransform : std::as_const( srcToWgs84 ) )
120 for (
int destTransform : std::as_const( destToWgs84 ) )
126 return transformations;
129 void QgsDatumTransform::searchDatumTransform(
const QString &sql, QList< int > &transforms )
133 if ( openResult != SQLITE_OK )
140 statement = database.
prepare( sql, prepareRes );
141 if ( prepareRes != SQLITE_OK )
147 while ( statement.
step() == SQLITE_ROW )
150 transforms.push_back( cOpCode.toInt() );
156 QString transformString;
160 if ( openResult != SQLITE_OK )
162 return transformString;
166 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 );
168 statement = database.
prepare( sql, prepareRes );
169 if ( prepareRes != SQLITE_OK )
171 return transformString;
174 if ( statement.
step() == SQLITE_ROW )
178 if ( methodCode == 9615 )
180 transformString =
"+nadgrids=" + statement.
columnAsText( 1 );
182 else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 )
184 transformString += QLatin1String(
"+towgs84=" );
192 if ( methodCode == 9603 )
194 transformString += QStringLiteral(
"%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) );
198 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 ) );
203 return transformString;
210 if ( openResult != SQLITE_OK )
216 QString sql = QStringLiteral(
"SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7,coord_op_code FROM tbl_datum_transform" );
218 statement = database.
prepare( sql, prepareRes );
219 if ( prepareRes != SQLITE_OK )
224 while ( statement.
step() == SQLITE_ROW )
226 QString transformString;
229 if ( methodCode == 9615 )
231 transformString =
"+nadgrids=" + statement.
columnAsText( 1 );
233 else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 )
235 transformString += QLatin1String(
"+towgs84=" );
243 if ( methodCode == 9603 )
245 transformString += QStringLiteral(
"%1,%2,%3" ).arg( QString::number( p1 ), QString::number( p2 ), QString::number( p3 ) );
249 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 ) );
253 if ( transformString.compare(
string, Qt::CaseInsensitive ) == 0 )
268 if ( openResult != SQLITE_OK )
274 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 );
276 statement = database.
prepare( sql, prepareRes );
277 if ( prepareRes != SQLITE_OK )
282 int srcCrsId, destCrsId;
283 if ( statement.
step() != SQLITE_ROW )
316 details.
proj = QString( proj_as_proj_string( pjContext, normalized.get(), PJ_PROJ_5,
nullptr ) );
318 if ( details.
proj.isEmpty() )
319 details.
proj = QString( proj_as_proj_string( pjContext, op, PJ_PROJ_5,
nullptr ) );
321 if ( details.
proj.isEmpty() )
324 details.
name = QString( proj_get_name( op ) );
325 details.
accuracy = proj_coordoperation_get_accuracy( pjContext, op );
326 details.
isAvailable = proj_coordoperation_is_instantiable( pjContext, op );
328 details.
authority = QString( proj_get_id_auth_name( op, 0 ) );
329 details.
code = QString( proj_get_id_code( op, 0 ) );
331 const char *areaOfUseName =
nullptr;
336 if ( proj_get_area_of_use( pjContext, op, &westLon, &southLat, &eastLon, &northLat, &areaOfUseName ) )
338 details.
areaOfUse = QString( areaOfUseName );
346 details.
remarks = QString( proj_get_remarks( op ) );
347 details.
scope = QString( proj_get_scope( op ) );
349 for (
int j = 0; j < proj_coordoperation_get_grid_used_count( pjContext, op ); ++j )
351 const char *shortName =
nullptr;
352 const char *fullName =
nullptr;
353 const char *packageName =
nullptr;
354 const char *url =
nullptr;
355 int directDownload = 0;
358 proj_coordoperation_get_grid_used( pjContext, op, j, &shortName, &fullName, &packageName, &url, &directDownload, &openLicense, &isAvailable );
360 gridDetails.
shortName = QString( shortName );
361 gridDetails.
fullName = QString( fullName );
363 gridDetails.
url = QString( url );
368 details.
grids.append( gridDetails );
371 if ( proj_get_type( op ) == PJ_TYPE_CONCATENATED_OPERATION )
373 for (
int j = 0; j < proj_concatoperation_get_step_count( pjContext, op ); ++j )
379 singleOpDetails.
remarks = QString( proj_get_remarks( step.get() ) );
380 singleOpDetails.
scope = QString( proj_get_scope( step.get() ) );
381 singleOpDetails.
authority = QString( proj_get_id_auth_name( step.get(), 0 ) );
382 singleOpDetails.
code = QString( proj_get_id_code( step.get(), 0 ) );
384 const char *areaOfUseName =
nullptr;
385 if ( proj_get_area_of_use( pjContext, step.get(),
nullptr,
nullptr,
nullptr,
nullptr, &areaOfUseName ) )
387 singleOpDetails.
areaOfUse = QString( areaOfUseName );
396 singleOpDetails.
remarks = QString( proj_get_remarks( op ) );
397 singleOpDetails.
scope = QString( proj_get_scope( op ) );
398 singleOpDetails.
authority = QString( proj_get_id_auth_name( op, 0 ) );
399 singleOpDetails.
code = QString( proj_get_id_code( op, 0 ) );
401 const char *areaOfUseName =
nullptr;
402 if ( proj_get_area_of_use( pjContext, op,
nullptr,
nullptr,
nullptr,
nullptr, &areaOfUseName ) )
404 singleOpDetails.
areaOfUse = QString( areaOfUseName );
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
PJ * projObject() const
Returns the underlying PROJ PJ object corresponding to the CRS, or nullptr if the CRS is invalid.
QString authid() const
Returns the authority identifier for the CRS.
QString geographicCrsAuthId() const
Returns auth id of related geographic CRS.
static PJ_CONTEXT * get()
Returns a thread local instance of a proj context, safe for use in the current thread.
std::unique_ptr< PJ, ProjPJDeleter > proj_pj_unique_ptr
Scoped Proj PJ object.
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Unique pointer for sqlite3 databases, which automatically closes the database when the pointer goes o...
sqlite3_statement_unique_ptr prepare(const QString &sql, int &resultCode) const
Prepares a sql statement, returning the result.
int open_v2(const QString &path, int flags, const char *zVfs)
Opens the database at the specified file path.
Unique pointer for sqlite3 prepared statements, which automatically finalizes the statement when the ...
QString columnAsText(int column) const
Returns the column value from the current statement row as a string.
double columnAsDouble(int column) const
Gets column value from the current statement row as a double.
int step()
Steps to the next record in the statement, returning the sqlite3 result code.
qlonglong columnAsInt64(int column) const
Gets column value from the current statement row as a long long integer (64 bits).
struct projCtx_t PJ_CONTEXT