Skip to content

Commit

Permalink
[processing] port points from polygons algorithm to C++
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy committed Dec 9, 2019
1 parent df3e801 commit 2caf9e6
Show file tree
Hide file tree
Showing 9 changed files with 243 additions and 150 deletions.
147 changes: 0 additions & 147 deletions python/plugins/processing/algs/qgis/PointsFromPolygons.py

This file was deleted.

2 changes: 0 additions & 2 deletions python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py
Expand Up @@ -63,7 +63,6 @@
from .PointDistance import PointDistance
from .PointsDisplacement import PointsDisplacement
from .PointsFromLines import PointsFromLines
from .PointsFromPolygons import PointsFromPolygons
from .PointsToPaths import PointsToPaths
from .PolarPlot import PolarPlot
from .PoleOfInaccessibility import PoleOfInaccessibility
Expand Down Expand Up @@ -153,7 +152,6 @@ def getAlgs(self):
PointDistance(),
PointsDisplacement(),
PointsFromLines(),
PointsFromPolygons(),
PointsToPaths(),
PolarPlot(),
PoleOfInaccessibility(),
Expand Down
Expand Up @@ -730,7 +730,7 @@ tests:
name: expected/displaced_points.gml
type: vector

- algorithm: qgis:generatepointspixelcentroidsinsidepolygons
- algorithm: native:generatepointspixelcentroidsinsidepolygons
name: Pixel centroids inside polygon
params:
INPUT_RASTER:
Expand Down
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -90,6 +90,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmorientedminimumboundingbox.cpp
processing/qgsalgorithmorthogonalize.cpp
processing/qgsalgorithmpackage.cpp
processing/qgsalgorithmpixelcentroidsfrompolygons.cpp
processing/qgsalgorithmarrayoffsetlines.cpp
processing/qgsalgorithmpolygonstolines.cpp
processing/qgsalgorithmpointonsurface.cpp
Expand Down
166 changes: 166 additions & 0 deletions src/analysis/processing/qgsalgorithmpixelcentroidsfrompolygons.cpp
@@ -0,0 +1,166 @@
/***************************************************************************
qgsalgorithmpixelcentroidsfrompolygons.cpp
---------------------
begin : December 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 "qgsalgorithmpixelcentroidsfrompolygons.h"
#include "qgsgeometryengine.h"
#include "qgsrasteranalysisutils.h"

///@cond PRIVATE

QString QgsPixelCentroidsFromPolygonsAlgorithm::name() const
{
return QStringLiteral( "generatepointspixelcentroidsinsidepolygons" );
}

QString QgsPixelCentroidsFromPolygonsAlgorithm::displayName() const
{
return QObject::tr( "Generate points (pixel centroids) inside polygons" );
}

QStringList QgsPixelCentroidsFromPolygonsAlgorithm::tags() const
{
return QObject::tr( "raster,polygon,centroid,pixel,create" ).split( ',' );
}

QString QgsPixelCentroidsFromPolygonsAlgorithm::group() const
{
return QObject::tr( "Vector creation" );
}

QString QgsPixelCentroidsFromPolygonsAlgorithm::groupId() const
{
return QStringLiteral( "vectorcreation" );
}

QString QgsPixelCentroidsFromPolygonsAlgorithm::shortHelpString() const
{
return QObject::tr( "Generates pixel centroids for the raster area falling inside polygons. Used to generate points "
"for further raster sampling." );
}

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

void QgsPixelCentroidsFromPolygonsAlgorithm::initAlgorithm( const QVariantMap & )
{
addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT_RASTER" ), QObject::tr( "Raster layer" ) ) );
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT_VECTOR" ), QObject::tr( "Vector layer" ), QList< int >() << QgsProcessing::TypeVectorPolygon ) );

addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Pixel centroids" ), QgsProcessing::TypeVectorPoint ) );
}

QVariantMap QgsPixelCentroidsFromPolygonsAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
QgsRasterLayer *rasterLayer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT_RASTER" ), context );

if ( !rasterLayer )
throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT_RASTER" ) ) );

std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT_VECTOR" ), context ) );
if ( !source )
throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT_VECTOR" ) ) );

QgsFields fields;
fields.append( QgsField( QStringLiteral( "id" ), QVariant::LongLong ) );
fields.append( QgsField( QStringLiteral( "poly_id" ), QVariant::Int ) );
fields.append( QgsField( QStringLiteral( "point_id" ), QVariant::Int ) );

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

double step = source->featureCount() ? 100.0 / source->featureCount() : 1;
QgsFeatureIterator it = source->getFeatures( QgsFeatureRequest().setDestinationCrs( rasterLayer->crs(), context.transformContext() ).setSubsetOfAttributes( QList< int >() ) );

double xPixel = rasterLayer->rasterUnitsPerPixelX();
double yPixel = rasterLayer->rasterUnitsPerPixelY();
QgsRectangle extent = rasterLayer->extent();

QgsFeature feature;
feature.setFields( fields );

int fid = 0;
int pointId = 0;

int i = 0;
QgsFeature f;
while ( it.nextFeature( f ) )
{
if ( feedback->isCanceled() )
{
break;
}

if ( !f.hasGeometry() )
{
continue;
}

QgsRectangle bbox = f.geometry().boundingBox();
double xMin = bbox.xMinimum();
double xMax = bbox.xMaximum();
double yMin = bbox.yMinimum();
double yMax = bbox.yMaximum();

double x, y;
int startRow, startColumn;
int endRow, endColumn;
QgsRasterAnalysisUtils::mapToPixel( xMin, yMax, extent, xPixel, yPixel, startRow, startColumn );
QgsRasterAnalysisUtils::mapToPixel( xMax, yMin, extent, xPixel, yPixel, endRow, endColumn );

std::unique_ptr< QgsGeometryEngine > engine( QgsGeometry::createGeometryEngine( f.geometry().constGet() ) );
engine->prepareGeometry();

for ( int row = startRow; row <= endRow; row++ )
{
for ( int col = startColumn; col <= endColumn; col++ )
{
if ( feedback->isCanceled() )
{
break;
}

QgsRasterAnalysisUtils::pixelToMap( row, col, extent, xPixel, yPixel, x, y );
QgsPoint point( x, y );
QgsGeometry geom( point.clone() );
if ( engine->contains( geom.constGet() ) )
{
feature.setGeometry( geom );
feature.setAttributes( QgsAttributes() << fid << i << pointId );
sink->addFeature( feature, QgsFeatureSink::FastInsert );

fid++;
pointId++;
}
}
}

pointId = 0;

feedback->setProgress( i * step );
i++;
}

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

///@endcond

0 comments on commit 2caf9e6

Please sign in to comment.