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 ( includeSuperseded )
50 proj_operation_factory_context_set_discard_superseded( pjContext, operationContext,
false );
52 if ( PJ_OBJ_LIST *ops = proj_create_operations( pjContext, source.projObject(), destination.projObject(), operationContext ) )
54 int count = proj_list_get_count( ops );
55 for (
int i = 0; i < count; ++i )
57 QgsProjUtils::proj_pj_unique_ptr op( proj_list_get( pjContext, ops, i ) );
62 if ( !details.
proj.isEmpty() )
63 res.push_back( details );
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
319 TransformDetails details;
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 ) );
330 if ( details.proj.isEmpty() )
333 details.name = QString( proj_get_name( op ) );
334 details.accuracy = proj_coordoperation_get_accuracy( pjContext, op );
335 details.isAvailable = proj_coordoperation_is_instantiable( pjContext, op );
337 details.authority = QString( proj_get_id_auth_name( op, 0 ) );
338 details.code = QString( proj_get_id_code( op, 0 ) );
340 const char *areaOfUseName =
nullptr;
345 if ( proj_get_area_of_use( pjContext, op, &westLon, &southLat, &eastLon, &northLat, &areaOfUseName ) )
347 details.areaOfUse = QString( areaOfUseName );
349 details.bounds.setXMinimum( westLon );
350 details.bounds.setYMinimum( southLat );
351 details.bounds.setXMaximum( eastLon );
352 details.bounds.setYMaximum( northLat );
355 details.remarks = QString( proj_get_remarks( op ) );
356 details.scope = QString( proj_get_scope( op ) );
358 for (
int j = 0; j < proj_coordoperation_get_grid_used_count( pjContext, op ); ++j )
360 const char *shortName =
nullptr;
361 const char *fullName =
nullptr;
362 const char *packageName =
nullptr;
363 const char *url =
nullptr;
364 int directDownload = 0;
367 proj_coordoperation_get_grid_used( pjContext, op, j, &shortName, &fullName, &packageName, &url, &directDownload, &openLicense, &isAvailable );
368 GridDetails gridDetails;
369 gridDetails.shortName = QString( shortName );
370 gridDetails.fullName = QString( fullName );
371 gridDetails.packageName = QString( packageName );
372 gridDetails.url = QString( url );
373 gridDetails.directDownload = directDownload;
374 gridDetails.openLicense = openLicense;
375 gridDetails.isAvailable = isAvailable;
377 details.grids.append( gridDetails );
380 if ( proj_get_type( op ) == PJ_TYPE_CONCATENATED_OPERATION )
382 for (
int j = 0; j < proj_concatoperation_get_step_count( pjContext, op ); ++j )
384 QgsProjUtils::proj_pj_unique_ptr step( proj_concatoperation_get_step( pjContext, op, j ) );
387 SingleOperationDetails singleOpDetails;
388 singleOpDetails.remarks = QString( proj_get_remarks( step.get() ) );
389 singleOpDetails.scope = QString( proj_get_scope( step.get() ) );
390 singleOpDetails.authority = QString( proj_get_id_auth_name( step.get(), 0 ) );
391 singleOpDetails.code = QString( proj_get_id_code( step.get(), 0 ) );
393 const char *areaOfUseName =
nullptr;
394 if ( proj_get_area_of_use( pjContext, step.get(),
nullptr,
nullptr,
nullptr,
nullptr, &areaOfUseName ) )
396 singleOpDetails.areaOfUse = QString( areaOfUseName );
398 details.operationDetails.append( singleOpDetails );
404 SingleOperationDetails singleOpDetails;
405 singleOpDetails.remarks = QString( proj_get_remarks( op ) );
406 singleOpDetails.scope = QString( proj_get_scope( op ) );
407 singleOpDetails.authority = QString( proj_get_id_auth_name( op, 0 ) );
408 singleOpDetails.code = QString( proj_get_id_code( op, 0 ) );
410 const char *areaOfUseName =
nullptr;
411 if ( proj_get_area_of_use( pjContext, op,
nullptr,
nullptr,
nullptr,
nullptr, &areaOfUseName ) )
413 singleOpDetails.areaOfUse = QString( areaOfUseName );
415 details.operationDetails.append( singleOpDetails );