QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsalgorithmextractspecificvertices.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmextractspecificvertices.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 "qgsabstractgeometry.h"
21#include "qgsgeometryutils.h"
22
24
25QString QgsExtractSpecificVerticesAlgorithm::name() const
26{
27 return QStringLiteral( "extractspecificvertices" );
28}
29
30QString QgsExtractSpecificVerticesAlgorithm::displayName() const
31{
32 return QObject::tr( "Extract specific vertices" );
33}
34
35QStringList QgsExtractSpecificVerticesAlgorithm::tags() const
36{
37 return QObject::tr( "points,vertex,nodes" ).split( ',' );
38}
39
40QString QgsExtractSpecificVerticesAlgorithm::group() const
41{
42 return QObject::tr( "Vector geometry" );
43}
44
45QString QgsExtractSpecificVerticesAlgorithm::groupId() const
46{
47 return QStringLiteral( "vectorgeometry" );
48}
49
50QString QgsExtractSpecificVerticesAlgorithm::shortHelpString() const
51{
52 return QObject::tr( "This algorithm takes a vector layer and generates a point layer with points "
53 "representing specific vertices in the input geometries. For instance, this algorithm "
54 "can be used to extract the first or last vertices in the geometry. The attributes associated "
55 "to each point are the same ones associated to the feature that the point belongs to." ) +
56 QStringLiteral( "\n\n" ) +
57 QObject::tr( "The vertex indices parameter accepts a comma separated string specifying the indices of the "
58 "vertices to extract. The first vertex corresponds to an index of 0, the second vertex has an "
59 "index of 1, etc. Negative indices can be used to find vertices at the end of the geometry, "
60 "e.g., an index of -1 corresponds to the last vertex, -2 corresponds to the second last vertex, etc." ) +
61 QStringLiteral( "\n\n" ) +
62 QObject::tr( "Additional fields are added to the points indicating the specific vertex position (e.g., 0, -1, etc), "
63 "the original vertex index, the vertex’s part and its index within the part (as well as its ring for "
64 "polygons), distance along the original geometry and bisector angle of vertex for the original geometry." );
65}
66
67QString QgsExtractSpecificVerticesAlgorithm::outputName() const
68{
69 return QObject::tr( "Vertices" );
70}
71
72QgsExtractSpecificVerticesAlgorithm *QgsExtractSpecificVerticesAlgorithm::createInstance() const
73{
74 return new QgsExtractSpecificVerticesAlgorithm();
75}
76
77Qgis::ProcessingSourceType QgsExtractSpecificVerticesAlgorithm::outputLayerType() const
78{
80}
81
82QgsFields QgsExtractSpecificVerticesAlgorithm::outputFields( const QgsFields &inputFields ) const
83{
84 QgsFields outputFields = inputFields;
85 outputFields.append( QgsField( QStringLiteral( "vertex_pos" ), QVariant::Int ) );
86 outputFields.append( QgsField( QStringLiteral( "vertex_index" ), QVariant::Int ) );
87 outputFields.append( QgsField( QStringLiteral( "vertex_part" ), QVariant::Int ) );
88 if ( mGeometryType == Qgis::GeometryType::Polygon )
89 {
90 outputFields.append( QgsField( QStringLiteral( "vertex_part_ring" ), QVariant::Int ) );
91 }
92 outputFields.append( QgsField( QStringLiteral( "vertex_part_index" ), QVariant::Int ) );
93 outputFields.append( QgsField( QStringLiteral( "distance" ), QVariant::Double ) );
94 outputFields.append( QgsField( QStringLiteral( "angle" ), QVariant::Double ) );
95
96 return outputFields;
97}
98
99Qgis::WkbType QgsExtractSpecificVerticesAlgorithm::outputWkbType( Qgis::WkbType inputWkbType ) const
100{
101 Qgis::WkbType outputWkbType = Qgis::WkbType::Point;
102 if ( QgsWkbTypes::hasM( inputWkbType ) )
103 {
104 outputWkbType = QgsWkbTypes::addM( outputWkbType );
105 }
106 if ( QgsWkbTypes::hasZ( inputWkbType ) )
107 {
108 outputWkbType = QgsWkbTypes::addZ( outputWkbType );
109 }
110
111 return outputWkbType;
112}
113
114Qgis::ProcessingFeatureSourceFlags QgsExtractSpecificVerticesAlgorithm::sourceFlags() const
115{
117}
118
119QgsFeatureSink::SinkFlags QgsExtractSpecificVerticesAlgorithm::sinkFlags() const
120{
122}
123
124void QgsExtractSpecificVerticesAlgorithm::initParameters( const QVariantMap & )
125{
126 addParameter( new QgsProcessingParameterString( QStringLiteral( "VERTICES" ), QObject::tr( "Vertex indices" ), QStringLiteral( "0" ) ) );
127}
128
129bool QgsExtractSpecificVerticesAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
130{
131 std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
132 mGeometryType = QgsWkbTypes::geometryType( source->wkbType() );
133
134 const QString verticesString = parameterAsString( parameters, QStringLiteral( "VERTICES" ), context );
135 const QStringList verticesList = verticesString.split( ',', Qt::SkipEmptyParts );
136 for ( const QString &vertex : verticesList )
137 {
138 bool ok = false;
139 const int i = vertex.toInt( &ok );
140 if ( ok )
141 {
142 mIndices << i;
143 }
144 else
145 {
146 throw QgsProcessingException( QObject::tr( "'%1' is not a valid vertex index" ).arg( vertex ) );
147 }
148 }
149
150 return true;
151}
152
153QgsFeatureList QgsExtractSpecificVerticesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
154{
155 QgsFeatureList outputFeatures;
156
157 QgsFeature f = feature;
158 const QgsGeometry inputGeom = f.geometry();
159 if ( inputGeom.isEmpty() )
160 {
161 QgsAttributes attrs = f.attributes();
162 attrs << QVariant()
163 << QVariant()
164 << QVariant();
165 if ( mGeometryType == Qgis::GeometryType::Polygon )
166 {
167 attrs << QVariant();
168 }
169 attrs << QVariant()
170 << QVariant()
171 << QVariant();
172
173 f.clearGeometry();
174 f.setAttributes( attrs );
175 outputFeatures << f;
176 }
177 else
178 {
179 int vertexIndex;
180 const int totalVertices = inputGeom.constGet()->nCoordinates();
181 for ( const int vertex : mIndices )
182 {
183 if ( vertex < 0 )
184 {
185 vertexIndex = totalVertices + vertex;
186 }
187 else
188 {
189 vertexIndex = vertex;
190 }
191
192 if ( vertexIndex < 0 || vertexIndex >= totalVertices )
193 continue;
194
195 QgsVertexId vertexId;
196 inputGeom.vertexIdFromVertexNr( vertexIndex, vertexId );
197
198 const double distance = inputGeom.distanceToVertex( vertexIndex );
199 const double angle = inputGeom.angleAtVertex( vertexIndex ) * 180 / M_PI;
200
201 QgsFeature outFeature = QgsFeature();
202 QgsAttributes attrs = f.attributes();
203 attrs << vertex
204 << vertexIndex
205 << vertexId.part;
206 if ( mGeometryType == Qgis::GeometryType::Polygon )
207 {
208 attrs << vertexId.ring;
209 }
210 attrs << vertexId.vertex
211 << distance
212 << angle;
213
214 outFeature.setAttributes( attrs );
215 const QgsPoint point = inputGeom.vertexAt( vertexIndex );
216 outFeature.setGeometry( QgsGeometry( point.clone() ) );
217 outputFeatures << outFeature;
218 }
219 }
220
221 return outputFeatures;
222}
223
ProcessingSourceType
Processing data source types.
Definition: qgis.h:2858
@ VectorPoint
Vector point layers.
@ Polygon
Polygons.
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
QFlags< ProcessingFeatureSourceFlag > ProcessingFeatureSourceFlags
Flags which control how QgsProcessingFeatureSource fetches features.
Definition: qgis.h:3011
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
A vector of attributes.
Definition: qgsattributes.h:59
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: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
void clearGeometry()
Removes any geometry associated with the feature.
Definition: qgsfeature.cpp:181
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:167
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:53
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:162
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool isEmpty() const
Returns true if the geometry is empty (eg a linestring with no vertices, or a collection with no geom...
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:105
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Definition: qgsexception.h:83
Base class for providing feedback from a processing algorithm.
A string parameter for processing algorithms.
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:862
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1092
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1068
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:973
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1023
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:716
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:917
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30
int vertex
Vertex number.
Definition: qgsvertexid.h:94
int part
Part number.
Definition: qgsvertexid.h:88
int ring
Ring number.
Definition: qgsvertexid.h:91