Branch data Line data Source code
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 : : 18 : : #include "qgsalgorithmextractvertices.h" 19 : : 20 : : #include "qgsabstractgeometry.h" 21 : : #include "qgsgeometryutils.h" 22 : : 23 : : ///@cond PRIVATE 24 : : 25 : 0 : QString QgsExtractVerticesAlgorithm::name() const 26 : : { 27 : 0 : return QStringLiteral( "extractvertices" ); 28 : : } 29 : : 30 : 0 : QString QgsExtractVerticesAlgorithm::displayName() const 31 : : { 32 : 0 : return QObject::tr( "Extract vertices" ); 33 : : } 34 : : 35 : 0 : QStringList QgsExtractVerticesAlgorithm::tags() const 36 : : { 37 : 0 : return QObject::tr( "points,vertex,nodes" ).split( ',' ); 38 : 0 : } 39 : : 40 : 0 : QString QgsExtractVerticesAlgorithm::group() const 41 : : { 42 : 0 : return QObject::tr( "Vector geometry" ); 43 : : } 44 : : 45 : 0 : QString QgsExtractVerticesAlgorithm::groupId() const 46 : : { 47 : 0 : return QStringLiteral( "vectorgeometry" ); 48 : : } 49 : : 50 : 0 : QString QgsExtractVerticesAlgorithm::shortHelpString() const 51 : : { 52 : 0 : 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 : 0 : QStringLiteral( "\n\n" ) + 54 : 0 : 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 : 0 : } 56 : : 57 : 0 : QString QgsExtractVerticesAlgorithm::outputName() const 58 : : { 59 : 0 : return QObject::tr( "Vertices" ); 60 : : } 61 : : 62 : 0 : QgsExtractVerticesAlgorithm *QgsExtractVerticesAlgorithm::createInstance() const 63 : : { 64 : 0 : return new QgsExtractVerticesAlgorithm(); 65 : : } 66 : : 67 : 0 : QgsProcessing::SourceType QgsExtractVerticesAlgorithm::outputLayerType() const 68 : : { 69 : 0 : return QgsProcessing::TypeVectorPoint; 70 : : } 71 : : 72 : 0 : QgsFields QgsExtractVerticesAlgorithm::outputFields( const QgsFields &inputFields ) const 73 : : { 74 : 0 : QgsFields outputFields = inputFields; 75 : 0 : outputFields.append( QgsField( QStringLiteral( "vertex_index" ), QVariant::Int, QString(), 10, 0 ) ); 76 : 0 : outputFields.append( QgsField( QStringLiteral( "vertex_part" ), QVariant::Int, QString(), 10, 0 ) ); 77 : 0 : if ( mGeometryType == QgsWkbTypes::PolygonGeometry ) 78 : : { 79 : 0 : outputFields.append( QgsField( QStringLiteral( "vertex_part_ring" ), QVariant::Int, QString(), 10, 0 ) ); 80 : 0 : } 81 : 0 : outputFields.append( QgsField( QStringLiteral( "vertex_part_index" ), QVariant::Int, QString(), 10, 0 ) ); 82 : 0 : outputFields.append( QgsField( QStringLiteral( "distance" ), QVariant::Double, QString(), 20, 14 ) ); 83 : 0 : outputFields.append( QgsField( QStringLiteral( "angle" ), QVariant::Double, QString(), 20, 14 ) ); 84 : : 85 : 0 : return outputFields; 86 : 0 : } 87 : : 88 : 0 : QgsWkbTypes::Type QgsExtractVerticesAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const 89 : : { 90 : 0 : QgsWkbTypes::Type outputWkbType = QgsWkbTypes::Point; 91 : 0 : if ( QgsWkbTypes::hasM( inputWkbType ) ) 92 : : { 93 : 0 : outputWkbType = QgsWkbTypes::addM( outputWkbType ); 94 : 0 : } 95 : 0 : if ( QgsWkbTypes::hasZ( inputWkbType ) ) 96 : : { 97 : 0 : outputWkbType = QgsWkbTypes::addZ( outputWkbType ); 98 : 0 : } 99 : : 100 : 0 : return outputWkbType; 101 : : } 102 : : 103 : 0 : QgsProcessingFeatureSource::Flag QgsExtractVerticesAlgorithm::sourceFlags() const 104 : : { 105 : 0 : return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks; 106 : : } 107 : : 108 : 0 : QgsFeatureSink::SinkFlags QgsExtractVerticesAlgorithm::sinkFlags() const 109 : : { 110 : 0 : return QgsFeatureSink::RegeneratePrimaryKey; 111 : : } 112 : : 113 : 0 : bool QgsExtractVerticesAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) 114 : : { 115 : 0 : std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) ); 116 : 0 : mGeometryType = QgsWkbTypes::geometryType( source->wkbType() ); 117 : : return true; 118 : 0 : } 119 : : 120 : 0 : QgsFeatureList QgsExtractVerticesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * ) 121 : : { 122 : 0 : QgsFeatureList outputFeatures; 123 : : 124 : 0 : QgsFeature f = feature; 125 : 0 : QgsGeometry inputGeom = f.geometry(); 126 : 0 : if ( inputGeom.isNull() ) 127 : : { 128 : 0 : QgsAttributes attrs = f.attributes(); 129 : 0 : attrs << QVariant() 130 : 0 : << QVariant(); 131 : 0 : if ( mGeometryType == QgsWkbTypes::PolygonGeometry ) 132 : : { 133 : 0 : attrs << QVariant(); 134 : 0 : } 135 : 0 : attrs << QVariant() 136 : 0 : << QVariant() 137 : 0 : << QVariant(); 138 : : 139 : 0 : f.setAttributes( attrs ); 140 : 0 : outputFeatures << f; 141 : 0 : } 142 : : else 143 : : { 144 : 0 : QgsAbstractGeometry::vertex_iterator vi = inputGeom.constGet()->vertices_begin(); 145 : 0 : double cumulativeDistance = 0.0; 146 : 0 : int vertexPos = 0; 147 : 0 : while ( vi != inputGeom.constGet()->vertices_end() ) 148 : : { 149 : 0 : QgsVertexId vertexId = vi.vertexId(); 150 : 0 : double angle = inputGeom.constGet()->vertexAngle( vertexId ) * 180 / M_PI; 151 : 0 : QgsAttributes attrs = f.attributes(); 152 : 0 : attrs << vertexPos 153 : 0 : << vertexId.part; 154 : 0 : if ( mGeometryType == QgsWkbTypes::PolygonGeometry ) 155 : : { 156 : 0 : attrs << vertexId.ring; 157 : 0 : } 158 : 0 : attrs << vertexId.vertex 159 : 0 : << cumulativeDistance 160 : 0 : << angle; 161 : : 162 : 0 : QgsFeature outputFeature = QgsFeature(); 163 : 0 : outputFeature.setAttributes( attrs ); 164 : 0 : outputFeature.setGeometry( QgsGeometry( ( *vi ).clone() ) ); 165 : 0 : outputFeatures << outputFeature; 166 : 0 : vi++; 167 : 0 : vertexPos++; 168 : : 169 : : // calculate distance to next vertex 170 : 0 : double distanceToNext = inputGeom.constGet()->segmentLength( vertexId ); 171 : 0 : cumulativeDistance += distanceToNext; 172 : 0 : } 173 : : } 174 : : 175 : 0 : return outputFeatures; 176 : 0 : } 177 : : 178 : : ///@endcond