QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 
26 QString QgsSumLineLengthAlgorithm::name() const
27 {
28  return QStringLiteral( "sumlinelengths" );
29 }
30 
31 QString QgsSumLineLengthAlgorithm::displayName() const
32 {
33  return QObject::tr( "Sum line lengths" );
34 }
35 
36 QStringList QgsSumLineLengthAlgorithm::tags() const
37 {
38  return QObject::tr( "line,intersects,intersecting,sum,length,count" ).split( ',' );
39 }
40 
41 QString QgsSumLineLengthAlgorithm::svgIconPath() const
42 {
43  return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmSumLengthLines.svg" ) );
44 }
45 
46 QIcon QgsSumLineLengthAlgorithm::icon() const
47 {
48  return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmSumLengthLines.svg" ) );
49 }
50 
51 QString QgsSumLineLengthAlgorithm::group() const
52 {
53  return QObject::tr( "Vector analysis" );
54 }
55 
56 QString QgsSumLineLengthAlgorithm::groupId() const
57 {
58  return QStringLiteral( "vectoranalysis" );
59 }
60 
61 QString 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 
72 QgsSumLineLengthAlgorithm *QgsSumLineLengthAlgorithm::createInstance() const
73 {
74  return new QgsSumLineLengthAlgorithm();
75 }
76 
77 QList<int> QgsSumLineLengthAlgorithm::inputLayerTypes() const
78 {
79  return QList< int >() << QgsProcessing::TypeVectorPolygon;
80 }
81 
82 QgsProcessing::SourceType QgsSumLineLengthAlgorithm::outputLayerType() const
83 {
85 }
86 
88 {
89  mCrs = inputCrs;
90  mDa.setSourceCrs( mCrs, mTransformContext );
91  return mCrs;
92 }
93 
94 QString QgsSumLineLengthAlgorithm::inputParameterName() const
95 {
96  return QStringLiteral( "POLYGONS" );
97 }
98 
99 QString QgsSumLineLengthAlgorithm::inputParameterDescription() const
100 {
101  return QObject::tr( "Polygons" );
102 }
103 
104 QString QgsSumLineLengthAlgorithm::outputName() const
105 {
106  return QObject::tr( "Line length" );
107 }
108 
109 void 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 
131 bool 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 
149 QgsFields 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 
173 bool QgsSumLineLengthAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
174 {
175  if ( const QgsVectorLayer *vl = qobject_cast< const QgsVectorLayer * >( layer ) )
176  {
177  return vl->geometryType() == QgsWkbTypes::PolygonGeometry;
178  }
179  return false;
180 }
181 
182 QgsFeatureList 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 
outputCrs
const QgsCoordinateReferenceSystem & outputCrs
Definition: qgswfsgetfeature.cpp:115
QgsFields::isEmpty
bool isEmpty() const
Checks whether the container is empty.
Definition: qgsfields.cpp:128
QgsProcessingFeedback
Base class for providing feedback from a processing algorithm.
Definition: qgsprocessingfeedback.h:37
QgsFeatureSource::SpatialIndexNotPresent
@ SpatialIndexNotPresent
No spatial index exists for the source.
Definition: qgsfeaturesource.h:190
QgsProcessing::TypeVectorPolygon
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:51
QgsFields
Container of fields for a vector layer.
Definition: qgsfields.h:44
QgsFeature::geometry
QgsGeometry geometry
Definition: qgsfeature.h:71
QgsFeedback::isCanceled
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:67
qgsalgorithmsumlinelength.h
QgsProcessing::TypeVectorLine
@ TypeVectorLine
Vector line layers.
Definition: qgsprocessing.h:50
QgsProcessingParameterFeatureSource
An input feature source (such as vector layers) parameter for processing algorithms.
Definition: qgsprocessingparameters.h:3057
QgsFeatureRequest::setSubsetOfAttributes
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
Definition: qgsfeaturerequest.cpp:228
QgsFields::append
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
QgsApplication::iconPath
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
Definition: qgsapplication.cpp:682
QgsWkbTypes::PolygonGeometry
@ PolygonGeometry
Definition: qgswkbtypes.h:144
QgsGeometry::intersection
QgsGeometry intersection(const QgsGeometry &geometry) const
Returns a geometry representing the points shared by this geometry and other.
Definition: qgsgeometry.cpp:2616
qgsapplication.h
QgsFeatureRequest::setFilterRect
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
Definition: qgsfeaturerequest.cpp:101
QgsFeatureRequest
This class wraps a request for features to a vector layer (or directly its vector data provider).
Definition: qgsfeaturerequest.h:83
qgsgeometryengine.h
QgsProcessingContext
Contains information about the context in which a processing algorithm is executed.
Definition: qgsprocessingcontext.h:46
QgsProcessingContext::ellipsoid
QString ellipsoid() const
Returns the ellipsoid to use for distance and area calculations.
Definition: qgsprocessingcontext.cpp:185
QgsProcessingParameterString
A string parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2647
QgsFeatureList
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:882
QgsProcessingContext::transformContext
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
Definition: qgsprocessingcontext.h:165
QgsGeometry::constGet
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Definition: qgsgeometry.cpp:136
QgsFeature::attributes
QgsAttributes attributes
Definition: qgsfeature.h:69
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
qgsvectorlayer.h
QgsGeometry::createGeometryEngine
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
Definition: qgsgeometry.cpp:3972
QgsFeatureIterator::nextFeature
bool nextFeature(QgsFeature &f)
Definition: qgsfeatureiterator.h:399
qgsprocessing.h
QgsGeometry
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:391
QgsFeature::hasGeometry
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
QgsMapLayer
Base class for all map layer types. This is the base class for all map layer types (vector,...
Definition: qgsmaplayer.h:72
QgsGeometry::boundingBox
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Definition: qgsgeometry.cpp:1080
QgsAttributes
A vector of attributes. Mostly equal to QVector<QVariant>.
Definition: qgsattributes.h:57
QgsFeature
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition: qgsfeature.h:55
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Definition: qgsapplication.cpp:693
QgsFeatureRequest::setDestinationCrs
QgsFeatureRequest & setDestinationCrs(const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context)
Sets the destination crs for feature's geometries.
Definition: qgsfeaturerequest.cpp:301
QgsFeature::setAttributes
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
QgsFields::lookupField
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Definition: qgsfields.cpp:349
QgsProcessingParameterField::Any
@ Any
Accepts any field.
Definition: qgsprocessingparameters.h:2947
QgsFeatureIterator
Wrapper for iterator of features from vector data provider or vector layer.
Definition: qgsfeatureiterator.h:289
QgsProcessing::SourceType
SourceType
Data source types enum.
Definition: qgsprocessing.h:45
QgsProcessingException
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
QgsProcessingParameterField
A vector layer or feature source field parameter for processing algorithms.
Definition: qgsprocessingparameters.h:2940
QgsProcessingFeedback::pushWarning
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
Definition: qgsprocessingfeedback.cpp:68
QgsField
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:50