QGIS API Documentation 3.99.0-Master (09f76ad7019)
Loading...
Searching...
No Matches
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
23#include <QString>
24
25using namespace Qt::StringLiterals;
26
28
29QString QgsExtractSpecificVerticesAlgorithm::name() const
30{
31 return u"extractspecificvertices"_s;
32}
33
34QString QgsExtractSpecificVerticesAlgorithm::displayName() const
35{
36 return QObject::tr( "Extract specific vertices" );
37}
38
39QStringList QgsExtractSpecificVerticesAlgorithm::tags() const
40{
41 return QObject::tr( "points,vertex,nodes" ).split( ',' );
42}
43
44QString QgsExtractSpecificVerticesAlgorithm::group() const
45{
46 return QObject::tr( "Vector geometry" );
47}
48
49QString QgsExtractSpecificVerticesAlgorithm::groupId() const
50{
51 return u"vectorgeometry"_s;
52}
53
54QString QgsExtractSpecificVerticesAlgorithm::shortHelpString() const
55{
56 return QObject::tr( "This algorithm takes a vector layer and generates a point layer with points "
57 "representing specific vertices in the input geometries. For instance, this algorithm "
58 "can be used to extract the first or last vertices in the geometry. The attributes associated "
59 "to each point are the same ones associated to the feature that the point belongs to." )
60 + u"\n\n"_s + QObject::tr( "The vertex indices parameter accepts a comma separated string specifying the indices of the "
61 "vertices to extract. The first vertex corresponds to an index of 0, the second vertex has an "
62 "index of 1, etc. Negative indices can be used to find vertices at the end of the geometry, "
63 "e.g., an index of -1 corresponds to the last vertex, -2 corresponds to the second last vertex, etc." )
64 + u"\n\n"_s + QObject::tr( "Additional fields are added to the points indicating the specific vertex position (e.g., 0, -1, etc), "
65 "the original vertex index, the vertex’s part and its index within the part (as well as its ring for "
66 "polygons), distance along the original geometry and bisector angle of vertex for the original geometry." );
67}
68
69QString QgsExtractSpecificVerticesAlgorithm::shortDescription() const
70{
71 return QObject::tr( "Generates a point layer with points representing specific vertices in the input geometries." );
72}
73
74Qgis::ProcessingAlgorithmDocumentationFlags QgsExtractSpecificVerticesAlgorithm::documentationFlags() const
75{
77}
78
79QString QgsExtractSpecificVerticesAlgorithm::outputName() const
80{
81 return QObject::tr( "Vertices" );
82}
83
84QgsExtractSpecificVerticesAlgorithm *QgsExtractSpecificVerticesAlgorithm::createInstance() const
85{
86 return new QgsExtractSpecificVerticesAlgorithm();
87}
88
89Qgis::ProcessingSourceType QgsExtractSpecificVerticesAlgorithm::outputLayerType() const
90{
92}
93
94QgsFields QgsExtractSpecificVerticesAlgorithm::outputFields( const QgsFields &inputFields ) const
95{
96 QgsFields newFields;
97 newFields.append( QgsField( u"vertex_pos"_s, QMetaType::Type::Int ) );
98 newFields.append( QgsField( u"vertex_index"_s, QMetaType::Type::Int ) );
99 newFields.append( QgsField( u"vertex_part"_s, QMetaType::Type::Int ) );
100 if ( mGeometryType == Qgis::GeometryType::Polygon )
101 {
102 newFields.append( QgsField( u"vertex_part_ring"_s, QMetaType::Type::Int ) );
103 }
104 newFields.append( QgsField( u"vertex_part_index"_s, QMetaType::Type::Int ) );
105 newFields.append( QgsField( u"distance"_s, QMetaType::Type::Double ) );
106 newFields.append( QgsField( u"angle"_s, QMetaType::Type::Double ) );
107
108 return QgsProcessingUtils::combineFields( inputFields, newFields );
109}
110
111Qgis::WkbType QgsExtractSpecificVerticesAlgorithm::outputWkbType( Qgis::WkbType inputWkbType ) const
112{
113 Qgis::WkbType outputWkbType = Qgis::WkbType::Point;
114 if ( QgsWkbTypes::hasM( inputWkbType ) )
115 {
116 outputWkbType = QgsWkbTypes::addM( outputWkbType );
117 }
118 if ( QgsWkbTypes::hasZ( inputWkbType ) )
119 {
120 outputWkbType = QgsWkbTypes::addZ( outputWkbType );
121 }
122
123 return outputWkbType;
124}
125
126Qgis::ProcessingFeatureSourceFlags QgsExtractSpecificVerticesAlgorithm::sourceFlags() const
127{
129}
130
131QgsFeatureSink::SinkFlags QgsExtractSpecificVerticesAlgorithm::sinkFlags() const
132{
134}
135
136void QgsExtractSpecificVerticesAlgorithm::initParameters( const QVariantMap & )
137{
138 addParameter( new QgsProcessingParameterString( u"VERTICES"_s, QObject::tr( "Vertex indices" ), u"0"_s ) );
139}
140
141bool QgsExtractSpecificVerticesAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
142{
143 std::unique_ptr<QgsProcessingFeatureSource> source( parameterAsSource( parameters, u"INPUT"_s, context ) );
144 if ( !source )
145 throw QgsProcessingException( invalidSourceError( parameters, u"INPUT"_s ) );
146
147 mGeometryType = QgsWkbTypes::geometryType( source->wkbType() );
148
149 const QString verticesString = parameterAsString( parameters, u"VERTICES"_s, context );
150 const QStringList verticesList = verticesString.split( ',', Qt::SkipEmptyParts );
151 for ( const QString &vertex : verticesList )
152 {
153 bool ok = false;
154 const int i = vertex.toInt( &ok );
155 if ( ok )
156 {
157 mIndices << i;
158 }
159 else
160 {
161 throw QgsProcessingException( QObject::tr( "'%1' is not a valid vertex index" ).arg( vertex ) );
162 }
163 }
164
165 return true;
166}
167
168QgsFeatureList QgsExtractSpecificVerticesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
169{
170 QgsFeatureList outputFeatures;
171
172 QgsFeature f = feature;
173 const QgsGeometry inputGeom = f.geometry();
174 if ( inputGeom.isEmpty() )
175 {
176 QgsAttributes attrs = f.attributes();
177 attrs << QVariant()
178 << QVariant()
179 << QVariant();
180 if ( mGeometryType == Qgis::GeometryType::Polygon )
181 {
182 attrs << QVariant();
183 }
184 attrs << QVariant()
185 << QVariant()
186 << QVariant();
187
188 f.clearGeometry();
189 f.setAttributes( attrs );
190 outputFeatures << f;
191 }
192 else
193 {
194 int vertexIndex;
195 const int totalVertices = inputGeom.constGet()->nCoordinates();
196 for ( const int vertex : mIndices )
197 {
198 if ( vertex < 0 )
199 {
200 vertexIndex = totalVertices + vertex;
201 }
202 else
203 {
204 vertexIndex = vertex;
205 }
206
207 if ( vertexIndex < 0 || vertexIndex >= totalVertices )
208 continue;
209
210 QgsVertexId vertexId;
211 inputGeom.vertexIdFromVertexNr( vertexIndex, vertexId );
212
213 const double distance = inputGeom.distanceToVertex( vertexIndex );
214 const double angle = inputGeom.angleAtVertex( vertexIndex ) * 180 / M_PI;
215
216 QgsFeature outFeature = QgsFeature();
217 QgsAttributes attrs = f.attributes();
218 attrs << vertex
219 << vertexIndex
220 << vertexId.part;
221 if ( mGeometryType == Qgis::GeometryType::Polygon )
222 {
223 attrs << vertexId.ring;
224 }
225 attrs << vertexId.vertex
226 << distance
227 << angle;
228
229 outFeature.setAttributes( attrs );
230 const QgsPoint point = inputGeom.vertexAt( vertexIndex );
231 outFeature.setGeometry( QgsGeometry( point.clone() ) );
232 outputFeatures << outFeature;
233 }
234 }
235
236 return outputFeatures;
237}
238
ProcessingSourceType
Processing data source types.
Definition qgis.h:3602
@ VectorPoint
Vector point layers.
Definition qgis.h:3605
@ Polygon
Polygons.
Definition qgis.h:368
@ RegeneratesPrimaryKey
Algorithm always drops any existing primary keys or FID values and regenerates them in outputs.
Definition qgis.h:3690
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3701
@ SkipGeometryValidityChecks
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
Definition qgis.h:3782
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:280
@ Point
Point.
Definition qgis.h:282
QFlags< ProcessingFeatureSourceFlag > ProcessingFeatureSourceFlags
Flags which control how QgsProcessingFeatureSource fetches features.
Definition qgis.h:3793
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
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:60
QgsAttributes attributes
Definition qgsfeature.h:69
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
QgsGeometry geometry
Definition qgsfeature.h:71
void clearGeometry()
Removes any geometry associated with the feature.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:56
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:76
A geometry is the spatial representation of a feature.
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:53
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition qgspoint.cpp:129
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
A string parameter for processing algorithms.
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).
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...
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
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:34
int vertex
Vertex number.
Definition qgsvertexid.h:98
int part
Part number.
Definition qgsvertexid.h:92
int ring
Ring number.
Definition qgsvertexid.h:95