Skip to content

Commit

Permalink
Merge pull request #42187 from wonder-sk/fix-rasterize-alg-layer-list
Browse files Browse the repository at this point in the history
Fix wrong list of layers in Rasterize alg (Convert map to raster)

(cherry picked from commit eb185d2)
  • Loading branch information
nyalldawson committed Apr 17, 2021
1 parent 9d528a4 commit 3387268
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 11 deletions.
1 change: 1 addition & 0 deletions .docker/qgis3-build-deps.dockerfile
Expand Up @@ -95,6 +95,7 @@ RUN apt-get update \
qt3d-defaultgeometryloader-plugin \
qt3d-gltfsceneio-plugin \
qt3d-scene2d-plugin \
qt5-image-formats-plugins \
qt5keychain-dev \
qtbase5-dev \
qtdeclarative5-dev-tools \
Expand Down
15 changes: 12 additions & 3 deletions python/core/auto_generated/qgsrenderchecker.sip.in
Expand Up @@ -40,9 +40,18 @@ Constructor for QgsRenderChecker.

void setControlName( const QString &name );
%Docstring
Base directory name for the control image (with control image path
suffixed) the path to the image will be constructed like this:
controlImagePath + '/' + mControlName + '/' + mControlName + '.png'
Sets the base directory ``name`` for the control image (with control image path
suffixed).

The path to the image will be constructed like this:
:py:func:`~QgsRenderChecker.controlImagePath` + '/' + control name + '/' + control name + '.' + extension ('png' by default)
%End

void setControlExtension( const QString &extension );
%Docstring
Sets file extension for the control image. By default it is "png"

.. versionadded:: 3.20
%End

void setControlPathPrefix( const QString &name );
Expand Down
13 changes: 11 additions & 2 deletions src/analysis/processing/qgsalgorithmrasterize.cpp
Expand Up @@ -29,6 +29,7 @@
#include "qgsmaprenderercustompainterjob.h"
#include "gdal.h"
#include "qgsgdalutils.h"
#include "qgslayertree.h"

#include <QtConcurrent>

