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