QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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
20#include "qgsapplication.h"
21#include "qgsgeometryengine.h"
22#include "qgsprocessing.h"
23#include "qgsvectorlayer.h"
24
26
27QString QgsSumLineLengthAlgorithm::name() const
28{
29 return QStringLiteral( "sumlinelengths" );
30}
31
32QString QgsSumLineLengthAlgorithm::displayName() const
33{
34 return QObject::tr( "Sum line lengths" );
35}
36
37QStringList QgsSumLineLengthAlgorithm::tags() const
38{
39 return QObject::tr( "line,intersects,intersecting,sum,length,count" ).split( ',' );
40}
41
42QString QgsSumLineLengthAlgorithm::svgIconPath() const
43{
44 return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmSumLengthLines.svg" ) );
45}
46
47QIcon QgsSumLineLengthAlgorithm::icon() const
48{
49 return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmSumLengthLines.svg" ) );
50}
51
52QString QgsSumLineLengthAlgorithm::group() const
53{
54 return QObject::tr( "Vector analysis" );
55}
56
57QString QgsSumLineLengthAlgorithm::groupId() const
58{
59 return QStringLiteral( "vectoranalysis" );
60}
61
62QString QgsSumLineLengthAlgorithm::shortHelpString() const
63{
64 return QObject::tr( "This algorithm takes a polygon layer and a line layer and "
65 "measures the total length of lines and the total number of "
66 "them that cross each polygon.\n\n"
67 "The resulting layer has the same features as the input polygon "
68 "layer, but with two additional attributes containing the length "
69 "and count of the lines across each polygon. The names of these "
70 "two fields can be configured in the algorithm parameters." );
71}
72
73QString QgsSumLineLengthAlgorithm::shortDescription() const
74{
75 return QObject::tr( "Takes a polygon layer and a line layer and "
76 "measures the total length of lines and the total number of "
77 "them that cross each polygon." );
78}
79
80Qgis::ProcessingAlgorithmDocumentationFlags QgsSumLineLengthAlgorithm::documentationFlags() const
81{
83}
84
85QgsSumLineLengthAlgorithm *QgsSumLineLengthAlgorithm::createInstance() const
86{
87 return new QgsSumLineLengthAlgorithm();
88}
89
90QList<int> QgsSumLineLengthAlgorithm::inputLayerTypes() const
91{
92 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPolygon );
93}
94
95Qgis::ProcessingSourceType QgsSumLineLengthAlgorithm::outputLayerType() const
96{
98}
99
100QgsCoordinateReferenceSystem QgsSumLineLengthAlgorithm::outputCrs( const QgsCoordinateReferenceSystem &inputCrs ) const
101{
102 mCrs = inputCrs;
103 mDa.setSourceCrs( mCrs, mTransformContext );
104 return mCrs;
105}
106
107QString QgsSumLineLengthAlgorithm::inputParameterName() const
108{
109 return QStringLiteral( "POLYGONS" );
110}
111
112QString QgsSumLineLengthAlgorithm::inputParameterDescription() const
113{
114 return QObject::tr( "Polygons" );
115}
116
117QString QgsSumLineLengthAlgorithm::outputName() const
118{
119 return QObject::tr( "Line length" );
120}
121
122void QgsSumLineLengthAlgorithm::initParameters( const QVariantMap &configuration )
123{
124 mIsInPlace = configuration.value( QStringLiteral( "IN_PLACE" ) ).toBool();
125
126 addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "LINES" ), QObject::tr( "Lines" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorLine ) ) );
127 if ( mIsInPlace )
128 {
129 addParameter( new QgsProcessingParameterField( QStringLiteral( "LEN_FIELD" ), QObject::tr( "Lines length field name" ), QStringLiteral( "LENGTH" ), inputParameterName(), Qgis::ProcessingFieldParameterDataType::Any, false, true ) );
130 addParameter( new QgsProcessingParameterField( QStringLiteral( "COUNT_FIELD" ), QObject::tr( "Lines count field name" ), QStringLiteral( "COUNT" ), inputParameterName(), Qgis::ProcessingFieldParameterDataType::Any, false, true ) );
131 }
132 else
133 {
134 addParameter( new QgsProcessingParameterString( QStringLiteral( "LEN_FIELD" ), QObject::tr( "Lines length field name" ), QStringLiteral( "LENGTH" ) ) );
135 addParameter( new QgsProcessingParameterString( QStringLiteral( "COUNT_FIELD" ), QObject::tr( "Lines count field name" ), QStringLiteral( "COUNT" ) ) );
136 }
137}
138
139bool QgsSumLineLengthAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
140{
141 mLengthFieldName = parameterAsString( parameters, QStringLiteral( "LEN_FIELD" ), context );
142 mCountFieldName = parameterAsString( parameters, QStringLiteral( "COUNT_FIELD" ), context );
143
144 mLinesSource.reset( parameterAsSource( parameters, QStringLiteral( "LINES" ), context ) );
145 if ( !mLinesSource )
146 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "LINES" ) ) );
147
148 if ( mLinesSource->hasSpatialIndex() == Qgis::SpatialIndexPresence::NotPresent )
149 feedback->pushWarning( QObject::tr( "No spatial index exists for lines layer, performance will be severely degraded" ) );
150
151 mDa.setEllipsoid( context.ellipsoid() );
152 mTransformContext = context.transformContext();
153
154 return true;
155}
156
157QgsFields QgsSumLineLengthAlgorithm::outputFields( const QgsFields &inputFields ) const
158{
159 if ( mIsInPlace )
160 {
161 mLengthFieldIndex = mLengthFieldName.isEmpty() ? -1 : inputFields.lookupField( mLengthFieldName );
162 mCountFieldIndex = mCountFieldName.isEmpty() ? -1 : inputFields.lookupField( mCountFieldName );
163 return inputFields;
164 }
165 else
166 {
167 QgsFields outFields = inputFields;
168 mLengthFieldIndex = inputFields.lookupField( mLengthFieldName );
169 if ( mLengthFieldIndex < 0 )
170 outFields.append( QgsField( mLengthFieldName, QMetaType::Type::Double ) );
171
172 mCountFieldIndex = inputFields.lookupField( mCountFieldName );
173 if ( mCountFieldIndex < 0 )
174 outFields.append( QgsField( mCountFieldName, QMetaType::Type::Double ) );
175
176 mFields = outFields;
177 return outFields;
178 }
179}
180
181bool QgsSumLineLengthAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
182{
183 if ( const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( layer ) )
184 {
185 return vl->geometryType() == Qgis::GeometryType::Polygon;
186 }
187 return false;
188}
189
190QgsFeatureList QgsSumLineLengthAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
191{
192 QgsFeature outputFeature = feature;
193 if ( !feature.hasGeometry() )
194 {
195 QgsAttributes attrs = feature.attributes();
196 if ( !mIsInPlace && mLengthFieldIndex < 0 )
197 attrs.append( 0 );
198 else if ( mLengthFieldIndex >= 0 )
199 attrs[mLengthFieldIndex] = 0;
200
201 if ( !mIsInPlace && mCountFieldIndex < 0 )
202 attrs.append( 0 );
203 else if ( mCountFieldIndex >= 0 )
204 attrs[mCountFieldIndex] = 0;
205
206 outputFeature.setAttributes( attrs );
207 return QList<QgsFeature>() << outputFeature;
208 }
209 else
210 {
211 const QgsGeometry polyGeom = feature.geometry();
212 std::unique_ptr<QgsGeometryEngine> engine( QgsGeometry::createGeometryEngine( polyGeom.constGet() ) );
213 engine->prepareGeometry();
214
216 req.setSubsetOfAttributes( QList<int>() );
217 QgsFeatureIterator it = mLinesSource->getFeatures( req );
218
219 double count = 0;
220 double length = 0;
221
222 QgsFeature lineFeature;
223 while ( it.nextFeature( lineFeature ) )
224 {
225 if ( feedback->isCanceled() )
226 break;
227
228 if ( engine->intersects( lineFeature.geometry().constGet() ) )
229 {
230 const QgsGeometry outGeom = polyGeom.intersection( lineFeature.geometry() );
231 try
232 {
233 length += mDa.measureLength( outGeom );
234 }
235 catch ( QgsCsException & )
236 {
237 throw QgsProcessingException( QObject::tr( "An error occurred while calculating feature length" ) );
238 }
239 count++;
240 }
241 }
242
243 QgsAttributes attrs = feature.attributes();
244 if ( !mIsInPlace && mLengthFieldIndex < 0 )
245 attrs.append( length );
246 else if ( mLengthFieldIndex >= 0 )
247 attrs[mLengthFieldIndex] = length;
248
249 if ( !mIsInPlace && mCountFieldIndex < 0 )
250 attrs.append( count );
251 else if ( mCountFieldIndex >= 0 )
252 attrs[mCountFieldIndex] = count;
253
254 outputFeature.setAttributes( attrs );
255 return QList<QgsFeature>() << outputFeature;
256 }
257}
258
ProcessingSourceType
Processing data source types.
Definition qgis.h:3531
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3536
@ VectorLine
Vector line layers.
Definition qgis.h:3535
@ NotPresent
No spatial index exists for the source.
Definition qgis.h:560
@ Polygon
Polygons.
Definition qgis.h:361
@ RespectsEllipsoid
Algorithm respects the context's ellipsoid settings, and uses ellipsoidal based measurements.
Definition qgis.h:3621
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3630
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.
Represents a coordinate reference system (CRS).
Custom exception class for Coordinate Reference System related exceptions.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
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.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:58
QgsAttributes attributes
Definition qgsfeature.h:67
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
QgsGeometry geometry
Definition qgsfeature.h:69
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:53
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:54
Container of fields for a vector layer.
Definition qgsfields.h:46
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:73
Q_INVOKABLE 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.
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.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Base class for all map layer types.
Definition qgsmaplayer.h:80
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.
Represents a vector layer which manages a vector based dataset.
QList< QgsFeature > QgsFeatureList