Skip to content

Commit 68bbf46

Browse files
wonder-sknyalldawson
authored andcommittedMay 17, 2020
Add QgsRasterDataProvider::transformCoordinates()
This is useful when client needs to find out image space coordinates of a point in map layer coordinates or vice versa. For warped VRT rasters this can't be simply done by using geotransform matrix because the transform may be more complex. This may be also useful functionality for identify tool to show source raster image coordinates.
1 parent 6358baa commit 68bbf46

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed
 

‎python/core/auto_generated/raster/qgsrasterdataprovider.sip.in‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,26 @@ Returns true if the extents reported by the data provider are not reliable
495495
and it's possible that there is renderable content outside of these extents.
496496

497497
.. versionadded:: 3.10.0
498+
%End
499+
500+
enum TransformType
501+
{
502+
TransformImageToLayer,
503+
TransformLayerToImage,
504+
};
505+
506+
virtual QgsPoint transformCoordinates( const QgsPoint &point, TransformType type );
507+
%Docstring
508+
Transforms coordinates between source image coordinate space [0..width]x[0..height] and
509+
layer coordinate space (georeferenced coordinates). Often this transformation is a simple
510+
2D affine transformation (offset and scaling), but rasters with different georeferencing
511+
methods like GCPs (ground control points) or RPCs (rational polynomial coefficients) may
512+
require a more complex transform.
513+
514+
If the transform fails (input coordinates are outside of the valid range or data provider
515+
does not support this functionality), an empty point is returned.
516+
517+
.. versionadded:: 3.14
498518
%End
499519

500520
signals:

‎src/core/providers/gdal/qgsgdalprovider.cpp‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,9 @@ QgsGdalProvider::~QgsGdalProvider()
457457
{
458458
QMutexLocker locker( sGdalProviderMutex() );
459459

460+
if ( mGdalTransformerArg )
461+
GDALDestroyTransformer( mGdalTransformerArg );
462+
460463
int lightRefCounter = -- ( *mpLightRefCounter );
461464
int refCounter = -- ( *mpRefCounter );
462465
if ( refCounter == 0 )
@@ -2686,6 +2689,8 @@ void QgsGdalProvider::initBaseDataset()
26862689
mGdalDataset = mGdalBaseDataset;
26872690
}
26882691

2692+
mGdalTransformerArg = GDALCreateGenImgProjTransformer( mGdalBaseDataset, nullptr, nullptr, nullptr, TRUE, 1.0, 0 );
2693+
26892694
if ( !hasGeoTransform )
26902695
{
26912696
// Initialize the affine transform matrix
@@ -3156,6 +3161,20 @@ QString QgsGdalProvider::validatePyramidsConfigOptions( QgsRaster::RasterPyramid
31563161
return QString();
31573162
}
31583163

3164+
QgsPoint QgsGdalProvider::transformCoordinates( const QgsPoint &point, QgsRasterDataProvider::TransformType type )
3165+
{
3166+
if ( !mGdalTransformerArg )
3167+
return QgsPoint();
3168+
3169+
int success;
3170+
double x = point.x(), y = point.y(), z = point.is3D() ? point.z() : 0;
3171+
GDALUseTransformer( mGdalTransformerArg, type == TransformLayerToImage, 1, &x, &y, &z, &success );
3172+
if ( !success )
3173+
return QgsPoint();
3174+
3175+
return QgsPoint( x, y, z );
3176+
}
3177+
31593178
bool QgsGdalProvider::isEditable() const
31603179
{
31613180
return mUpdate;

‎src/core/providers/gdal/qgsgdalprovider.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ class QgsGdalProvider final: public QgsRasterDataProvider, QgsGdalProviderBase
203203
QString validatePyramidsConfigOptions( QgsRaster::RasterPyramidsFormat pyramidsFormat,
204204
const QStringList &configOptions, const QString &fileFormat ) override;
205205

206+
QgsPoint transformCoordinates( const QgsPoint &point, TransformType type ) override;
207+
206208
private:
207209
QgsGdalProvider( const QgsGdalProvider &other );
208210

@@ -338,6 +340,9 @@ class QgsGdalProvider final: public QgsRasterDataProvider, QgsGdalProviderBase
338340
* Closes and reinits dataset
339341
*/
340342
void reloadProviderData() override;
343+
344+
//! Instance of GDAL transformer function used in transformCoordinates() for conversion between image and layer coordinates
345+
void *mGdalTransformerArg = nullptr;
341346
};
342347

343348
/**

‎src/core/raster/qgsrasterdataprovider.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,13 @@ bool QgsRasterDataProvider::ignoreExtents() const
512512
return false;
513513
}
514514

515+
QgsPoint QgsRasterDataProvider::transformCoordinates( const QgsPoint &point, QgsRasterDataProvider::TransformType type )
516+
{
517+
Q_UNUSED( point )
518+
Q_UNUSED( type )
519+
return QgsPoint();
520+
}
521+
515522
bool QgsRasterDataProvider::userNoDataValuesContains( int bandNo, double value ) const
516523
{
517524
QgsRasterRangeList rangeList = mUserNoDataValue.value( bandNo - 1 );

‎src/core/raster/qgsrasterdataprovider.h‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,30 @@ class CORE_EXPORT QgsRasterDataProvider : public QgsDataProvider, public QgsRast
557557
*/
558558
virtual bool ignoreExtents() const;
559559

560+
/**
561+
* Types of transformation in transformCoordinates() function.
562+
* \since QGIS 3.14
563+
*/
564+
enum TransformType
565+
{
566+
TransformImageToLayer, //!< Transforms image coordinates to layer (georeferenced) coordinates
567+
TransformLayerToImage, //!< Transforms layer (georeferenced) coordinates to image coordinates
568+
};
569+
570+
/**
571+
* Transforms coordinates between source image coordinate space [0..width]x[0..height] and
572+
* layer coordinate space (georeferenced coordinates). Often this transformation is a simple
573+
* 2D affine transformation (offset and scaling), but rasters with different georeferencing
574+
* methods like GCPs (ground control points) or RPCs (rational polynomial coefficients) may
575+
* require a more complex transform.
576+
*
577+
* If the transform fails (input coordinates are outside of the valid range or data provider
578+
* does not support this functionality), an empty point is returned.
579+
*
580+
* \since QGIS 3.14
581+
*/
582+
virtual QgsPoint transformCoordinates( const QgsPoint &point, TransformType type );
583+
560584
signals:
561585

562586
/**

0 commit comments

Comments
 (0)
Please sign in to comment.