Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsalgorithmpixelcentroidsfrompolygons.cpp
3 : : ---------------------
4 : : begin : December 2019
5 : : copyright : (C) 2019 by Alexander Bruy
6 : : email : alexander dot bruy at gmail dot com
7 : : ***************************************************************************/
8 : :
9 : : /***************************************************************************
10 : : * *
11 : : * This program is free software; you can redistribute it and/or modify *
12 : : * it under the terms of the GNU General Public License as published by *
13 : : * the Free Software Foundation; either version 2 of the License, or *
14 : : * (at your option) any later version. *
15 : : * *
16 : : ***************************************************************************/
17 : :
18 : : #include "qgsalgorithmpixelcentroidsfrompolygons.h"
19 : : #include "qgsgeometryengine.h"
20 : : #include "qgsrasteranalysisutils.h"
21 : :
22 : : ///@cond PRIVATE
23 : :
24 : 0 : QString QgsPixelCentroidsFromPolygonsAlgorithm::name() const
25 : : {
26 : 0 : return QStringLiteral( "generatepointspixelcentroidsinsidepolygons" );
27 : : }
28 : :
29 : 0 : QString QgsPixelCentroidsFromPolygonsAlgorithm::displayName() const
30 : : {
31 : 0 : return QObject::tr( "Generate points (pixel centroids) inside polygons" );
32 : : }
33 : :
34 : 0 : QStringList QgsPixelCentroidsFromPolygonsAlgorithm::tags() const
35 : : {
36 : 0 : return QObject::tr( "raster,polygon,centroid,pixel,create" ).split( ',' );
37 : 0 : }
38 : :
39 : 0 : QString QgsPixelCentroidsFromPolygonsAlgorithm::group() const
40 : : {
41 : 0 : return QObject::tr( "Vector creation" );
42 : : }
43 : :
44 : 0 : QString QgsPixelCentroidsFromPolygonsAlgorithm::groupId() const
45 : : {
46 : 0 : return QStringLiteral( "vectorcreation" );
47 : : }
48 : :
49 : 0 : QString QgsPixelCentroidsFromPolygonsAlgorithm::shortHelpString() const
50 : : {
51 : 0 : return QObject::tr( "Generates pixel centroids for the raster area falling inside polygons. Used to generate points "
52 : : "for further raster sampling." );
53 : : }
54 : :
55 : 0 : QgsPixelCentroidsFromPolygonsAlgorithm *QgsPixelCentroidsFromPolygonsAlgorithm::createInstance() const
56 : : {
57 : 0 : return new QgsPixelCentroidsFromPolygonsAlgorithm();
58 : : }
59 : :
60 : 0 : void QgsPixelCentroidsFromPolygonsAlgorithm::initAlgorithm( const QVariantMap & )
61 : : {
62 : 0 : addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT_RASTER" ), QObject::tr( "Raster layer" ) ) );
63 : 0 : addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT_VECTOR" ), QObject::tr( "Vector layer" ), QList< int >() << QgsProcessing::TypeVectorPolygon ) );
64 : :
65 : 0 : addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Pixel centroids" ), QgsProcessing::TypeVectorPoint ) );
66 : 0 : }
67 : :
68 : 0 : QVariantMap QgsPixelCentroidsFromPolygonsAlgorithm::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
69 : : {
70 : 0 : QgsRasterLayer *rasterLayer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT_RASTER" ), context );
71 : :
72 : 0 : if ( !rasterLayer )
73 : 0 : throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT_RASTER" ) ) );
74 : :
75 : 0 : std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT_VECTOR" ), context ) );
76 : 0 : if ( !source )
77 : 0 : throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT_VECTOR" ) ) );
78 : :
79 : 0 : QgsFields fields;
80 : 0 : fields.append( QgsField( QStringLiteral( "id" ), QVariant::LongLong ) );
81 : 0 : fields.append( QgsField( QStringLiteral( "poly_id" ), QVariant::Int ) );
82 : 0 : fields.append( QgsField( QStringLiteral( "point_id" ), QVariant::Int ) );
83 : :
84 : 0 : QString dest;
85 : 0 : std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, QgsWkbTypes::Point, rasterLayer->crs(), QgsFeatureSink::RegeneratePrimaryKey ) );
86 : 0 : if ( !sink )
87 : 0 : throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
88 : :
89 : 0 : double step = source->featureCount() ? 100.0 / source->featureCount() : 1;
90 : 0 : QgsFeatureIterator it = source->getFeatures( QgsFeatureRequest().setDestinationCrs( rasterLayer->crs(), context.transformContext() ).setSubsetOfAttributes( QList< int >() ) );
91 : :
92 : 0 : double xPixel = rasterLayer->rasterUnitsPerPixelX();
93 : 0 : double yPixel = rasterLayer->rasterUnitsPerPixelY();
94 : 0 : QgsRectangle extent = rasterLayer->extent();
95 : :
96 : 0 : QgsFeature feature;
97 : 0 : feature.setFields( fields );
98 : :
99 : 0 : int fid = 0;
100 : 0 : int pointId = 0;
101 : :
102 : 0 : int i = 0;
103 : 0 : QgsFeature f;
104 : 0 : while ( it.nextFeature( f ) )
105 : : {
106 : 0 : if ( feedback->isCanceled() )
107 : : {
108 : 0 : break;
109 : : }
110 : :
111 : 0 : if ( !f.hasGeometry() )
112 : : {
113 : 0 : continue;
114 : : }
115 : :
116 : 0 : QgsRectangle bbox = f.geometry().boundingBox();
117 : 0 : double xMin = bbox.xMinimum();
118 : 0 : double xMax = bbox.xMaximum();
119 : 0 : double yMin = bbox.yMinimum();
120 : 0 : double yMax = bbox.yMaximum();
121 : :
122 : : double x, y;
123 : : int startRow, startColumn;
124 : : int endRow, endColumn;
125 : 0 : QgsRasterAnalysisUtils::mapToPixel( xMin, yMax, extent, xPixel, yPixel, startRow, startColumn );
126 : 0 : QgsRasterAnalysisUtils::mapToPixel( xMax, yMin, extent, xPixel, yPixel, endRow, endColumn );
127 : :
128 : 0 : std::unique_ptr< QgsGeometryEngine > engine( QgsGeometry::createGeometryEngine( f.geometry().constGet() ) );
129 : 0 : engine->prepareGeometry();
130 : :
131 : 0 : for ( int row = startRow; row <= endRow; row++ )
132 : : {
133 : 0 : for ( int col = startColumn; col <= endColumn; col++ )
134 : : {
135 : 0 : if ( feedback->isCanceled() )
136 : : {
137 : 0 : break;
138 : : }
139 : :
140 : 0 : QgsRasterAnalysisUtils::pixelToMap( row, col, extent, xPixel, yPixel, x, y );
141 : 0 : QgsPoint point( x, y );
142 : 0 : QgsGeometry geom( point.clone() );
143 : 0 : if ( engine->contains( geom.constGet() ) )
144 : : {
145 : 0 : feature.setGeometry( geom );
146 : 0 : feature.setAttributes( QgsAttributes() << fid << i << pointId );
147 : 0 : sink->addFeature( feature, QgsFeatureSink::FastInsert );
148 : :
149 : 0 : fid++;
150 : 0 : pointId++;
151 : 0 : }
152 : 0 : }
153 : 0 : }
154 : :
155 : 0 : pointId = 0;
156 : :
157 : 0 : feedback->setProgress( i * step );
158 : 0 : i++;
159 : 0 : }
160 : :
161 : 0 : QVariantMap outputs;
162 : 0 : outputs.insert( QStringLiteral( "OUTPUT" ), dest );
163 : 0 : return outputs;
164 : 0 : }
165 : :
166 : : ///@endcond
|