QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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
20#include "qgscurve.h"
21#include "qgsapplication.h"
22
24
25QString QgsPointsAlongGeometryAlgorithm::name() const
26{
27 return QStringLiteral( "pointsalonglines" );
28}
29
30QString QgsPointsAlongGeometryAlgorithm::displayName() const
31{
32 return QObject::tr( "Points along geometry" );
33}
34
35QStringList QgsPointsAlongGeometryAlgorithm::tags() const
36{
37 return QObject::tr( "create,interpolate,points,lines,regular,distance,by" ).split( ',' );
38}
39
40QString QgsPointsAlongGeometryAlgorithm::group() const
41{
42 return QObject::tr( "Vector geometry" );
43}
44
45QString QgsPointsAlongGeometryAlgorithm::groupId() const
46{
47 return QStringLiteral( "vectorgeometry" );
48}
49
50QString QgsPointsAlongGeometryAlgorithm::outputName() const
51{
52 return QObject::tr( "Interpolated points" );
53}
54
55QString 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
64QString QgsPointsAlongGeometryAlgorithm::shortDescription() const
65{
66 return QObject::tr( "Creates regularly spaced points along line features." );
67}
68
69QList<int> QgsPointsAlongGeometryAlgorithm::inputLayerTypes() const
70{
72}
73
74QgsProcessing::SourceType QgsPointsAlongGeometryAlgorithm::outputLayerType() const
75{
77}
78
79QgsWkbTypes::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
89QgsFields 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
97QgsPointsAlongGeometryAlgorithm *QgsPointsAlongGeometryAlgorithm::createInstance() const
98{
99 return new QgsPointsAlongGeometryAlgorithm();
100}
101
102void QgsPointsAlongGeometryAlgorithm::initParameters( const QVariantMap & )
103{
104 std::unique_ptr< QgsProcessingParameterDistance> distance = std::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 = std::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 = std::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
126QIcon QgsPointsAlongGeometryAlgorithm::icon() const
127{
128 return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmExtractVertices.svg" ) );
129}
130
131QString QgsPointsAlongGeometryAlgorithm::svgIconPath() const
132{
133 return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmExtractVertices.svg" ) );
134}
135
136QgsProcessingFeatureSource::Flag QgsPointsAlongGeometryAlgorithm::sourceFlags() const
137{
138 // skip geometry checks - this algorithm doesn't care about invalid geometries
140}
141
142QgsFeatureSink::SinkFlags QgsPointsAlongGeometryAlgorithm::sinkFlags() const
143{
145}
146
147bool 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
167QgsFeatureList 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
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.
Definition: qgsattributes.h:59
@ 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:56
QgsAttributes attributes
Definition: qgsfeature.h:65
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
Definition: qgsfeature.cpp:160
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:233
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:170
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:51
Container of fields for a vector layer.
Definition: qgsfields.h:45
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
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:164
const QgsAbstractGeometry * constGet() const SIP_HOLDGIL
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
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.
QgsWkbTypes::GeometryType type
Definition: qgsgeometry.h:167
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.
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
@ FlagSkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
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...
SourceType
Data source types enum.
Definition: qgsprocessing.h:46
@ TypeVectorLine
Vector line layers.
Definition: qgsprocessing.h:50
@ TypeVectorPolygon
Vector polygon layers.
Definition: qgsprocessing.h:51
@ TypeVectorPoint
Vector point layers.
Definition: qgsprocessing.h:49
Definition for a property.
Definition: qgsproperty.h:46
@ DoublePositive
Positive double value (including 0)
Definition: qgsproperty.h:57
A store for object properties.
Definition: qgsproperty.h:230
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 bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1130
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
static Type addZ(Type type) SIP_HOLDGIL
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1176
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
static Type addM(Type type) SIP_HOLDGIL
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1201
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
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:922