QGIS API Documentation 3.34.0-Prizren (ffbdd678812)
Loading...
Searching...
No Matches
qgsalgorithmsumlinelength.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmsumlinelength.cpp
3 ---------------------
4 begin : November 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
19#include "qgsprocessing.h"
20#include "qgsgeometryengine.h"
21#include "qgsvectorlayer.h"
22#include "qgsapplication.h"
23
25
26QString QgsSumLineLengthAlgorithm::name() const
27{
28 return QStringLiteral( "sumlinelengths" );
29}
30
31QString QgsSumLineLengthAlgorithm::displayName() const
32{
33 return QObject::tr( "Sum line lengths" );
34}
35
36QStringList QgsSumLineLengthAlgorithm::tags() const
37{
38 return QObject::tr( "line,intersects,intersecting,sum,length,count" ).split( ',' );
39}
40
41QString QgsSumLineLengthAlgorithm::svgIconPath() const
42{
43 return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmSumLengthLines.svg" ) );
44}
45
46QIcon QgsSumLineLengthAlgorithm::icon() const
47{
48 return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmSumLengthLines.svg" ) );
49}
50
51QString QgsSumLineLengthAlgorithm::group() const
52{
53 return QObject::tr( "Vector analysis" );
54}
55
56QString QgsSumLineLengthAlgorithm::groupId() const
57{
58 return QStringLiteral( "vectoranalysis" );
59}
60
61QString QgsSumLineLengthAlgorithm::shortHelpString() const
62{
63 return QObject::tr( "This algorithm takes a polygon layer and a line layer and "
64 "measures the total length of lines and the total number of "
65 "them that cross each polygon.\n\n"
66 "The resulting layer has the same features as the input polygon "
67 "layer, but with two additional attributes containing the length "
68 "and count of the lines across each polygon. The names of these "
69 "two fields can be configured in the algorithm parameters." );
70}
71
72QgsSumLineLengthAlgorithm *QgsSumLineLengthAlgorithm::createInstance() const
73{
74 return new QgsSumLineLengthAlgorithm();
75}
76
77QList<int> QgsSumLineLengthAlgorithm::inputLayerTypes() const
78{
79 return QList< int >() << QgsProcessing::TypeVectorPolygon;
80}
81
82QgsProcessing::SourceType QgsSumLineLengthAlgorithm::outputLayerType() const
83{
85}
86
87QgsCoordinateReferenceSystem QgsSumLineLengthAlgorithm::outputCrs( const QgsCoordinateReferenceSystem &inputCrs ) const
88{
89 mCrs = inputCrs;
90 mDa.setSourceCrs( mCrs, mTransformContext );
91 return mCrs;
92}
93
94QString QgsSumLineLengthAlgorithm::inputParameterName() const
95{
96 return QStringLiteral( "POLYGONS" );
97}
98
99QString QgsSumLineLengthAlgorithm::inputParameterDescription() const
100{
101 return QObject::tr( "Polygons" );
102}
103
104QString QgsSumLineLengthAlgorithm::outputName() const
105{
106 return QObject::tr( "Line length" );
107}
108
109void QgsSumLineLengthAlgorithm::initParameters( const QVariantMap &configuration )
110{
111 mIsInPlace = configuration.value( QStringLiteral( "IN_PLACE" ) ).toBool();
112
113 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "LINES" ),
114 QObject::tr( "Lines" ), QList< int > () << QgsProcessing::TypeVectorLine ) );
115 if ( mIsInPlace )
116 {
117 addParameter( new QgsProcessingParameterField( QStringLiteral( "LEN_FIELD" ),
118 QObject::tr( "Lines length field name" ), QStringLiteral( "LENGTH" ), inputParameterName(), QgsProcessingParameterField::Any, false, true ) );
119 addParameter( new QgsProcessingParameterField( QStringLiteral( "COUNT_FIELD" ),
120 QObject::tr( "Lines count field name" ), QStringLiteral( "COUNT" ), inputParameterName(), QgsProcessingParameterField::Any, false, true ) );
121 }
122 else
123 {
124 addParameter( new QgsProcessingParameterString( QStringLiteral( "LEN_FIELD" ),
125 QObject::tr( "Lines length field name" ), QStringLiteral( "LENGTH" ) ) );
126 addParameter( new QgsProcessingParameterString( QStringLiteral( "COUNT_FIELD" ),
127 QObject::tr( "Lines count field name" ), QStringLiteral( "COUNT" ) ) );
128 }
129}
130
131bool QgsSumLineLengthAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
132{
133 mLengthFieldName = parameterAsString( parameters, QStringLiteral( "LEN_FIELD" ), context );
134 mCountFieldName = parameterAsString( parameters, QStringLiteral( "COUNT_FIELD" ), context );
135
136 mLinesSource.reset( parameterAsSource( parameters, QStringLiteral( "LINES" ), context ) );
137 if ( !mLinesSource )
138 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "LINES" ) ) );
139
140 if ( mLinesSource->hasSpatialIndex() == QgsFeatureSource::SpatialIndexNotPresent )
141 feedback->pushWarning( QObject::tr( "No spatial index exists for lines layer, performance will be severely degraded" ) );
142
143 mDa.setEllipsoid( context.ellipsoid() );
144 mTransformContext = context.transformContext();
145
146 return true;
147}
148
149QgsFields QgsSumLineLengthAlgorithm::outputFields( const QgsFields &inputFields ) const
150{
151 if ( mIsInPlace )
152 {
153 mLengthFieldIndex = mLengthFieldName.isEmpty() ? -1 : inputFields.lookupField( mLengthFieldName );
154 mCountFieldIndex = mCountFieldName.isEmpty() ? -1 : inputFields.lookupField( mCountFieldName );
155 return inputFields;
156 }
157 else
158 {
159 QgsFields outFields = inputFields;
160 mLengthFieldIndex = inputFields.lookupField( mLengthFieldName );
161 if ( mLengthFieldIndex < 0 )
162 outFields.append( QgsField( mLengthFieldName, QVariant::Double ) );
163
164 mCountFieldIndex = inputFields.lookupField( mCountFieldName );
165 if ( mCountFieldIndex < 0 )
166 outFields.append( QgsField( mCountFieldName, QVariant::Double ) );
167
168 mFields = outFields;
169 return outFields;
170 }
171}
172
173bool QgsSumLineLengthAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
174{
175 if ( const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
176 {
177 return vl->geometryType() == Qgis::GeometryType::Polygon;
178 }
179 return false;
180}
181
182QgsFeatureList QgsSumLineLengthAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
183{
184 QgsFeature outputFeature = feature;
185 if ( !feature.hasGeometry() )
186 {
187 QgsAttributes attrs = feature.attributes();
188 if ( !mIsInPlace && mLengthFieldIndex < 0 )
189 attrs.append( 0 );
190 else if ( mLengthFieldIndex >= 0 )
191 attrs[mLengthFieldIndex] = 0;
192
193 if ( !mIsInPlace && mCountFieldIndex < 0 )
194 attrs.append( 0 );
195 else if ( mCountFieldIndex >= 0 )
196 attrs[mCountFieldIndex] = 0;
197
198 outputFeature.setAttributes( attrs );
199 return QList< QgsFeature > () << outputFeature;
200 }
201 else
202 {
203 const QgsGeometry polyGeom = feature.geometry();
204 std::unique_ptr< QgsGeometryEngine > engine( QgsGeometry::createGeometryEngine( polyGeom.constGet() ) );
205 engine->prepareGeometry();
206
208 req.setSubsetOfAttributes( QList< int >() );
209 QgsFeatureIterator it = mLinesSource->getFeatures( req );
210
211 double count = 0;
212 double length = 0;
213
214 QgsFeature lineFeature;
215 while ( it.nextFeature( lineFeature ) )
216 {
217 if ( feedback->isCanceled() )
218 break;
219
220 if ( engine->intersects( lineFeature.geometry().constGet() ) )
221 {
222 const QgsGeometry outGeom = polyGeom.intersection( lineFeature.geometry() );
223 length += mDa.measureLength( outGeom );
224 count++;
225 }
226 }
227
228 QgsAttributes attrs = feature.attributes();
229 if ( !mIsInPlace && mLengthFieldIndex < 0 )
230 attrs.append( length );
231 else if ( mLengthFieldIndex >= 0 )
232 attrs[mLengthFieldIndex] = length;
233
234 if ( !mIsInPlace && mCountFieldIndex < 0 )
235 attrs.append( count );
236 else if ( mCountFieldIndex >= 0 )
237 attrs[mCountFieldIndex] = count;
238
239 outputFeature.setAttributes( attrs );
240 return QList< QgsFeature >() << outputFeature;
241 }
242}
243
@ Polygon
Polygons.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
A vector of attributes.
This class represents a coordinate reference system (CRS).
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
@ SpatialIndexNotPresent
No spatial index exists for the source.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:56
QgsAttributes attributes
Definition qgsfeature.h:65
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
QgsGeometry geometry
Definition qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:54
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
Container of fields for a vector layer.
Definition qgsfields.h:45
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Appends a field. The field must have unique name, otherwise it is rejected (returns false)
Definition qgsfields.cpp:59
bool isEmpty() const
Checks whether the container is empty.
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters &parameters=QgsGeometryParameters()) const
Returns a geometry representing the points shared by this geometry and other.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Base class for all map layer types.
Definition qgsmaplayer.h:74
Contains information about the context in which a processing algorithm is executed.
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
An input feature source (such as vector layers) parameter for processing algorithms.
A vector layer or feature source field parameter for processing algorithms.
A string parameter for processing algorithms.
SourceType
Data source types enum.
@ TypeVectorLine
Vector line layers.
@ TypeVectorPolygon
Vector polygon layers.
Represents a vector layer which manages a vector based data sets.
QList< QgsFeature > QgsFeatureList
Definition qgsfeature.h:920