QGIS API Documentation 4.3.0-Master (45633be667c)
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(
69 "This algorithm takes a polygon layer and a line layer and "
70 "measures the total length of lines and the total number of "
71 "them that cross each polygon.\n\n"
72 "The resulting layer has the same features as the input polygon "
73 "layer, but with two additional attributes containing the length "
74 "and count of the lines across each polygon. The names of these "
75 "two fields can be configured in the algorithm parameters."
76 );
77}
78
79QString QgsSumLineLengthAlgorithm::shortDescription() const
80{
81 return QObject::tr(
82 "Takes a polygon layer and a line layer and "
83 "measures the total length of lines and the total number of "
84 "them that cross each polygon."
85 );
86}
87
88Qgis::ProcessingAlgorithmDocumentationFlags QgsSumLineLengthAlgorithm::documentationFlags() const
89{
91}
92
93QgsSumLineLengthAlgorithm *QgsSumLineLengthAlgorithm::createInstance() const
94{
95 return new QgsSumLineLengthAlgorithm();
96}
97
98QList<int> QgsSumLineLengthAlgorithm::inputLayerTypes() const
99{
100 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPolygon );
101}
102
103Qgis::ProcessingSourceType QgsSumLineLengthAlgorithm::outputLayerType() const
104{
106}
107
108QgsCoordinateReferenceSystem QgsSumLineLengthAlgorithm::outputCrs( const QgsCoordinateReferenceSystem &inputCrs ) const
109{
110 mCrs = inputCrs;
111 mDa.setSourceCrs( mCrs, mTransformContext );
112 return mCrs;
113}
114
115QString QgsSumLineLengthAlgorithm::inputParameterName() const
116{
117 return u"POLYGONS"_s;
118}
119
120QString QgsSumLineLengthAlgorithm::inputParameterDescription() const
121{
122 return QObject::tr( "Polygons" );
123}
124
125QString QgsSumLineLengthAlgorithm::outputName() const
126{
127 return QObject::tr( "Line length" );
128}
129
130void QgsSumLineLengthAlgorithm::initParameters( const QVariantMap &configuration )
131{
132 mIsInPlace = configuration.value( u"IN_PLACE"_s ).toBool();
133
134 addParameter( new QgsProcessingParameterFeatureSource( u"LINES"_s, QObject::tr( "Lines" ), QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorLine ) ) );
135 if ( mIsInPlace )
136 {
137 addParameter( new QgsProcessingParameterField( u"LEN_FIELD"_s, QObject::tr( "Lines length field name" ), u"LENGTH"_s, inputParameterName(), Qgis::ProcessingFieldParameterDataType::Any, false, true ) );
138 addParameter( new QgsProcessingParameterField( u"COUNT_FIELD"_s, QObject::tr( "Lines count field name" ), u"COUNT"_s, inputParameterName(), Qgis::ProcessingFieldParameterDataType::Any, false, true ) );
139 }
140 else
141 {
142 addParameter( new QgsProcessingParameterString( u"LEN_FIELD"_s, QObject::tr( "Lines length field name" ), u"LENGTH"_s ) );
143 addParameter( new QgsProcessingParameterString( u"COUNT_FIELD"_s, QObject::tr( "Lines count field name" ), u"COUNT"_s ) );
144 }
145}
146
147bool QgsSumLineLengthAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
148{
149 mLengthFieldName = parameterAsString( parameters, u"LEN_FIELD"_s, context );
150 mCountFieldName = parameterAsString( parameters, u"COUNT_FIELD"_s, context );
151
152 mLinesSource.reset( parameterAsSource( parameters, u"LINES"_s, context ) );
153 if ( !mLinesSource )
154 throw QgsProcessingException( invalidSourceError( parameters, u"LINES"_s ) );
155
156 if ( mLinesSource->hasSpatialIndex() == Qgis::SpatialIndexPresence::NotPresent )
157 feedback->pushWarning( QObject::tr( "No spatial index exists for lines layer, performance will be severely degraded" ) );
158
159 mDa.setEllipsoid( context.ellipsoid() );
160 mTransformContext = context.transformContext();
161
162 return true;
163}
164
165QgsFields QgsSumLineLengthAlgorithm::outputFields( const QgsFields &inputFields ) const
166{
167 if ( mIsInPlace )
168 {
169 mLengthFieldIndex = mLengthFieldName.isEmpty() ? -1 : inputFields.lookupField( mLengthFieldName );
170 mCountFieldIndex = mCountFieldName.isEmpty() ? -1 : inputFields.lookupField( mCountFieldName );
171 return inputFields;
172 }
173 else
174 {
175 QgsFields outFields = inputFields;
176 mLengthFieldIndex = inputFields.lookupField( mLengthFieldName );
177 if ( mLengthFieldIndex < 0 )
178 outFields.append( QgsField( mLengthFieldName, QMetaType::Type::Double ) );
179
180 mCountFieldIndex = inputFields.lookupField( mCountFieldName );
181 if ( mCountFieldIndex < 0 )
182 outFields.append( QgsField( mCountFieldName, QMetaType::Type::Double ) );
183
184 mFields = outFields;
185 return outFields;
186 }
187}
188
189bool QgsSumLineLengthAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
190{
191 if ( const QgsVectorLayer *vl = qobject_cast<const QgsVectorLayer *>( layer ) )
192 {
193 return vl->geometryType() == Qgis::GeometryType::Polygon;
194 }
195 return false;
196}
197
198QgsFeatureList QgsSumLineLengthAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
199{
200 QGS_MARK_ALGORITHM_SOURCE
201
202 QgsFeature outputFeature = feature;
203 if ( !feature.hasGeometry() )
204 {
205 QgsAttributes attrs = feature.attributes();
206 if ( !mIsInPlace && mLengthFieldIndex < 0 )
207 attrs.append( 0 );
208 else if ( mLengthFieldIndex >= 0 )
209 attrs[mLengthFieldIndex] = 0;
210
211 if ( !mIsInPlace && mCountFieldIndex < 0 )
212 attrs.append( 0 );
213 else if ( mCountFieldIndex >= 0 )
214 attrs[mCountFieldIndex] = 0;
215
216 outputFeature.setAttributes( attrs );
217 return QList<QgsFeature>() << outputFeature;
218 }
219 else
220 {
221 const QgsGeometry polyGeom = feature.geometry();
222 std::unique_ptr<QgsGeometryEngine> engine( QgsGeometry::createGeometryEngine( polyGeom.constGet() ) );
223 engine->prepareGeometry();
224
226 req.setSubsetOfAttributes( QList<int>() );
227 QgsFeatureIterator it = mLinesSource->getFeatures( req );
228
229 double count = 0;
230 double length = 0;
231
232 QgsFeature lineFeature;
233 while ( it.nextFeature( lineFeature ) )
234 {
235 if ( feedback->isCanceled() )
236 break;
237
238 if ( engine->intersects( lineFeature.geometry().constGet() ) )
239 {
240 const QgsGeometry outGeom = polyGeom.intersection( lineFeature.geometry(), QgsGeometryParameters(), feedback );
241 try
242 {
243 length += mDa.measureLength( outGeom );
244 }
245 catch ( QgsCsException & )
246 {
247 throw QgsProcessingException( QObject::tr( "An error occurred while calculating feature length" ) );
248 }
249 count++;
250 }
251 }
252
253 QgsAttributes attrs = feature.attributes();
254 if ( !mIsInPlace && mLengthFieldIndex < 0 )
255 attrs.append( length );
256 else if ( mLengthFieldIndex >= 0 )
257 attrs[mLengthFieldIndex] = length;
258
259 if ( !mIsInPlace && mCountFieldIndex < 0 )
260 attrs.append( count );
261 else if ( mCountFieldIndex >= 0 )
262 attrs[mCountFieldIndex] = count;
263
264 outputFeature.setAttributes( attrs );
265 return QList<QgsFeature>() << outputFeature;
266 }
267}
268
ProcessingSourceType
Processing data source types.
Definition qgis.h:3749
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3754
@ VectorLine
Vector line layers.
Definition qgis.h:3753
@ NotPresent
No spatial index exists for the source.
Definition qgis.h:601
@ Polygon
Polygons.
Definition qgis.h:382
@ RespectsEllipsoid
Algorithm respects the context's ellipsoid settings, and uses ellipsoidal based measurements.
Definition qgis.h:3840
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3849
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:64
QgsGeometry geometry
Definition qgsfeature.h:66
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:56
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
Container of fields for a vector layer.
Definition qgsfields.h:45
bool append(const QgsField &field, Qgis::FieldOrigin origin=Qgis::FieldOrigin::Provider, int originIndex=-1)
Appends a field.
Definition qgsfields.cpp:75
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Encapsulates parameters under which a geometry operation is performed.
A geometry is the spatial representation of a feature.
QgsGeometry intersection(const QgsGeometry &geometry, const QgsGeometryParameters &parameters=QgsGeometryParameters(), QgsFeedback *feedback=nullptr) const
Returns a geometry representing the points shared by this geometry and other.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
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