Skip to content

Commit

Permalink
[processing] port extract layer extent to C++
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed Dec 9, 2019
1 parent 9615306 commit e0136ff
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 169 deletions.
3 changes: 0 additions & 3 deletions python/plugins/processing/algs/help/qgis.yaml
Expand Up @@ -296,9 +296,6 @@ qgis:polygoncentroids: >

NOTE: This algorithm is deprecated and the generic "centroids" algorithm (which works for line and multi geometry layers) should be used instead.

qgis:polygonfromlayerextent: >
This algorithm takes a map layer and generates a new vector layer with the minimum bounding box (rectangle polygon with N-S orientation) that covers the input layer. Optionally, the extent can be enlarged to a rounded value.

qgis:polygonize: >
This algorithm takes a lines layer and creates a polygon layer, with polygons generated from the lines in the input layer.

Expand Down
160 changes: 0 additions & 160 deletions python/plugins/processing/algs/qgis/ExtentFromLayer.py

This file was deleted.

2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -43,7 +43,6 @@
from .EliminateSelection import EliminateSelection
from .ExecuteSQL import ExecuteSQL
from .ExportGeometryInfo import ExportGeometryInfo
from .ExtentFromLayer import ExtentFromLayer
from .ExtractSpecificVertices import ExtractSpecificVertices
from .FieldPyculator import FieldsPyculator
from .FieldsCalculator import FieldsCalculator
Expand Down Expand Up @@ -137,7 +136,6 @@ def getAlgs(self):
EliminateSelection(),
ExecuteSQL(),
ExportGeometryInfo(),
ExtentFromLayer(),
ExtractSpecificVertices(),
FieldsCalculator(),
FieldsMapper(),
Expand Down
Expand Up @@ -1821,7 +1821,7 @@ tests:
name: expected/multipoint_delaunay.gml
type: vector

- algorithm: qgis:polygonfromlayerextent
- algorithm: native:polygonfromlayerextent
name: Polygon from layer extent rounded to 0
params:
BY_FEATURE: false
Expand All @@ -1834,7 +1834,7 @@ tests:
name: expected/polygon_from_extent.gml
type: vector

- algorithm: qgis:polygonfromlayerextent
- algorithm: native:polygonfromlayerextent
name: Polygon from layer extent rounded to 2
params:
BY_FEATURE: false
Expand Down
Expand Up @@ -293,7 +293,7 @@ tests:
name: expected/projection_candidates.gml
type: vector

- algorithm: qgis:polygonfromlayerextent
- algorithm: native:polygonfromlayerextent
name: Standard polygon from layer extent
params:
BY_FEATURE: false
Expand Down Expand Up @@ -809,7 +809,7 @@ tests:
name: expected/execute_sql.gml
type: vector

