Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsalgorithmvectorize.cpp
3 : : ---------------------
4 : : begin : June, 2018
5 : : copyright : (C) 2018 by Nyall Dawson
6 : : email : nyall dot dawson 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 "qgsalgorithmvectorize.h"
19 : : #include "qgis.h"
20 : : #include "qgsprocessing.h"
21 : :
22 : : ///@cond PRIVATE
23 : :
24 : 0 : QString QgsVectorizeAlgorithmBase::group() const
25 : : {
26 : 0 : return QObject::tr( "Vector creation" );
27 : : }
28 : :
29 : 0 : QString QgsVectorizeAlgorithmBase::groupId() const
30 : : {
31 : 0 : return QStringLiteral( "vectorcreation" );
32 : : }
33 : :
34 : 0 : void QgsVectorizeAlgorithmBase::initAlgorithm( const QVariantMap & )
35 : : {
36 : 0 : addParameter( new QgsProcessingParameterRasterLayer( QStringLiteral( "INPUT_RASTER" ),
37 : 0 : QObject::tr( "Raster layer" ) ) );
38 : 0 : addParameter( new QgsProcessingParameterBand( QStringLiteral( "RASTER_BAND" ),
39 : 0 : QObject::tr( "Band number" ), 1, QStringLiteral( "INPUT_RASTER" ) ) );
40 : 0 : addParameter( new QgsProcessingParameterString( QStringLiteral( "FIELD_NAME" ),
41 : 0 : QObject::tr( "Field name" ), QStringLiteral( "VALUE" ) ) );
42 : :
43 : 0 : addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), outputName(), outputType() ) );
44 : 0 : }
45 : :
46 : 0 : bool QgsVectorizeAlgorithmBase::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * )
47 : : {
48 : 0 : QgsRasterLayer *layer = parameterAsRasterLayer( parameters, QStringLiteral( "INPUT_RASTER" ), context );
49 : :
50 : 0 : if ( !layer )
51 : 0 : throw QgsProcessingException( invalidRasterError( parameters, QStringLiteral( "INPUT_RASTER" ) ) );
52 : :
53 : 0 : mBand = parameterAsInt( parameters, QStringLiteral( "RASTER_BAND" ), context );
54 : 0 : if ( mBand < 1 || mBand > layer->bandCount() )
55 : 0 : throw QgsProcessingException( QObject::tr( "Invalid band number for RASTER_BAND (%1): Valid values for input raster are 1 to %2" ).arg( mBand )
56 : 0 : .arg( layer->bandCount() ) );
57 : :
58 : 0 : mInterface.reset( layer->dataProvider()->clone() );
59 : 0 : mExtent = layer->extent();
60 : 0 : mCrs = layer->crs();
61 : 0 : mRasterUnitsPerPixelX = std::abs( layer->rasterUnitsPerPixelX() );
62 : 0 : mRasterUnitsPerPixelY = std::abs( layer->rasterUnitsPerPixelY() );
63 : 0 : mNbCellsXProvider = mInterface->xSize();
64 : 0 : mNbCellsYProvider = mInterface->ySize();
65 : 0 : return true;
66 : 0 : }
67 : :
68 : 0 : QVariantMap QgsVectorizeAlgorithmBase::processAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
69 : : {
70 : 0 : const QString fieldName = parameterAsString( parameters, QStringLiteral( "FIELD_NAME" ), context );
71 : 0 : QgsFields fields;
72 : 0 : fields.append( QgsField( fieldName, QVariant::Double, QString(), 20, 8 ) );
73 : :
74 : 0 : QString dest;
75 : 0 : std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, fields, sinkType(), mCrs ) );
76 : 0 : if ( !sink )
77 : 0 : throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
78 : :
79 : :
80 : 0 : int maxWidth = QgsRasterIterator::DEFAULT_MAXIMUM_TILE_WIDTH;
81 : 0 : int maxHeight = QgsRasterIterator::DEFAULT_MAXIMUM_TILE_HEIGHT;
82 : :
83 : 0 : QgsRasterIterator iter( mInterface.get() );
84 : 0 : iter.startRasterRead( mBand, mNbCellsXProvider, mNbCellsYProvider, mExtent );
85 : :
86 : 0 : int nbBlocksWidth = static_cast< int >( std::ceil( 1.0 * mNbCellsXProvider / maxWidth ) );
87 : 0 : int nbBlocksHeight = static_cast< int >( std::ceil( 1.0 * mNbCellsYProvider / maxHeight ) );
88 : 0 : int nbBlocks = nbBlocksWidth * nbBlocksHeight;
89 : :
90 : 0 : int iterLeft = 0;
91 : 0 : int iterTop = 0;
92 : 0 : int iterCols = 0;
93 : 0 : int iterRows = 0;
94 : 0 : std::unique_ptr< QgsRasterBlock > rasterBlock;
95 : 0 : QgsRectangle blockExtent;
96 : 0 : bool isNoData = false;
97 : 0 : while ( iter.readNextRasterPart( mBand, iterCols, iterRows, rasterBlock, iterLeft, iterTop, &blockExtent ) )
98 : : {
99 : 0 : if ( feedback )
100 : 0 : feedback->setProgress( 100 * ( ( iterTop / maxHeight * nbBlocksWidth ) + iterLeft / maxWidth ) / nbBlocks );
101 : 0 : if ( feedback && feedback->isCanceled() )
102 : 0 : break;
103 : :
104 : 0 : double currentY = blockExtent.yMaximum() - 0.5 * mRasterUnitsPerPixelY;
105 : :
106 : 0 : for ( int row = 0; row < iterRows; row++ )
107 : : {
108 : 0 : if ( feedback && feedback->isCanceled() )
109 : 0 : break;
110 : :
111 : 0 : double currentX = blockExtent.xMinimum() + 0.5 * mRasterUnitsPerPixelX;
112 : :
113 : 0 : for ( int column = 0; column < iterCols; column++ )
114 : : {
115 : 0 : const double value = rasterBlock->valueAndNoData( row, column, isNoData );
116 : 0 : if ( !isNoData )
117 : : {
118 : 0 : QgsGeometry pixelRectGeometry = createGeometryForPixel( currentX, currentY, mRasterUnitsPerPixelX, mRasterUnitsPerPixelY );
119 : :
120 : 0 : QgsFeature f;
121 : 0 : f.setGeometry( pixelRectGeometry );
122 : 0 : f.setAttributes( QgsAttributes() << value );
123 : 0 : sink->addFeature( f, QgsFeatureSink::FastInsert );
124 : 0 : }
125 : 0 : currentX += mRasterUnitsPerPixelX;
126 : 0 : }
127 : 0 : currentY -= mRasterUnitsPerPixelY;
128 : 0 : }
129 : : }
130 : :
131 : 0 : QVariantMap outputs;
132 : 0 : outputs.insert( QStringLiteral( "OUTPUT" ), dest );
133 : 0 : return outputs;
134 : 0 : }
135 : :
136 : : //
137 : : // QgsRasterPixelsToPolygonsAlgorithm
138 : : //
139 : :
140 : 0 : QString QgsRasterPixelsToPolygonsAlgorithm::name() const
141 : : {
142 : 0 : return QStringLiteral( "pixelstopolygons" );
143 : : }
144 : :
145 : 0 : QString QgsRasterPixelsToPolygonsAlgorithm::displayName() const
146 : : {
147 : 0 : return QObject::tr( "Raster pixels to polygons" );
148 : : }
149 : :
150 : 0 : QStringList QgsRasterPixelsToPolygonsAlgorithm::tags() const
151 : : {
152 : 0 : return QObject::tr( "vectorize,polygonize,raster,convert,pixels" ).split( ',' );
153 : 0 : }
154 : :
155 : 0 : QString QgsRasterPixelsToPolygonsAlgorithm::shortHelpString() const
156 : : {
157 : 0 : return QObject::tr( "This algorithm converts a raster layer to a vector layer, by creating polygon features "
158 : : "for each individual pixel's extent in the raster layer.\n\n"
159 : : "Any nodata pixels are skipped in the output." );
160 : : }
161 : :
162 : 0 : QString QgsRasterPixelsToPolygonsAlgorithm::shortDescription() const
163 : : {
164 : 0 : return QObject::tr( "Creates a vector layer of polygons corresponding to each pixel in a raster layer." );
165 : : }
166 : :
167 : 0 : QgsRasterPixelsToPolygonsAlgorithm *QgsRasterPixelsToPolygonsAlgorithm::createInstance() const
168 : : {
169 : 0 : return new QgsRasterPixelsToPolygonsAlgorithm();
170 : 0 : }
171 : :
172 : 0 : QString QgsRasterPixelsToPolygonsAlgorithm::outputName() const
173 : : {
174 : 0 : return QObject::tr( "Vector polygons" );
175 : : }
176 : :
177 : 0 : QgsProcessing::SourceType QgsRasterPixelsToPolygonsAlgorithm::outputType() const
178 : : {
179 : 0 : return QgsProcessing::TypeVectorPolygon;
180 : : }
181 : :
182 : 0 : QgsWkbTypes::Type QgsRasterPixelsToPolygonsAlgorithm::sinkType() const
183 : : {
184 : 0 : return QgsWkbTypes::Polygon;
185 : : }
186 : :
187 : 0 : QgsGeometry QgsRasterPixelsToPolygonsAlgorithm::createGeometryForPixel( double centerX, double centerY, double pixelWidthX, double pixelWidthY ) const
188 : : {
189 : 0 : const double hCellSizeX = pixelWidthX / 2.0;
190 : 0 : const double hCellSizeY = pixelWidthY / 2.0;
191 : 0 : return QgsGeometry::fromRect( QgsRectangle( centerX - hCellSizeX, centerY - hCellSizeY, centerX + hCellSizeX, centerY + hCellSizeY ) );
192 : : }
193 : :
194 : :
195 : : //
196 : : // QgsRasterPixelsToPointsAlgorithm
197 : : //
198 : :
199 : 0 : QString QgsRasterPixelsToPointsAlgorithm::name() const
200 : : {
201 : 0 : return QStringLiteral( "pixelstopoints" );
202 : : }
203 : :
204 : 0 : QString QgsRasterPixelsToPointsAlgorithm::displayName() const
205 : : {
206 : 0 : return QObject::tr( "Raster pixels to points" );
207 : : }
208 : :
209 : 0 : QStringList QgsRasterPixelsToPointsAlgorithm::tags() const
210 : : {
211 : 0 : return QObject::tr( "vectorize,polygonize,raster,convert,pixels,centers" ).split( ',' );
212 : 0 : }
213 : :
214 : 0 : QString QgsRasterPixelsToPointsAlgorithm::shortHelpString() const
215 : : {
216 : 0 : return QObject::tr( "This algorithm converts a raster layer to a vector layer, by creating point features "
217 : : "for each individual pixel's center in the raster layer.\n\n"
218 : : "Any nodata pixels are skipped in the output." );
219 : : }
220 : :
221 : 0 : QString QgsRasterPixelsToPointsAlgorithm::shortDescription() const
222 : : {
223 : 0 : return QObject::tr( "Creates a vector layer of points corresponding to each pixel in a raster layer." );
224 : : }
225 : :
226 : 0 : QgsRasterPixelsToPointsAlgorithm *QgsRasterPixelsToPointsAlgorithm::createInstance() const
227 : : {
228 : 0 : return new QgsRasterPixelsToPointsAlgorithm();
229 : 0 : }
230 : :
231 : 0 : QString QgsRasterPixelsToPointsAlgorithm::outputName() const
232 : : {
233 : 0 : return QObject::tr( "Vector points" );
234 : : }
235 : :
236 : 0 : QgsProcessing::SourceType QgsRasterPixelsToPointsAlgorithm::outputType() const
237 : : {
238 : 0 : return QgsProcessing::TypeVectorPoint;
239 : : }
240 : :
241 : 0 : QgsWkbTypes::Type QgsRasterPixelsToPointsAlgorithm::sinkType() const
242 : : {
243 : 0 : return QgsWkbTypes::Point;
244 : : }
245 : :
246 : 0 : QgsGeometry QgsRasterPixelsToPointsAlgorithm::createGeometryForPixel( double centerX, double centerY, double, double ) const
247 : : {
248 : 0 : return QgsGeometry( new QgsPoint( centerX, centerY ) );
249 : 0 : }
250 : :
251 : : ///@endcond
252 : :
253 : :
|