QGIS API Documentation 3.99.0-Master (21b3aa880ba)
Loading...
Searching...
No Matches
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
20#include "qgsapplication.h"
21#include "qgscurve.h"
23
25
26QString QgsPointsAlongGeometryAlgorithm::name() const
27{
28 return QStringLiteral( "pointsalonglines" );
29}
30
31QString QgsPointsAlongGeometryAlgorithm::displayName() const
32{
33 return QObject::tr( "Points along geometry" );
34}
35
36QStringList QgsPointsAlongGeometryAlgorithm::tags() const
37{
38 return QObject::tr( "create,interpolate,points,lines,regular,distance,by" ).split( ',' );
39}
40
41QString QgsPointsAlongGeometryAlgorithm::group() const
42{
43 return QObject::tr( "Vector geometry" );
44}
45
46QString QgsPointsAlongGeometryAlgorithm::groupId() const
47{
48 return QStringLiteral( "vectorgeometry" );
49}
50
51QString QgsPointsAlongGeometryAlgorithm::outputName() const
52{
53 return QObject::tr( "Interpolated points" );
54}
55
56QString QgsPointsAlongGeometryAlgorithm::shortHelpString() const
57{
58 return QObject::tr( "This algorithm creates a points layer, with points distributed along the lines of an "
59 "input vector layer. The distance between points (measured along the line) is defined as a parameter.\n\n"
60 "Start and end offset distances can be defined, so the first and last point will not fall exactly on the line's "
61 "first and last nodes. These start and end offsets are defined as distances, measured along the line from the first and last "
62 "nodes of the lines." );
63}
64
65QString QgsPointsAlongGeometryAlgorithm::shortDescription() const
66{
67 return QObject::tr( "Creates regularly spaced points along line features." );
68}
69
70Qgis::ProcessingAlgorithmDocumentationFlags QgsPointsAlongGeometryAlgorithm::documentationFlags() const
71{
73}
74
75QList<int> QgsPointsAlongGeometryAlgorithm::inputLayerTypes() const
76{
77 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorLine ) << static_cast<int>( Qgis::ProcessingSourceType::VectorPolygon );
78}
79
80Qgis::ProcessingSourceType QgsPointsAlongGeometryAlgorithm::outputLayerType() const
81{
83}
84
85Qgis::WkbType QgsPointsAlongGeometryAlgorithm::outputWkbType( Qgis::WkbType inputType ) const
86{
88 if ( QgsWkbTypes::hasZ( inputType ) )
89 out = QgsWkbTypes::addZ( out );
90 if ( QgsWkbTypes::hasM( inputType ) )
91 out = QgsWkbTypes::addM( out );
92 return out;
93}
94
95QgsFields QgsPointsAlongGeometryAlgorithm::outputFields( const QgsFields &inputFields ) const
96{
97 QgsFields newFields;
98 newFields.append( QgsField( QStringLiteral( "distance" ), QMetaType::Type::Double ) );
99 newFields.append( QgsField( QStringLiteral( "angle" ), QMetaType::Type::Double ) );
100 return QgsProcessingUtils::combineFields( inputFields, newFields );
101}
102
103QgsPointsAlongGeometryAlgorithm *QgsPointsAlongGeometryAlgorithm::createInstance() const
104{
105 return new QgsPointsAlongGeometryAlgorithm();
106}
107
108void QgsPointsAlongGeometryAlgorithm::initParameters( const QVariantMap & )
109{
110 auto distance = std::make_unique<QgsProcessingParameterDistance>( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance" ), 1.0, QStringLiteral( "INPUT" ), false, 0 );
111 distance->setIsDynamic( true );
112 distance->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "DISTANCE" ), QObject::tr( "Distance" ), QgsPropertyDefinition::DoublePositive ) );
113 distance->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
114 addParameter( distance.release() );
115
116 auto startOffset = std::make_unique<QgsProcessingParameterDistance>( QStringLiteral( "START_OFFSET" ), QObject::tr( "Start offset" ), 0.0, QStringLiteral( "INPUT" ), false, 0 );
117 startOffset->setIsDynamic( true );
118 startOffset->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "START_OFFSET" ), QObject::tr( "Start offset" ), QgsPropertyDefinition::DoublePositive ) );
119 startOffset->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
120 addParameter( startOffset.release() );
121
122 auto endOffset = std::make_unique<QgsProcessingParameterDistance>( QStringLiteral( "END_OFFSET" ), QObject::tr( "End offset" ), 0.0, QStringLiteral( "INPUT" ), false, 0 );
123 endOffset->setIsDynamic( true );
124 endOffset->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "END_OFFSET" ), QObject::tr( "End offset" ), QgsPropertyDefinition::DoublePositive ) );
125 endOffset->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
126 addParameter( endOffset.release() );
127}
128
129QIcon QgsPointsAlongGeometryAlgorithm::icon() const
130{
131 return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmExtractVertices.svg" ) );
132}
133
134QString QgsPointsAlongGeometryAlgorithm::svgIconPath() const
135{
136 return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmExtractVertices.svg" ) );
137}
138
139Qgis::ProcessingFeatureSourceFlags QgsPointsAlongGeometryAlgorithm::sourceFlags() const
140{
141 // skip geometry checks - this algorithm doesn't care about invalid geometries
143}
144
145QgsFeatureSink::SinkFlags QgsPointsAlongGeometryAlgorithm::sinkFlags() const
146{
148}
149
150bool QgsPointsAlongGeometryAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
151{
152 mDistance = parameterAsDouble( parameters, QStringLiteral( "DISTANCE" ), context );
153 mDynamicDistance = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "DISTANCE" ) );
154 if ( mDynamicDistance )
155 mDistanceProperty = parameters.value( QStringLiteral( "DISTANCE" ) ).value<QgsProperty>();
156
157 mStartOffset = parameterAsDouble( parameters, QStringLiteral( "START_OFFSET" ), context );
158 mDynamicStartOffset = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "START_OFFSET" ) );
159 if ( mDynamicStartOffset )
160 mStartOffsetProperty = parameters.value( QStringLiteral( "START_OFFSET" ) ).value<QgsProperty>();
161
162 mEndOffset = parameterAsDouble( parameters, QStringLiteral( "END_OFFSET" ), context );
163 mDynamicEndOffset = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "END_OFFSET" ) );
164 if ( mDynamicEndOffset )
165 mEndOffsetProperty = parameters.value( QStringLiteral( "END_OFFSET" ) ).value<QgsProperty>();
166
167 return true;
168}
169
170QgsFeatureList QgsPointsAlongGeometryAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
171{
172 QgsFeature f = feature;
173 if ( f.hasGeometry() )
174 {
175 const QgsGeometry geometry = f.geometry();
176
177 double distance = mDistance;
178 if ( mDynamicDistance )
179 distance = mDistanceProperty.valueAsDouble( context.expressionContext(), distance );
180 if ( distance <= 0 )
181 return QgsFeatureList();
182
183 double startOffset = mStartOffset;
184 if ( mDynamicStartOffset )
185 startOffset = mStartOffsetProperty.valueAsDouble( context.expressionContext(), startOffset );
186
187 double endOffset = mEndOffset;
188 if ( mDynamicEndOffset )
189 endOffset = mEndOffsetProperty.valueAsDouble( context.expressionContext(), endOffset );
190
191 const double totalLength = geometry.type() == Qgis::GeometryType::Polygon ? geometry.constGet()->perimeter()
192 : geometry.length() - endOffset;
193
194 double currentDistance = startOffset;
195 QgsFeatureList out;
196 out.reserve( static_cast<int>( std::ceil( ( totalLength - startOffset ) / distance ) ) );
197 while ( currentDistance <= totalLength )
198 {
199 const QgsGeometry point = geometry.interpolate( currentDistance );
200 const double angle = ( 180 / M_PI ) * geometry.interpolateAngle( currentDistance );
201 QgsFeature outputFeature;
202 outputFeature.setGeometry( point );
203 QgsAttributes outAttr = f.attributes();
204 outAttr << currentDistance << angle;
205 outputFeature.setAttributes( outAttr );
206 out.append( outputFeature );
207 currentDistance += distance;
208 if ( feedback->isCanceled() ) // better check here -- a ridiculously small distance might take forever
209 break;
210 }
211 return out;
212 }
213 else
214 {
215 QgsAttributes outAttr = f.attributes();
216 outAttr << QVariant() << QVariant();
217 f.setAttributes( outAttr );
218 return QgsFeatureList() << f;
219 }
220}
221
ProcessingSourceType
Processing data source types.
Definition qgis.h:3531
@ VectorPoint
Vector point layers.
Definition qgis.h:3534
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3536
@ VectorLine
Vector line layers.
Definition qgis.h:3535
@ Polygon
Polygons.
Definition qgis.h:361
@ RegeneratesPrimaryKey
Algorithm always drops any existing primary keys or FID values and regenerates them in outputs.
Definition qgis.h:3619
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3630
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition qgis.h:3711
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:277
@ Point
Point.
Definition qgis.h:279
QFlags< ProcessingFeatureSourceFlag > ProcessingFeatureSourceFlags
Flags which control how QgsProcessingFeatureSource fetches features.
Definition qgis.h:3722
virtual double perimeter() const
Returns the planar, 2-dimensional perimeter of the geometry.
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.
QFlags< SinkFlag > SinkFlags
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
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.
void setGeometry(const QgsGeometry &geometry)
Set the feature's 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
A geometry is the spatial representation of a feature.
double length() const
Returns the planar, 2-dimensional length of geometry.
QgsGeometry interpolate(double distance) const
Returns an interpolated point on the geometry at the specified distance.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Qgis::GeometryType type
double interpolateAngle(double distance) const
Returns the angle parallel to the linestring or polygon boundary at the specified distance along the ...
Contains information about the context in which a processing algorithm is executed.
QgsExpressionContext & expressionContext()
Returns the expression context.
Base class for providing feedback from a processing algorithm.
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...
static QgsFields combineFields(const QgsFields &fieldsA, const QgsFields &fieldsB, const QString &fieldsBPrefix=QString())
Combines two field lists, avoiding duplicate field names (in a case-insensitive manner).
Definition for a property.
Definition qgsproperty.h:45
@ DoublePositive
Positive double value (including 0).
Definition qgsproperty.h:56
A store for object properties.
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.
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
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).
QList< QgsFeature > QgsFeatureList