QGIS API Documentation 3.41.0-Master (f75d66fa9f9)
Loading...
Searching...
No Matches
qgsalgorithmcheckgeometryangle.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmcheckgeometryangle.cpp
3 ---------------------
4 begin : June 2024
5 copyright : (C) 2024 by Jacky Volpes
6 email : jacky dot volpes at oslandia 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
22#include "qgspoint.h"
23#include "qgsvectorlayer.h"
25
27
28auto QgsGeometryCheckAngleAlgorithm::name() const -> QString
29{
30 return QStringLiteral( "checkgeometryangle" );
31}
32
33auto QgsGeometryCheckAngleAlgorithm::displayName() const -> QString
34{
35 return QObject::tr( "Check geometry (Angle)" );
36}
37
38auto QgsGeometryCheckAngleAlgorithm::tags() const -> QStringList
39{
40 return QObject::tr( "check,geometry,angle" ).split( ',' );
41}
42
43auto QgsGeometryCheckAngleAlgorithm::group() const -> QString
44{
45 return QObject::tr( "Check geometry" );
46}
47
48auto QgsGeometryCheckAngleAlgorithm::groupId() const -> QString
49{
50 return QStringLiteral( "checkgeometry" );
51}
52
53auto QgsGeometryCheckAngleAlgorithm::shortHelpString() const -> QString
54{
55 return QObject::tr( "This algorithm checks the angles of line or polygon geometries." );
56}
57
58auto QgsGeometryCheckAngleAlgorithm::flags() const -> Qgis::ProcessingAlgorithmFlags
59{
61}
62
63auto QgsGeometryCheckAngleAlgorithm::createInstance() const -> QgsGeometryCheckAngleAlgorithm *
64{
65 return new QgsGeometryCheckAngleAlgorithm();
66}
67
68void QgsGeometryCheckAngleAlgorithm::initAlgorithm( const QVariantMap &configuration )
69{
70 Q_UNUSED( configuration )
71
72 // inputs
73 addParameter(
75 QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ),
76 QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPolygon ) << static_cast<int>( Qgis::ProcessingSourceType::VectorLine )
77 )
78 );
79 addParameter( new QgsProcessingParameterField( QStringLiteral( "UNIQUE_ID" ), QObject::tr( "Unique feature identifier" ), QString(), QStringLiteral( "INPUT" ) ) );
80 addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MIN_ANGLE" ), QObject::tr( "min angle" ), Qgis::ProcessingNumberParameterType::Double, 0, false, 0.0, 180.0 ) );
81
82 // outputs
83 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "ERRORS" ), QObject::tr( "Error layer" ), Qgis::ProcessingSourceType::VectorPoint ) );
84 addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Output layer" ), Qgis::ProcessingSourceType::VectorAnyGeometry ) );
85
86 std::unique_ptr<QgsProcessingParameterNumber> tolerance = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "TOLERANCE" ), QObject::tr( "Tolerance" ), Qgis::ProcessingNumberParameterType::Integer, 8, false, 1, 13 );
87 tolerance->setFlags( tolerance->flags() | Qgis::ProcessingParameterFlag::Advanced );
88 addParameter( tolerance.release() );
89}
90
91auto QgsGeometryCheckAngleAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * ) -> bool
92{
93 mTolerance = parameterAsInt( parameters, QStringLiteral( "TOLERANCE" ), context );
94
95 return true;
96}
97
98
99auto QgsGeometryCheckAngleAlgorithm::outputFields() -> QgsFields
100{
101 QgsFields fields;
102 fields.append( QgsField( QStringLiteral( "gc_layerid" ), QMetaType::QString ) );
103 fields.append( QgsField( QStringLiteral( "gc_layername" ), QMetaType::QString ) );
104 fields.append( QgsField( QStringLiteral( "gc_partidx" ), QMetaType::Int ) );
105 fields.append( QgsField( QStringLiteral( "gc_ringidx" ), QMetaType::Int ) );
106 fields.append( QgsField( QStringLiteral( "gc_vertidx" ), QMetaType::Int ) );
107 fields.append( QgsField( QStringLiteral( "gc_errorx" ), QMetaType::Double ) );
108 fields.append( QgsField( QStringLiteral( "gc_errory" ), QMetaType::Double ) );
109 fields.append( QgsField( QStringLiteral( "gc_error" ), QMetaType::QString ) );
110 return fields;
111}
112
113
114auto QgsGeometryCheckAngleAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) -> QVariantMap
115{
116 QString dest_output;
117 QString dest_errors;
118 QgsProcessingFeatureSource *input = parameterAsSource( parameters, QStringLiteral( "INPUT" ), context );
119
120 QString uniqueIdFieldName( parameterAsString( parameters, QStringLiteral( "UNIQUE_ID" ), context ) );
121 int uniqueIdFieldIdx = input->fields().indexFromName( uniqueIdFieldName );
122 if ( uniqueIdFieldIdx == -1 )
123 throw QgsProcessingException( QObject::tr( "Missing field %1 in input layer" ).arg( uniqueIdFieldName ) );
124
125 const QgsField uniqueIdField = input->fields().at( uniqueIdFieldIdx );
126
127 QgsFields fields = outputFields();
128 fields.append( uniqueIdField );
129
130 const std::unique_ptr<QgsFeatureSink> sink_output( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest_output, fields, input->wkbType(), input->sourceCrs() ) );
131 if ( !sink_output )
132 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
133
134 const std::unique_ptr<QgsFeatureSink> sink_errors( parameterAsSink( parameters, QStringLiteral( "ERRORS" ), context, dest_errors, fields, Qgis::WkbType::Point, input->sourceCrs() ) );
135 if ( !sink_errors )
136 throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "ERRORS" ) ) );
137
138 QgsProcessingMultiStepFeedback multiStepFeedback( 3, feedback );
139
140 const QgsProject *project = QgsProject::instance();
141
142 const std::unique_ptr<QgsGeometryCheckContext> checkContext = std::make_unique<QgsGeometryCheckContext>( mTolerance, input->sourceCrs(), project->transformContext(), project );
143
144 // Test detection
145 QList<QgsGeometryCheckError *> checkErrors;
146 QStringList messages;
147
148 const double minAngle = parameterAsDouble( parameters, QStringLiteral( "MIN_ANGLE" ), context );
149
150 QVariantMap configurationCheck;
151 configurationCheck.insert( "minAngle", minAngle );
152 const QgsGeometryAngleCheck check( checkContext.get(), configurationCheck );
153
154 multiStepFeedback.setCurrentStep( 1 );
155 feedback->setProgressText( QObject::tr( "Preparing features…" ) );
156 QMap<QString, QgsFeaturePool *> featurePools;
157
158 QgsVectorLayer *inputLayer = input->materialize( QgsFeatureRequest() );
159 featurePools.insert( inputLayer->id(), new QgsVectorDataProviderFeaturePool( inputLayer ) );
160
161 multiStepFeedback.setCurrentStep( 2 );
162 feedback->setProgressText( QObject::tr( "Collecting errors…" ) );
163 check.collectErrors( featurePools, checkErrors, messages, feedback );
164
165 multiStepFeedback.setCurrentStep( 3 );
166 feedback->setProgressText( QObject::tr( "Exporting errors…" ) );
167 const double step { checkErrors.size() > 0 ? 100.0 / checkErrors.size() : 1 };
168 long i = 0;
169 feedback->setProgress( 0.0 );
170
171 for ( const QgsGeometryCheckError *error : checkErrors )
172 {
173 if ( feedback->isCanceled() )
174 {
175 break;
176 }
177 QgsFeature f;
178 QgsAttributes attrs = f.attributes();
179
180 attrs << error->layerId()
181 << inputLayer->name()
182 << error->vidx().part
183 << error->vidx().ring
184 << error->vidx().vertex
185 << error->location().x()
186 << error->location().y()
187 << error->value().toString()
188 << inputLayer->getFeature( error->featureId() ).attribute( uniqueIdField.name() );
189 f.setAttributes( attrs );
190
191 f.setGeometry( error->geometry() );
192 if ( !sink_output->addFeature( f, QgsFeatureSink::FastInsert ) )
193 throw QgsProcessingException( writeFeatureError( sink_output.get(), parameters, QStringLiteral( "OUTPUT" ) ) );
194
195 f.setGeometry( QgsGeometry::fromPoint( QgsPoint( error->location().x(), error->location().y() ) ) );
196 if ( !sink_errors->addFeature( f, QgsFeatureSink::FastInsert ) )
197 throw QgsProcessingException( writeFeatureError( sink_errors.get(), parameters, QStringLiteral( "ERRORS" ) ) );
198
199 i++;
200 feedback->setProgress( 100.0 * step * static_cast<double>( i ) );
201 }
202
203 QVariantMap outputs;
204 outputs.insert( QStringLiteral( "OUTPUT" ), dest_output );
205 outputs.insert( QStringLiteral( "ERRORS" ), dest_errors );
206
207 return outputs;
208}
209
The Qgis class provides global constants for use throughout the application.
Definition qgis.h:54
@ VectorAnyGeometry
Any vector layer with geometry.
@ VectorPoint
Vector point layers.
@ VectorPolygon
Vector polygon layers.
@ VectorLine
Vector line layers.
@ NoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
A vector of attributes.
This class wraps a request for features to a vector layer (or directly its vector data provider).
@ FastInsert
Use faster inserts, at the cost of updating the passed features to reflect changes made at the provid...
QgsVectorLayer * materialize(const QgsFeatureRequest &request, QgsFeedback *feedback=nullptr)
Materializes a request (query) made against this feature source, by running it over the source and re...
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.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Encapsulate a field in an attribute table or data source.
Definition qgsfield.h:53
QString name
Definition qgsfield.h:62
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:70
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
This represents an error reported by a geometry check.
static QgsGeometry fromPoint(const QgsPoint &point)
Creates a new geometry from a QgsPoint object.
QString name
Definition qgsmaplayer.h:80
QString id
Definition qgsmaplayer.h:79
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
virtual Qgis::ProcessingAlgorithmFlags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
Contains information about the context in which a processing algorithm is executed.
Custom exception class for processing related exceptions.
QgsFeatureSource subclass which proxies methods to an underlying QgsFeatureSource,...
QgsCoordinateReferenceSystem sourceCrs() const override
Returns the coordinate reference system for features in the source.
Qgis::WkbType wkbType() const override
Returns the geometry type for features returned by this source.
QgsFields fields() const override
Returns the fields associated with features in the source.
Base class for providing feedback from a processing algorithm.
Processing feedback object for multi-step operations.
A feature sink output for processing algorithms.
An input feature source (such as vector layers) parameter for processing algorithms.
A vector layer or feature source field parameter for processing algorithms.
A numeric parameter for processing algorithms.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:113
A feature pool based on a vector data provider.
Represents a vector layer which manages a vector based data sets.
Q_INVOKABLE QgsFeature getFeature(QgsFeatureId fid) const
Queries the layer for the feature with the given id.