QGIS API Documentation 3.39.0-Master (d85f3c2a281)
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
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
67Qgis::ProcessingAlgorithmDocumentationFlags QgsExtractSpecificVerticesAlgorithm::documentationFlags() const
68{
70}
71
72QString QgsExtractSpecificVerticesAlgorithm::outputName() const
73{
74 return QObject::tr( "Vertices" );
75}
76
77QgsExtractSpecificVerticesAlgorithm *QgsExtractSpecificVerticesAlgorithm::createInstance() const
78{
79 return new QgsExtractSpecificVerticesAlgorithm();
80}
81
82Qgis::ProcessingSourceType QgsExtractSpecificVerticesAlgorithm::outputLayerType() const
83{
85}
86
87QgsFields QgsExtractSpecificVerticesAlgorithm::outputFields( const QgsFields &inputFields ) const
88{
89 QgsFields outputFields = inputFields;
90 outputFields.append( QgsField( QStringLiteral( "vertex_pos" ), QMetaType::Type::Int ) );
91 outputFields.append( QgsField( QStringLiteral( "vertex_index" ), QMetaType::Type::Int ) );
92 outputFields.append( QgsField( QStringLiteral( "vertex_part" ), QMetaType::Type::Int ) );
93 if ( mGeometryType == Qgis::GeometryType::Polygon )
94 {
95 outputFields.append( QgsField( QStringLiteral( "vertex_part_ring" ), QMetaType::Type::Int ) );
96 }
97 outputFields.append( QgsField( QStringLiteral( "vertex_part_index" ), QMetaType::Type::Int ) );
98 outputFields.append( QgsField( QStringLiteral( "distance" ), QMetaType::Type::Double ) );
99 outputFields.append( QgsField( QStringLiteral( "angle" ), QMetaType::Type::Double ) );
100
101 return outputFields;
102}
103
104Qgis::WkbType QgsExtractSpecificVerticesAlgorithm::outputWkbType( Qgis::WkbType inputWkbType ) const
105{
106 Qgis::WkbType outputWkbType = Qgis::WkbType::Point;
107 if ( QgsWkbTypes::hasM( inputWkbType ) )
108 {
109 outputWkbType = QgsWkbTypes::addM( outputWkbType );
110 }
111 if ( QgsWkbTypes::hasZ( inputWkbType ) )
112 {
113 outputWkbType = QgsWkbTypes::addZ( outputWkbType );
114 }
115
116 return outputWkbType;
117}
118
119Qgis::ProcessingFeatureSourceFlags QgsExtractSpecificVerticesAlgorithm::sourceFlags() const
120{
122}
123
124QgsFeatureSink::SinkFlags QgsExtractSpecificVerticesAlgorithm::sinkFlags() const
125{
127}
128
129void QgsExtractSpecificVerticesAlgorithm::initParameters( const QVariantMap & )
130{
131 addParameter( new QgsProcessingParameterString( QStringLiteral( "VERTICES" ), QObject::tr( "Vertex indices" ), QStringLiteral( "0" ) ) );
132}
133
134bool QgsExtractSpecificVerticesAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
135{
136 std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
137 if ( !source )
138 throw QgsProcessingException( invalidSourceError( parameters, QStringLiteral( "INPUT" ) ) );
139
140 mGeometryType = QgsWkbTypes::geometryType( source->wkbType() );
141
142 const QString verticesString = parameterAsString( parameters, QStringLiteral( "VERTICES" ), context );
143 const QStringList verticesList = verticesString.split( ',', Qt::SkipEmptyParts );
144 for ( const QString &vertex : verticesList )
145 {
146 bool ok = false;
147 const int i = vertex.toInt( &ok );
148 if ( ok )
149 {
150 mIndices << i;
151 }
152 else
153 {
154 throw QgsProcessingException( QObject::tr( "'%1' is not a valid vertex index" ).arg( vertex ) );
155 }
156 }
157
158 return true;
159}
160
161QgsFeatureList QgsExtractSpecificVerticesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
162{
163 QgsFeatureList outputFeatures;
164
165 QgsFeature f = feature;
166 const QgsGeometry inputGeom = f.geometry();
167 if ( inputGeom.isEmpty() )
168 {
169 QgsAttributes attrs = f.attributes();
170 attrs << QVariant()
171 << QVariant()
172 << QVariant();
173 if ( mGeometryType == Qgis::GeometryType::Polygon )
174 {
175 attrs << QVariant();
176 }
177 attrs << QVariant()
178 << QVariant()
179 << QVariant();
180
181 f.clearGeometry();
182 f.setAttributes( attrs );
183 outputFeatures << f;
184 }
185 else
186 {
187 int vertexIndex;
188 const int totalVertices = inputGeom.constGet()->nCoordinates();
189 for ( const int vertex : mIndices )
190 {
191 if ( vertex < 0 )
192 {
193 vertexIndex = totalVertices + vertex;
194 }
195 else
196 {
197 vertexIndex = vertex;
198 }
199
200 if ( vertexIndex < 0 || vertexIndex >= totalVertices )
201 continue;
202
203 QgsVertexId vertexId;
204 inputGeom.vertexIdFromVertexNr( vertexIndex, vertexId );
205
206 const double distance = inputGeom.distanceToVertex( vertexIndex );
207 const double angle = inputGeom.angleAtVertex( vertexIndex ) * 180 / M_PI;
208
209 QgsFeature outFeature = QgsFeature();
210 QgsAttributes attrs = f.attributes();
211 attrs << vertex
212 << vertexIndex
213 << vertexId.part;
214 if ( mGeometryType == Qgis::GeometryType::Polygon )
215 {
216 attrs << vertexId.ring;
217 }
218 attrs << vertexId.vertex
219 << distance
220 << angle;
221
222 outFeature.setAttributes( attrs );
223 const QgsPoint point = inputGeom.vertexAt( vertexIndex );
224 outFeature.setGeometry( QgsGeometry( point.clone() ) );
225 outputFeatures << outFeature;
226 }
227 }
228
229 return outputFeatures;
230}
231
ProcessingSourceType
Processing data source types.
Definition qgis.h:3241
@ VectorPoint
Vector point layers.
@ Polygon
Polygons.
@ RegeneratesPrimaryKey
Algorithm always drops any existing primary keys or FID values and regenerates them in outputs.
QFlags< ProcessingAlgorithmDocumentationFlag > ProcessingAlgorithmDocumentationFlags
Flags describing algorithm behavior for documentation purposes.
Definition qgis.h:3337
@ 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:256
QFlags< ProcessingFeatureSourceFlag > ProcessingFeatureSourceFlags
Flags which control how QgsProcessingFeatureSource fetches features.
Definition qgis.h:3414
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:58
QgsAttributes attributes
Definition qgsfeature.h:67
void setAttributes(const QgsAttributes &attrs)
Sets the feature's attributes.
QgsGeometry geometry
Definition qgsfeature.h:69
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:53
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:69
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:49
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition qgspoint.cpp:104
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 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 bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static 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: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