- algorithm: qgis:polygonfromlayerextent
- algorithm: native:polygonfromlayerextent
name: Polygon from raster extent
params:
INPUT:
Expand Down
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -48,6 +48,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmexplode.cpp
processing/qgsalgorithmexplodehstore.cpp
processing/qgsalgorithmextendlines.cpp
processing/qgsalgorithmextentfromlayer.cpp
processing/qgsalgorithmextenttolayer.cpp
processing/qgsalgorithmextractbinary.cpp
processing/qgsalgorithmextractbyattribute.cpp
Expand Down
147 changes: 147 additions & 0 deletions src/analysis/processing/qgsalgorithmextentfromlayer.cpp
@@ -0,0 +1,147 @@
/***************************************************************************
qgsalgorithmextentfromlayer.cpp
---------------------
begin : November 2019
copyright : (C) 2019 by Alexander Bruy
email : alexander dot bruy at gmail dot com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#include "qgsalgorithmextentfromlayer.h"
#include "qgsapplication.h"
#include "qgsvectorlayer.h"

///@cond PRIVATE

QString QgsExtentFromLayerAlgorithm::name() const
{
return QStringLiteral( "polygonfromlayerextent" );
}

QString QgsExtentFromLayerAlgorithm::displayName() const
{
return QObject::tr( "Extract layer extent" );
}

QStringList QgsExtentFromLayerAlgorithm::tags() const
{
return QObject::tr( "polygon,vector,raster,extent,envelope,bounds,bounding,boundary,layer,round,rounded" ).split( ',' );
}

QString QgsExtentFromLayerAlgorithm::group() const
{
return QObject::tr( "Raster terrain analysis" );
}

QString QgsExtentFromLayerAlgorithm::groupId() const
{
return QStringLiteral( "rasterterrainanalysis" );
}

QString QgsExtentFromLayerAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm takes a map layer and generates a new vector "
"layer with the minimum bounding box (rectangle polygon with "
"N-S orientation) that covers the input layer. Optionally, the "
"extent can be enlarged to a rounded value." );
}

QString QgsExtentFromLayerAlgorithm::svgIconPath() const
{
return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmExtractLayerExtent.svg" ) );
}

QIcon QgsExtentFromLayerAlgorithm::icon() const
{
return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmExtractLayerExtent.svg" ) );
}

QgsExtentFromLayerAlgorithm *QgsExtentFromLayerAlgorithm::createInstance() const
{
return new QgsExtentFromLayerAlgorithm();
}

void QgsExtentFromLayerAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterMapLayer( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );

auto roundParam = qgis::make_unique < QgsProcessingParameterDistance >( QStringLiteral( "ROUND_TO" ), QObject::tr( "Round values to" ), 0, QStringLiteral( "INPUT" ), 0 );
roundParam->setFlags( QgsProcessingParameterDefinition::FlagAdvanced );
addParameter( roundParam.release() );

addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Extent" ), QgsProcessing::TypeVectorPolygon ) );
}

QVariantMap QgsExtentFromLayerAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsMapLayer *layer = parameterAsLayer( parameters, QStringLiteral( "INPUT" ), context );

if ( !layer )
throw QgsProcessingException( QObject::tr( "Invalid input layer" ) );

double roundTo = parameterAsDouble( parameters, QStringLiteral( "ROUND_TO" ), context );

QgsFields fields;
fields.append( QgsField( QStringLiteral( "MINX" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "MINY" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "MAXX" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "MAXY" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "CNTX" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "CNTY" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "AREA" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "PERIM" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "HEIGHT" ), QVariant::Double ) );
fields.append( QgsField( QStringLiteral( "WIDTH" ), QVariant::Double ) );

QString dest;
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Polygon, layer->crs() ) );
if ( !sink )
throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );

if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer * >( layer ) )
{
vl->updateExtents();
}

QgsRectangle rect = layer->extent();

if ( roundTo > 0 )
{
rect.setXMinimum( std::floor( rect.xMinimum() / roundTo ) * roundTo );
rect.setYMinimum( std::floor( rect.yMinimum() / roundTo ) * roundTo );
rect.setXMaximum( std::ceil( rect.xMaximum() / roundTo ) * roundTo );
rect.setYMaximum( std::ceil( rect.yMaximum() / roundTo ) * roundTo );
}

QgsGeometry geom = QgsGeometry::fromRect( rect );

double minX = rect.xMinimum();
double maxX = rect.xMaximum();
double minY = rect.yMinimum();
double maxY = rect.yMaximum();
double height = rect.height();
double width = rect.width();
double cntX = minX + width / 2.0;
double cntY = minY + height / 2.0;
double area = width * height;
double perim = 2 * width + 2 * height;

QgsFeature feat;
feat.setGeometry( geom );
feat.setAttributes( QgsAttributes() << minX << minY << maxX << maxY << cntX << cntY << area << perim << height << width );
sink->addFeature( feat, QgsFeatureSink::FastInsert );

QVariantMap outputs;
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
return outputs;
}

///@endcond

0 comments on commit e0136ff

Please sign in to comment.