QGIS API Documentation  3.0.2-Girona (307d082)
qgsalgorithmextractvertices.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmextractvertices.cpp
3  --------------------------
4  begin : November 2017
5  copyright : (C) 2017 by Mathieu Pellerin
6  email : nirvn dot asia 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 QgsExtractVerticesAlgorithm::name() const
26 {
27  return QStringLiteral( "extractvertices" );
28 }
29 
30 QString QgsExtractVerticesAlgorithm::displayName() const
31 {
32  return QObject::tr( "Extract vertices" );
33 }
34 
35 QStringList QgsExtractVerticesAlgorithm::tags() const
36 {
37  return QObject::tr( "points,vertex,nodes" ).split( ',' );
38 }
39 
40 QString QgsExtractVerticesAlgorithm::group() const
41 {
42  return QObject::tr( "Vector geometry" );
43 }
44 
45 QString QgsExtractVerticesAlgorithm::groupId() const
46 {
47  return QStringLiteral( "vectorgeometry" );
48 }
49 
50 QString QgsExtractVerticesAlgorithm::shortHelpString() const
51 {
52  return QObject::tr( "This algorithm takes a line or polygon layer and generates a point layer with points representing the vertices in the input lines or polygons. The attributes associated to each point are the same ones associated to the line or polygon that the point belongs to." ) +
53  QStringLiteral( "\n\n" ) +
54  QObject::tr( "Additional fields are added to the point indicating the vertex index (beginning at 0), the vertex’s part and its index within the part (as well as its ring for polygons), distance along original geometry and bisector angle of vertex for original geometry." );
55 }
56 
57 QgsExtractVerticesAlgorithm *QgsExtractVerticesAlgorithm::createInstance() const
58 {
59  return new QgsExtractVerticesAlgorithm();
60 }
61 
62 void QgsExtractVerticesAlgorithm::initAlgorithm( const QVariantMap & )
63 {
64  addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
65 
66  addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Vertices" ) ) );
67 }
68 
69 QVariantMap QgsExtractVerticesAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
70 {
71  std::unique_ptr< QgsProcessingFeatureSource > featureSource( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
72  if ( !featureSource )
73  throw QgsProcessingException( QObject::tr( "Could not load source layer for INPUT" ) );
74 
75  QgsWkbTypes::Type outputWkbType = QgsWkbTypes::Point;
76  if ( QgsWkbTypes::hasM( featureSource->wkbType() ) )
77  {
78  outputWkbType = QgsWkbTypes::addM( outputWkbType );
79  }
80  if ( QgsWkbTypes::hasZ( featureSource->wkbType() ) )
81  {
82  outputWkbType = QgsWkbTypes::addZ( outputWkbType );
83  }
84 
85  QgsFields outputFields = featureSource->fields();
86  outputFields.append( QgsField( QStringLiteral( "vertex_index" ), QVariant::Int, QString(), 10, 0 ) );
87  outputFields.append( QgsField( QStringLiteral( "vertex_part" ), QVariant::Int, QString(), 10, 0 ) );
88  if ( QgsWkbTypes::geometryType( featureSource->wkbType() ) == QgsWkbTypes::PolygonGeometry )
89  {
90  outputFields.append( QgsField( QStringLiteral( "vertex_part_ring" ), QVariant::Int, QString(), 10, 0 ) );
91  }
92  outputFields.append( QgsField( QStringLiteral( "vertex_part_index" ), QVariant::Int, QString(), 10, 0 ) );
93  outputFields.append( QgsField( QStringLiteral( "distance" ), QVariant::Double, QString(), 20, 14 ) );
94  outputFields.append( QgsField( QStringLiteral( "angle" ), QVariant::Double, QString(), 20, 14 ) );
95 
96  QString dest;
97  std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outputFields, outputWkbType, featureSource->sourceCrs() ) );
98  if ( !sink )
99  throw QgsProcessingException( QObject::tr( "Could not create destination layer for OUTPUT" ) );;
100 
101  double step = featureSource->featureCount() > 0 ? 100.0 / featureSource->featureCount() : 1;
103  QgsFeature f;
104  int i = -1;
105  while ( fi.nextFeature( f ) )
106  {
107  i++;
108  if ( feedback->isCanceled() )
109  {
110  break;
111  }
112 
113  QgsGeometry inputGeom = f.geometry();
114  if ( inputGeom.isNull() )
115  {
116  sink->addFeature( f, QgsFeatureSink::FastInsert );
117  }
118  else
119  {
121  double cumulativeDistance = 0.0;
122  int vertexPos = 0;
123  while ( vi != inputGeom.constGet()->vertices_end() )
124  {
125  QgsVertexId vertexId = vi.vertexId();
126  double angle = inputGeom.constGet()->vertexAngle( vertexId ) * 180 / M_PI;
127  QgsAttributes attrs = f.attributes();
128  attrs << vertexPos
129  << vertexId.part;
130  if ( QgsWkbTypes::geometryType( featureSource->wkbType() ) == QgsWkbTypes::PolygonGeometry )
131  {
132  attrs << vertexId.ring;
133  }
134  attrs << vertexId.vertex
135  << cumulativeDistance
136  << angle;
137  QgsFeature outputFeature = QgsFeature();
138  outputFeature.setAttributes( attrs );
139  outputFeature.setGeometry( QgsGeometry( ( *vi ).clone() ) );
140  sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
141  vi++;
142  vertexPos++;
143 
144  // calculate distance to next vertex
145  double distanceToNext = inputGeom.constGet()->segmentLength( vertexId );
146  cumulativeDistance += distanceToNext;
147  }
148  }
149  feedback->setProgress( i * step );
150  }
151 
152  QVariantMap outputs;
153  outputs.insert( QStringLiteral( "OUTPUT" ), dest );
154  return outputs;
155 }
156 
Wrapper for iterator of features from vector data provider or vector layer.
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
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...
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
QgsVertexId vertexId() const
Returns vertex ID of the current item.
void setProgress(double progress)
Sets the current progress for the feedback object.
Definition: qgsfeedback.h:63
virtual double vertexAngle(QgsVertexId vertex) const =0
Returns approximate angle at a vertex.
Container of fields for a vector layer.
Definition: qgsfields.h:42
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:111
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:62
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:768
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
A feature sink output for processing algorithms.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:67
virtual double segmentLength(QgsVertexId startVertex) const =0
Returns the length of the segment of the geometry which begins at startVertex.
static Type addM(Type type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:889
Utility class for identifying a unique vertex within a geometry.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the 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:663
static Type addZ(Type type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:864
This class wraps a request for features to a vector layer (or directly its vector data provider)...
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
bool append(const QgsField &field, FieldOrigin origin=OriginProvider, int originIndex=-1)
Append a field. The field must have unique name, otherwise it is rejected (returns false) ...
Definition: qgsfields.cpp:59
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:48
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
The vertex_iterator class provides STL-style iterator for vertices.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
An input feature source (such as vector layers) parameter for processing algorithms.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:818
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
bool nextFeature(QgsFeature &f)
A vector of attributes.
Definition: qgsattributes.h:58
Contains information about the context in which a processing algorithm is executed.
QgsAttributes attributes
Definition: qgsfeature.h:72