QGIS API Documentation  3.8.0-Zanzibar (11aff65)
qgsalgorithmpointsalonggeometry.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmpointsalonggeometry.cpp
3  ---------------------
4  begin : June 2019
5  copyright : (C) 2019 by Nyall Dawson
6  email : nyall dot dawson 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 "qgsgeometrycollection.h"
20 #include "qgscurve.h"
21 #include "qgsapplication.h"
22 
24 
25 QString QgsPointsAlongGeometryAlgorithm::name() const
26 {
27  return QStringLiteral( "pointsalonglines" );
28 }
29 
30 QString QgsPointsAlongGeometryAlgorithm::displayName() const
31 {
32  return QObject::tr( "Points along geometry" );
33 }
34 
35 QStringList QgsPointsAlongGeometryAlgorithm::tags() const
36 {
37  return QObject::tr( "create,interpolate,points,lines,regular,distance,by" ).split( ',' );
38 }
39 
40 QString QgsPointsAlongGeometryAlgorithm::group() const
41 {
42  return QObject::tr( "Vector geometry" );
43 }
44 
45 QString QgsPointsAlongGeometryAlgorithm::groupId() const
46 {
47  return QStringLiteral( "vectorgeometry" );
48 }
49 
50 QString QgsPointsAlongGeometryAlgorithm::outputName() const
51 {
52  return QObject::tr( "Interpolated points" );
53 }
54 
55 QString QgsPointsAlongGeometryAlgorithm::shortHelpString() const
56 {
57  return QObject::tr( "This algorithm creates a points layer, with points distributed along the lines of an "
58  "input vector layer. The distance between points (measured along the line) is defined as a parameter.\n\n"
59  "Start and end offset distances can be defined, so the first and last point will not fall exactly on the line's "
60  "first and last nodes. These start and end offsets are defined as distances, measured along the line from the first and last "
61  "nodes of the lines." );
62 }
63 
64 QString QgsPointsAlongGeometryAlgorithm::shortDescription() const
65 {
66  return QObject::tr( "Creates regularly spaced points along line features." );
67 }
68 
69 QList<int> QgsPointsAlongGeometryAlgorithm::inputLayerTypes() const
70 {
72 }
73 
74 QgsProcessing::SourceType QgsPointsAlongGeometryAlgorithm::outputLayerType() const
75 {
77 }
78 
79 QgsWkbTypes::Type QgsPointsAlongGeometryAlgorithm::outputWkbType( QgsWkbTypes::Type inputType ) const
80 {
82  if ( QgsWkbTypes::hasZ( inputType ) )
83  out = QgsWkbTypes::addZ( out );
84  if ( QgsWkbTypes::hasM( inputType ) )
85  out = QgsWkbTypes::addM( out );
86  return out;
87 }
88 
89 QgsFields QgsPointsAlongGeometryAlgorithm::outputFields( const QgsFields &inputFields ) const
90 {
91  QgsFields output = inputFields;
92  output.append( QgsField( QStringLiteral( "distance" ), QVariant::Double ) );
93  output.append( QgsField( QStringLiteral( "angle" ), QVariant::Double ) );
94  return output;
95 }
96 
97 QgsPointsAlongGeometryAlgorithm *QgsPointsAlongGeometryAlgorithm::createInstance() const
98 {
99  return new QgsPointsAlongGeometryAlgorithm();
100 }
101 
102 void QgsPointsAlongGeometryAlgorithm::initParameters( const QVariantMap & )
103 {
104  std::unique_ptr< QgsProcessingParameterDistance> distance = qgis::make_unique< QgsProcessingParameterDistance >( QStringLiteral( "DISTANCE" ),
105  QObject::tr( "Distance" ), 1.0, QStringLiteral( "INPUT" ), false, 0 );
106  distance->setIsDynamic( true );
107  distance->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance" ), QgsPropertyDefinition::DoublePositive ) );
108  distance->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
109  addParameter( distance.release() );
110 
111  std::unique_ptr< QgsProcessingParameterDistance> startOffset = qgis::make_unique< QgsProcessingParameterDistance >( QStringLiteral( "START_OFFSET" ),
112  QObject::tr( "Start offset" ), 0.0, QStringLiteral( "INPUT" ), false, 0 );
113  startOffset->setIsDynamic( true );
114  startOffset->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "START_OFFSET" ), QObject::tr( "Start offset" ), QgsPropertyDefinition::DoublePositive ) );
115  startOffset->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
116  addParameter( startOffset.release() );
117 
118  std::unique_ptr< QgsProcessingParameterDistance> endOffset = qgis::make_unique< QgsProcessingParameterDistance >( QStringLiteral( "END_OFFSET" ),
119  QObject::tr( "End offset" ), 0.0, QStringLiteral( "INPUT" ), false, 0 );
120  endOffset->setIsDynamic( true );
121  endOffset->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "END_OFFSET" ), QObject::tr( "End offset" ), QgsPropertyDefinition::DoublePositive ) );
122  endOffset->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
123  addParameter( endOffset.release() );
124 }
125 
126 QIcon QgsPointsAlongGeometryAlgorithm::icon() const
127 {
128  return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmExtractVertices.svg" ) );
129 }
130 
131 QString QgsPointsAlongGeometryAlgorithm::svgIconPath() const
132 {
133  return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmExtractVertices.svg" ) );
134 }
135 
136 QgsProcessingFeatureSource::Flag QgsPointsAlongGeometryAlgorithm::sourceFlags() const
137 {
138  // skip geometry checks - this algorithm doesn't care about invalid geometries
140 }
141 
142 QgsFeatureSink::SinkFlags QgsPointsAlongGeometryAlgorithm::sinkFlags() const
143 {
145 }
146 
147 bool QgsPointsAlongGeometryAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
148 {
149  mDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
150  mDynamicDistance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
151  if ( mDynamicDistance )
152  mDistanceProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value< QgsProperty >();
153 
154  mStartOffset = parameterAsDouble( parameters, QStringLiteral( "START_OFFSET" ), context );
155  mDynamicStartOffset = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "START_OFFSET" ) );
156  if ( mDynamicStartOffset )
157  mStartOffsetProperty = parameters.value( QStringLiteral( "START_OFFSET" ) ).value< QgsProperty >();
158 
159  mEndOffset = parameterAsDouble( parameters, QStringLiteral( "END_OFFSET" ), context );
160  mDynamicEndOffset = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "END_OFFSET" ) );
161  if ( mDynamicEndOffset )
162  mEndOffsetProperty = parameters.value( QStringLiteral( "END_OFFSET" ) ).value< QgsProperty >();
163 
164  return true;
165 }
166 
167 QgsFeatureList QgsPointsAlongGeometryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
168 {
169  QgsFeature f = feature;
170  if ( f.hasGeometry() )
171  {
172  const QgsGeometry geometry = f.geometry();
173 
174  double distance = mDistance;
175  if ( mDynamicDistance )
176  distance = mDistanceProperty.valueAsDouble( context.expressionContext(), distance );
177  if ( distance <= 0 )
178  return QgsFeatureList();
179 
180  double startOffset = mStartOffset;
181  if ( mDynamicStartOffset )
182  startOffset = mStartOffsetProperty.valueAsDouble( context.expressionContext(), startOffset );
183 
184  double endOffset = mEndOffset;
185  if ( mDynamicEndOffset )
186  endOffset = mEndOffsetProperty.valueAsDouble( context.expressionContext(), endOffset );
187 
188  const double totalLength = geometry.type() == QgsWkbTypes::PolygonGeometry ? geometry.constGet()->perimeter()
189  : geometry.length() - endOffset;
190 
191  double currentDistance = startOffset;
192  QgsFeatureList out;
193  out.reserve( static_cast< int >( std::ceil( ( totalLength - startOffset ) / distance ) ) );
194  while ( currentDistance <= totalLength )
195  {
196  const QgsGeometry point = geometry.interpolate( currentDistance );
197  const double angle = ( 180 / M_PI ) * geometry.interpolateAngle( currentDistance );
198  QgsFeature outputFeature;
199  outputFeature.setGeometry( point );
200  QgsAttributes outAttr = f.attributes();
201  outAttr << currentDistance << angle;
202  outputFeature.setAttributes( outAttr );
203  out.append( outputFeature );
204  currentDistance += distance;
205  if ( feedback->isCanceled() ) // better check here -- a ridiculously small distance might take forever
206  break;
207  }
208  return out;
209  }
210  else
211  {
212  QgsAttributes outAttr = f.attributes();
213  outAttr << QVariant() << QVariant();
214  f.setAttributes( outAttr );
215  return QgsFeatureList() << f;
216  }
217 }
218 
220 
221 
Base class for providing feedback from a processing algorithm.
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
QgsGeometry interpolate(double distance) const
Returns an interpolated point on the geometry at the specified distance.
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
Positive double value (including 0)
Definition: qgsproperty.h:58
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:771
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:892
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:867
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
Vector polygon layers.
Definition: qgsprocessing.h:50
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
A store for object properties.
Definition: qgsproperty.h:229
double length() const
Returns the length of geometry using GEOS.
QgsExpressionContext & expressionContext()
Returns the expression context.
Definition for a property.
Definition: qgsproperty.h:46
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
double valueAsDouble(const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a double.
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Vector point layers.
Definition: qgsprocessing.h:48
virtual double perimeter() const
Returns the perimeter of the geometry.
Vector line layers.
Definition: qgsprocessing.h:49
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
SourceType
Data source types enum.
Definition: qgsprocessing.h:44
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:821
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:115
QgsGeometry geometry
Definition: qgsfeature.h:67
A vector of attributes.
Definition: qgsattributes.h:57
Contains information about the context in which a processing algorithm is executed.
static bool isDynamic(const QVariantMap &parameters, const QString &name)
Returns true if the parameter with matching name is a dynamic parameter, and must be evaluated once f...
QgsAttributes attributes
Definition: qgsfeature.h:65