QGIS API Documentation  3.12.1-București (121cc00ff0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 
25 QString QgsExtractSpecificVerticesAlgorithm::name() const
26 {
27  return QStringLiteral( "extractspecificvertices" );
28 }
29 
30 QString QgsExtractSpecificVerticesAlgorithm::displayName() const
31 {
32  return QObject::tr( "Extract specific vertices" );
33 }
34 
35 QStringList QgsExtractSpecificVerticesAlgorithm::tags() const
36 {
37  return QObject::tr( "points,vertex,nodes" ).split( ',' );
38 }
39 
40 QString QgsExtractSpecificVerticesAlgorithm::group() const
41 {
42  return QObject::tr( "Vector geometry" );
43 }
44 
45 QString QgsExtractSpecificVerticesAlgorithm::groupId() const
46 {
47  return QStringLiteral( "vectorgeometry" );
48 }
49 
50 QString QgsExtractSpecificVerticesAlgorithm::shortHelpString() const
51 {
52  return QObject::tr( "This algorithm takes a line or polygon layer and generates a point layer with points "
53  "representing specific vertices in the input lines or polygons. 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 line or polygon 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 
67 QString QgsExtractSpecificVerticesAlgorithm::outputName() const
68 {
69  return QObject::tr( "Vertices" );
70 }
71 
72 QgsExtractSpecificVerticesAlgorithm *QgsExtractSpecificVerticesAlgorithm::createInstance() const
73 {
74  return new QgsExtractSpecificVerticesAlgorithm();
75 }
76 
77 QgsProcessing::SourceType QgsExtractSpecificVerticesAlgorithm::outputLayerType() const
78 {
80 }
81 
82 QgsFields 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 == QgsWkbTypes::PolygonGeometry )
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 
99 QgsWkbTypes::Type QgsExtractSpecificVerticesAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
100 {
101  QgsWkbTypes::Type outputWkbType = QgsWkbTypes::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 
114 QgsProcessingFeatureSource::Flag QgsExtractSpecificVerticesAlgorithm::sourceFlags() const
115 {
117 }
118 
119 QgsFeatureSink::SinkFlags QgsExtractSpecificVerticesAlgorithm::sinkFlags() const
120 {
122 }
123 
124 void QgsExtractSpecificVerticesAlgorithm::initParameters( const QVariantMap & )
125 {
126  addParameter( new QgsProcessingParameterString( QStringLiteral( "VERTICES" ), QObject::tr( "Vertex indices" ), QStringLiteral( "0" ) ) );
127 }
128 
129 bool 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  QString verticesString = parameterAsString( parameters, QStringLiteral( "VERTICES" ), context );
135  const QStringList verticesList = verticesString.split( ',', QString::SkipEmptyParts );
136  for ( const QString &vertex : verticesList )
137  {
138  bool ok = false;
139  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 
153 QgsFeatureList QgsExtractSpecificVerticesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * )
154 {
155  QgsFeatureList outputFeatures;
156 
157  QgsFeature f = feature;
158  QgsGeometry inputGeom = f.geometry();
159  if ( inputGeom.isNull() )
160  {
161  QgsAttributes attrs = f.attributes();
162  attrs << QVariant()
163  << QVariant()
164  << QVariant();
165  if ( mGeometryType == QgsWkbTypes::PolygonGeometry )
166  {
167  attrs << QVariant();
168  }
169  attrs << QVariant()
170  << QVariant()
171  << QVariant();
172 
173  f.setAttributes( attrs );
174  outputFeatures << f;
175  }
176  else
177  {
178  int vertexIndex;
179  int totalVertices = inputGeom.constGet()->nCoordinates();
180  for ( int vertex : mIndices )
181  {
182  if ( vertex < 0 )
183  {
184  vertexIndex = totalVertices + vertex;
185  }
186  else
187  {
188  vertexIndex = vertex;
189  }
190 
191  if ( vertexIndex < 0 || vertexIndex >= totalVertices )
192  continue;
193 
194  QgsVertexId vertexId;
195  inputGeom.vertexIdFromVertexNr( vertexIndex, vertexId );
196 
197  double distance = inputGeom.distanceToVertex( vertexIndex );
198  double angle = inputGeom.angleAtVertex( vertexIndex ) * 180 / M_PI;
199 
200  QgsFeature outFeature = QgsFeature();
201  QgsAttributes attrs = f.attributes();
202  attrs << vertex
203  << vertexIndex
204  << vertexId.part;
205  if ( mGeometryType == QgsWkbTypes::PolygonGeometry )
206  {
207  attrs << vertexId.ring;
208  }
209  attrs << vertexId.vertex
210  << distance
211  << angle;
212 
213  outFeature.setAttributes( attrs );
214  QgsPoint point = inputGeom.vertexAt( vertexIndex );
215  outFeature.setGeometry( QgsGeometry( point.clone() ) );
216  outputFeatures << outFeature;
217  }
218  }
219 
220  return outputFeatures;
221 }
222 
Base class for providing feedback from a processing algorithm.
Invalid geometry checks should always be skipped. This flag can be useful for algorithms which always...
double angleAtVertex(int vertex) const
Returns the bisector angle for this geometry at the specified vertex.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
double distanceToVertex(int vertex) const
Returns the distance along this geometry from its first vertex to the specified vertex.
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:917
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
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1038
Utility class for identifying a unique vertex within a geometry.
static GeometryType geometryType(Type type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:812
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1013
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
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
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:97
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:49
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
Flag
Flags controlling how QgsProcessingFeatureSource fetches features.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPoint vertexAt(int atVertex) const
Returns coordinates of a vertex.
Vector point layers.
Definition: qgsprocessing.h:48
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
SourceType
Data source types enum.
Definition: qgsprocessing.h:44
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:967
QgsGeometry geometry
Definition: qgsfeature.h:67
bool vertexIdFromVertexNr(int number, QgsVertexId &id) const
Calculates the vertex ID from a vertex number.
A vector of attributes.
Definition: qgsattributes.h:57
virtual int nCoordinates() const
Returns the number of nodes contained in the geometry.
Contains information about the context in which a processing algorithm is executed.
A string parameter for processing algorithms.
QgsAttributes attributes
Definition: qgsfeature.h:65