Skip to content

Commit cfdc3c7

Browse files
committed
Use geometry of reproject extent parameters for more accurate clipping
1 parent 60b56db commit cfdc3c7

8 files changed

+112
-3
lines changed

python/core/processing/qgsprocessingalgorithm.sip

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,9 +669,25 @@ class QgsProcessingAlgorithm
669669

670670
If ``crs`` is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
671671
reprojected so that it is in the specified ``crs``. In this case the extent of the reproject rectangle will be returned.
672+
673+
.. seealso:: parameterAsExtentGeometry()
672674
:rtype: QgsRectangle
673675
%End
674676

677+
QgsGeometry parameterAsExtentGeometry( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
678+
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
679+
%Docstring
680+
Evaluates the parameter with matching ``name`` to a rectangular extent, and returns a geometry covering this extent.
681+
682+
If ``crs`` is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
683+
reprojected so that it is in the specified ``crs``. Unlike parameterAsExtent(), the reprojected rectangle returned by this function
684+
will no longer be a rectangle itself (i.e. this method returns the geometry of the actual reprojected rectangle, while parameterAsExtent() returns
685+
just the extent of the reprojected rectangle).
686+
687+
.. seealso:: parameterAsExtent()
688+
:rtype: QgsGeometry
689+
%End
690+
675691
QgsPointXY parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
676692
%Docstring
677693
Evaluates the parameter with matching ``name`` to a point.

python/core/processing/qgsprocessingparameters.sip

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,9 +541,25 @@ class QgsProcessingParameters
541541

542542
If ``crs`` is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
543543
reprojected so that it is in the specified ``crs``. In this case the extent of the reproject rectangle will be returned.
544+
545+
.. seealso:: parameterAsExtentGeometry()
544546
:rtype: QgsRectangle
545547
%End
546548

549+
static QgsGeometry parameterAsExtentGeometry( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context,
550+
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
551+
%Docstring
552+
Evaluates the parameter with matching ``definition`` to a rectangular extent, and returns a geometry covering this extent.
553+
554+
If ``crs`` is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
555+
reprojected so that it is in the specified ``crs``. Unlike parameterAsExtent(), the reprojected rectangle returned by this function
556+
will no longer be a rectangle itself (i.e. this method returns the geometry of the actual reprojected rectangle, while parameterAsExtent() returns
557+
just the extent of the reprojected rectangle).
558+
559+
.. seealso:: parameterAsExtent()
560+
:rtype: QgsGeometry
561+
%End
562+
547563
static QgsPointXY parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
548564
%Docstring
549565
Evaluates the parameter with matching ``definition`` to a point.

src/core/processing/qgsnativealgorithms.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1854,7 +1854,7 @@ QVariantMap QgsExtractByExtentAlgorithm::processAlgorithm( const QVariantMap &pa
18541854
if ( !sink )
18551855
return QVariantMap();
18561856

1857-
QgsGeometry clipGeom = QgsGeometry::fromRect( extent );
1857+
QgsGeometry clipGeom = parameterAsExtentGeometry( parameters, QStringLiteral( "EXTENT" ), context, featureSource->sourceCrs() );
18581858

18591859
double step = featureSource->featureCount() > 0 ? 100.0 / featureSource->featureCount() : 1;
18601860
QgsFeatureIterator inputIt = featureSource->getFeatures( QgsFeatureRequest().setFilterRect( extent ).setFlags( QgsFeatureRequest::ExactIntersect ) );

src/core/processing/qgsprocessingalgorithm.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,11 @@ QgsRectangle QgsProcessingAlgorithm::parameterAsExtent( const QVariantMap &param
555555
return QgsProcessingParameters::parameterAsExtent( parameterDefinition( name ), parameters, context, crs );
556556
}
557557

558+
QgsGeometry QgsProcessingAlgorithm::parameterAsExtentGeometry( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
559+
{
560+
return QgsProcessingParameters::parameterAsExtentGeometry( parameterDefinition( name ), parameters, context, crs );
561+
}
562+
558563
QgsPointXY QgsProcessingAlgorithm::parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
559564
{
560565
return QgsProcessingParameters::parameterAsPoint( parameterDefinition( name ), parameters, context );

src/core/processing/qgsprocessingalgorithm.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,10 +651,25 @@ class CORE_EXPORT QgsProcessingAlgorithm
651651
*
652652
* If \a crs is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
653653
* reprojected so that it is in the specified \a crs. In this case the extent of the reproject rectangle will be returned.
654+
*
655+
* \see parameterAsExtentGeometry()
654656
*/
655657
QgsRectangle parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
656658
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() ) const;
657659

660+
/**
661+
* Evaluates the parameter with matching \a name to a rectangular extent, and returns a geometry covering this extent.
662+
*
663+
* If \a crs is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
664+
* reprojected so that it is in the specified \a crs. Unlike parameterAsExtent(), the reprojected rectangle returned by this function
665+
* will no longer be a rectangle itself (i.e. this method returns the geometry of the actual reprojected rectangle, while parameterAsExtent() returns
666+
* just the extent of the reprojected rectangle).
667+
*
668+
* \see parameterAsExtent()
669+
*/
670+
QgsGeometry parameterAsExtentGeometry( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
671+
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
672+
658673
/**
659674
* Evaluates the parameter with matching \a name to a point.
660675
*/

src/core/processing/qgsprocessingparameters.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,36 @@ QgsRectangle QgsProcessingParameters::parameterAsExtent( const QgsProcessingPara
539539
return QgsRectangle();
540540
}
541541

542+
QgsGeometry QgsProcessingParameters::parameterAsExtentGeometry( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
543+
{
544+
if ( !definition )
545+
return QgsGeometry();
546+
547+
QVariant val = parameters.value( definition->name() );
548+
549+
if ( val.canConvert< QgsReferencedRectangle >() )
550+
{
551+
QgsReferencedRectangle rr = val.value<QgsReferencedRectangle>();
552+
QgsGeometry g = QgsGeometry::fromRect( rr );
553+
if ( crs.isValid() && rr.crs().isValid() && crs != rr.crs() )
554+
{
555+
g = g.densifyByCount( 20 );
556+
QgsCoordinateTransform ct( rr.crs(), crs );
557+
try
558+
{
559+
g.transform( ct );
560+
}
561+
catch ( QgsCsException & )
562+
{
563+
QgsMessageLog::logMessage( QObject::tr( "Error transforming extent geometry" ) );
564+
}
565+
return g;
566+
}
567+
}
568+
569+
return QgsGeometry::fromRect( parameterAsExtent( definition, parameters, context, crs ) );
570+
}
571+
542572
QgsPointXY QgsProcessingParameters::parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
543573
{
544574
if ( !definition )

src/core/processing/qgsprocessingparameters.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,10 +568,25 @@ class CORE_EXPORT QgsProcessingParameters
568568
*
569569
* If \a crs is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
570570
* reprojected so that it is in the specified \a crs. In this case the extent of the reproject rectangle will be returned.
571+
*
572+
* \see parameterAsExtentGeometry()
571573
*/
572574
static QgsRectangle parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context,
573575
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
574576

577+
/**
578+
* Evaluates the parameter with matching \a definition to a rectangular extent, and returns a geometry covering this extent.
579+
*
580+
* If \a crs is set, and the original coordinate reference system of the parameter can be determined, then the extent will be automatically
581+
* reprojected so that it is in the specified \a crs. Unlike parameterAsExtent(), the reprojected rectangle returned by this function
582+
* will no longer be a rectangle itself (i.e. this method returns the geometry of the actual reprojected rectangle, while parameterAsExtent() returns
583+
* just the extent of the reprojected rectangle).
584+
*
585+
* \see parameterAsExtent()
586+
*/
587+
static QgsGeometry parameterAsExtentGeometry( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context,
588+
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
589+
575590
/**
576591
* Evaluates the parameter with matching \a definition to a point.
577592
*/

tests/src/core/testqgsprocessing.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,6 +1912,9 @@ void TestQgsProcessing::parameterExtent()
19121912
QGSCOMPARENEAR( ext.yMinimum(), 12.2, 0.001 );
19131913
QGSCOMPARENEAR( ext.yMaximum(), 14.4, 0.001 );
19141914

1915+
QgsGeometry gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
1916+
QCOMPARE( gExt.exportToWkt( 1 ), QStringLiteral( "Polygon ((11.1 12.2, 13.3 12.2, 13.3 14.4, 11.1 14.4, 11.1 12.2))" ) );
1917+
19151918
// QgsReferencedRectangle
19161919
params.insert( "non_optional", QgsReferencedRectangle( QgsRectangle( 1.1, 2.2, 3.3, 4.4 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) );
19171920
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
@@ -1927,13 +1930,22 @@ void TestQgsProcessing::parameterExtent()
19271930
QGSCOMPARENEAR( ext.yMinimum(), 244963, 100 );
19281931
QGSCOMPARENEAR( ext.yMaximum(), 490287, 100 );
19291932

1933+
// as reprojected geometry
1934+
gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
1935+
QCOMPARE( gExt.geometry()->vertexCount(), 85 );
1936+
ext = gExt.boundingBox();
1937+
QGSCOMPARENEAR( ext.xMinimum(), 122451, 100 );
1938+
QGSCOMPARENEAR( ext.xMaximum(), 367354, 100 );
1939+
QGSCOMPARENEAR( ext.yMinimum(), 244963, 100 );
1940+
QGSCOMPARENEAR( ext.yMaximum(), 490287, 100 );
1941+
19301942
QCOMPARE( def->valueAsPythonString( "1,2,3,4", context ), QStringLiteral( "'1,2,3,4'" ) );
19311943
QCOMPARE( def->valueAsPythonString( r1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
19321944
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( r1 ), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
19331945
QCOMPARE( def->valueAsPythonString( raster2, context ), QString( "'" ) + testDataDir + QStringLiteral( "landsat.tif'" ) );
19341946
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
1935-
QCOMPARE( def->valueAsPythonString( QgsRectangle( 11.1, 12.2, 13.3, 14.4 ), context ), QStringLiteral( "QgsRectangle( 11.1, 12.2, 13.3, 14.4 )" ) );
1936-
QCOMPARE( def->valueAsPythonString( QgsReferencedRectangle( QgsRectangle( 11.1, 12.2, 13.3, 14.4 ), QgsCoordinateReferenceSystem( "epsg:4326" ) ), context ), QStringLiteral( "QgsReferencedRectangle( QgsRectangle( 11.1, 12.2, 13.3, 14.4 ), QgsCoordinateReferenceSystem( 'EPSG:4326' ) )" ) );
1947+
QCOMPARE( def->valueAsPythonString( QgsRectangle( 11, 12, 13, 14 ), context ), QStringLiteral( "QgsRectangle( 11, 12, 13, 14 )" ) );
1948+
QCOMPARE( def->valueAsPythonString( QgsReferencedRectangle( QgsRectangle( 11, 12, 13, 14 ), QgsCoordinateReferenceSystem( "epsg:4326" ) ), context ), QStringLiteral( "QgsReferencedRectangle( QgsRectangle( 11, 12, 13, 14 ), QgsCoordinateReferenceSystem( 'EPSG:4326' ) )" ) );
19371949

19381950
QString code = def->asScriptCode();
19391951
QCOMPARE( code, QStringLiteral( "##non_optional=extent 1,2,3,4" ) );

0 commit comments

Comments
 (0)