Expand Down Expand Up @@ -333,8 +334,16 @@ bool QgsRasterizeAlgorithm::prepareAlgorithm( const QVariantMap &parameters, Qgs
// Still no layers? Get them all from the project
if ( mMapLayers.size() == 0 )
{
const auto constLayers { context.project()->mapLayers().values() };
for ( const QgsMapLayer *ml : constLayers )
QList<QgsMapLayer *> layers;
QgsLayerTree *root = context.project()->layerTreeRoot();
for ( QgsLayerTreeLayer *nodeLayer : root->findLayers() )
{
QgsMapLayer *layer = nodeLayer->layer();
if ( nodeLayer->isVisible() && root->layerOrder().contains( layer ) )
layers << layer;
}

for ( const QgsMapLayer *ml : qgis::as_const( layers ) )
{
mMapLayers.push_back( std::unique_ptr<QgsMapLayer>( ml->clone( ) ) );
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsrenderchecker.cpp
Expand Up @@ -38,7 +38,7 @@ QString QgsRenderChecker::controlImagePath() const
void QgsRenderChecker::setControlName( const QString &name )
{
mControlName = name;
mExpectedImageFile = controlImagePath() + name + '/' + mControlPathSuffix + name + ".png";
mExpectedImageFile = controlImagePath() + name + '/' + mControlPathSuffix + name + "." + mControlExtension;
}

void QgsRenderChecker::setControlPathSuffix( const QString &name )
Expand Down
19 changes: 14 additions & 5 deletions src/core/qgsrenderchecker.h
Expand Up @@ -60,15 +60,23 @@ class CORE_EXPORT QgsRenderChecker
void setElapsedTimeTarget( int target ) { mElapsedTimeTarget = target; }

/**
* Base directory name for the control image (with control image path
* suffixed) the path to the image will be constructed like this:
* controlImagePath + '/' + mControlName + '/' + mControlName + '.png'
* Sets the base directory \a name for the control image (with control image path
* suffixed).
*
* The path to the image will be constructed like this:
* controlImagePath() + '/' + control name + '/' + control name + '.' + extension ('png' by default)
*/
void setControlName( const QString &name );

/**
* Prefix where the control images are kept.
* This will be appended to controlImagePath
* Sets file extension for the control image. By default it is "png"
* \since QGIS 3.20
*/
void setControlExtension( const QString &extension ) { mControlExtension = extension; }

/**
* Sets the path prefix where the control images are kept.
* This will be appended to controlImagePath().
*/
void setControlPathPrefix( const QString &name ) { mControlPathPrefix = name + '/'; }

Expand Down Expand Up @@ -197,6 +205,7 @@ class CORE_EXPORT QgsRenderChecker
int mMaxSizeDifferenceY = 0;
int mElapsedTimeTarget = 0;
QgsMapSettings mMapSettings;
QString mControlExtension = QStringLiteral( "png" );
QString mControlPathPrefix;
QString mControlPathSuffix;
QVector<QgsDartMeasurement> mDashMessages;
Expand Down
50 changes: 50 additions & 0 deletions tests/src/analysis/testqgsprocessingalgs.cpp
Expand Up @@ -38,6 +38,7 @@
#include "qgsreclassifyutils.h"
#include "qgsalgorithmrasterlogicalop.h"
#include "qgsprintlayout.h"
#include "qgslayertree.h"
#include "qgslayoutmanager.h"
#include "qgslayoutitemmap.h"
#include "qgsmarkersymbollayer.h"
Expand Down Expand Up @@ -150,6 +151,8 @@ class TestQgsProcessingAlgs: public QObject

void tinMeshCreation();

void rasterize();

private:

bool imageCheck( const QString &testName, const QString &renderedImage );
Expand Down Expand Up @@ -4830,6 +4833,53 @@ void TestQgsProcessingAlgs::tinMeshCreation()
QVERIFY( qgsDoubleNear( meshLayer.datasetValue( QgsMeshDatasetIndex( 0, 0 ), QgsPointXY( -86.0, 35.0 ) ).scalar(), 1.855, 0.001 ) ) ;
}

void TestQgsProcessingAlgs::rasterize()
{
std::unique_ptr< QgsProcessingAlgorithm > alg( QgsApplication::processingRegistry()->createAlgorithmById( QStringLiteral( "native:rasterize" ) ) );
QVERIFY( alg != nullptr );

QString outputTif = QDir::tempPath() + "/rasterize_output.tif";
if ( QFile::exists( outputTif ) )
QFile::remove( outputTif );

QVariantMap parameters;
parameters.insert( QStringLiteral( "EXTENT" ), QStringLiteral( "-120,-80,15,55" ) );
parameters.insert( QStringLiteral( "TILE_SIZE" ), 320 );
parameters.insert( QStringLiteral( "MAP_UNITS_PER_PIXEL" ), 0.125 );
parameters.insert( QStringLiteral( "OUTPUT" ), outputTif );

// create a temporary project with three layers, but only two are visible
// (to test that the algorithm in the default setup without defined LAYERS or MAP_THEME uses only vsisible
// layers that and in the correct order)
QgsProject project;
QString dataDir( TEST_DATA_DIR ); //defined in CmakeLists.txt
QgsVectorLayer *pointsLayer = new QgsVectorLayer( dataDir + "/points.shp", QStringLiteral( "points" ), QStringLiteral( "ogr" ) );
QgsVectorLayer *linesLayer = new QgsVectorLayer( dataDir + "/lines.shp", QStringLiteral( "lines" ), QStringLiteral( "ogr" ) );
QgsVectorLayer *polygonLayer = new QgsVectorLayer( dataDir + "/polys.shp", QStringLiteral( "polygons" ), QStringLiteral( "ogr" ) );
QVERIFY( pointsLayer->isValid() && linesLayer->isValid() && polygonLayer->isValid() );
project.addMapLayers( QList<QgsMapLayer *>() << pointsLayer << linesLayer << polygonLayer );
QgsLayerTreeLayer *nodePolygons = project.layerTreeRoot()->findLayer( polygonLayer );
QVERIFY( nodePolygons );
nodePolygons->setItemVisibilityChecked( false );

std::unique_ptr< QgsProcessingContext > context = qgis::make_unique< QgsProcessingContext >();
context->setProject( &project );
QgsProcessingFeedback feedback;
QVariantMap results;
bool ok = false;

results = alg->run( parameters, *context, &feedback, &ok );
QVERIFY( ok );
QVERIFY( QFile::exists( outputTif ) );

QgsRenderChecker checker;
checker.setControlPathPrefix( QStringLiteral( "processing_algorithm" ) );
checker.setControlExtension( "tif" );
checker.setControlName( "expected_rasterize" );
checker.setRenderedImage( outputTif );
QVERIFY( checker.compareImages( "rasterize", 500 ) );
}

bool TestQgsProcessingAlgs::imageCheck( const QString &testName, const QString &renderedImage )
{
QgsRenderChecker checker;
Expand Down
Binary file not shown.

0 comments on commit 3387268

Please sign in to comment.