QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsalgorithmrectanglesovalsdiamonds.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsalgorithmrectanglesovalsdiamonds.cpp
3 ---------------------
4 begin : January 2020
5 copyright : (C) 2020 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 "qgsapplication.h"
21#include "qgslinestring.h"
22#include "qgspolygon.h"
23
24#include <QString>
25
26using namespace Qt::StringLiterals;
27
29
30QString QgsRectanglesOvalsDiamondsAlgorithm::name() const
31{
32 return u"rectanglesovalsdiamonds"_s;
33}
34
35QString QgsRectanglesOvalsDiamondsAlgorithm::displayName() const
36{
37 return QObject::tr( "Rectangles, ovals, diamonds" );
38}
39
40QStringList QgsRectanglesOvalsDiamondsAlgorithm::tags() const
41{
42 return QObject::tr( "buffer,grow,fixed,variable,distance,rectangle,oval,diamond,point" ).split( ',' );
43}
44
45QString QgsRectanglesOvalsDiamondsAlgorithm::group() const
46{
47 return QObject::tr( "Vector geometry" );
48}
49
50QString QgsRectanglesOvalsDiamondsAlgorithm::groupId() const
51{
52 return u"vectorgeometry"_s;
53}
54
55QString QgsRectanglesOvalsDiamondsAlgorithm::shortHelpString() const
56{
57 return QObject::tr(
58 "This algorithm creates rectangle, oval or diamond-shaped polygons from the input point layer using "
59 "specified width, height and (optional) rotation values. Multipart inputs should be promoted "
60 "to singleparts first."
61 );
62}
63
64QString QgsRectanglesOvalsDiamondsAlgorithm::shortDescription() const
65{
66 return QObject::tr( "Creates rectangle, oval or diamond-shaped polygons from an input point layer." );
67}
68
69QIcon QgsRectanglesOvalsDiamondsAlgorithm::icon() const
70{
71 return QgsApplication::getThemeIcon( u"/algorithms/mAlgorithmRectanglesOvalsDiamonds.svg"_s );
72}
73
74QString QgsRectanglesOvalsDiamondsAlgorithm::svgIconPath() const
75{
76 return QgsApplication::iconPath( u"/algorithms/mAlgorithmRectanglesOvalsDiamonds.svg"_s );
77}
78
79QString QgsRectanglesOvalsDiamondsAlgorithm::outputName() const
80{
81 return QObject::tr( "Polygon" );
82}
83
84QList<int> QgsRectanglesOvalsDiamondsAlgorithm::inputLayerTypes() const
85{
86 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPoint );
87}
88
89Qgis::ProcessingSourceType QgsRectanglesOvalsDiamondsAlgorithm::outputLayerType() const
90{
92}
93
94Qgis::WkbType QgsRectanglesOvalsDiamondsAlgorithm::outputWkbType( Qgis::WkbType inputWkbType ) const
95{
97 if ( QgsWkbTypes::hasM( inputWkbType ) )
98 {
99 outputWkbType = QgsWkbTypes::addM( outputWkbType );
100 }
101 if ( QgsWkbTypes::hasZ( inputWkbType ) )
102 {
103 outputWkbType = QgsWkbTypes::addZ( outputWkbType );
104 }
105
106 return outputWkbType;
107}
108
109QgsRectanglesOvalsDiamondsAlgorithm *QgsRectanglesOvalsDiamondsAlgorithm::createInstance() const
110{
111 return new QgsRectanglesOvalsDiamondsAlgorithm();
112}
113
114void QgsRectanglesOvalsDiamondsAlgorithm::initParameters( const QVariantMap & )
115{
116 addParameter( new QgsProcessingParameterEnum( u"SHAPE"_s, QObject::tr( "Shape" ), QStringList() << QObject::tr( "Rectangle" ) << QObject::tr( "Diamond" ) << QObject::tr( "Oval" ), false, 0 ) );
117
118 auto widthParam = std::make_unique<QgsProcessingParameterDistance>( u"WIDTH"_s, QObject::tr( "Width" ), 1.0, u"INPUT"_s, false, 0.0 );
119 widthParam->setIsDynamic( true );
120 widthParam->setDynamicPropertyDefinition( QgsPropertyDefinition( u"Width"_s, QObject::tr( "Width" ), QgsPropertyDefinition::DoublePositive ) );
121 widthParam->setDynamicLayerParameterName( u"INPUT"_s );
122 addParameter( widthParam.release() );
123
124 auto heightParam = std::make_unique<QgsProcessingParameterDistance>( u"HEIGHT"_s, QObject::tr( "Height" ), 1.0, u"INPUT"_s, false, 0.0 );
125 heightParam->setIsDynamic( true );
126 heightParam->setDynamicPropertyDefinition( QgsPropertyDefinition( u"Height"_s, QObject::tr( "Height" ), QgsPropertyDefinition::DoublePositive ) );
127 heightParam->setDynamicLayerParameterName( u"INPUT"_s );
128 addParameter( heightParam.release() );
129
130 auto rotationParam = std::make_unique<QgsProcessingParameterNumber>( u"ROTATION"_s, QObject::tr( "Rotation" ), Qgis::ProcessingNumberParameterType::Double, 0.0, true, -360.0, 360.0 );
131 rotationParam->setIsDynamic( true );
132 rotationParam->setDynamicPropertyDefinition( QgsPropertyDefinition( u"Rotation"_s, QObject::tr( "Rotation" ), QgsPropertyDefinition::Double ) );
133 rotationParam->setDynamicLayerParameterName( u"INPUT"_s );
134 addParameter( rotationParam.release() );
135
136 addParameter( new QgsProcessingParameterNumber( u"SEGMENTS"_s, QObject::tr( "Segments" ), Qgis::ProcessingNumberParameterType::Integer, 36, false, 1 ) );
137}
138
139bool QgsRectanglesOvalsDiamondsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
140{
141 mShape = parameterAsEnum( parameters, u"SHAPE"_s, context );
142
143 mWidth = parameterAsDouble( parameters, u"WIDTH"_s, context );
144 mDynamicWidth = QgsProcessingParameters::isDynamic( parameters, u"WIDTH"_s );
145 if ( mDynamicWidth )
146 mWidthProperty = parameters.value( u"WIDTH"_s ).value<QgsProperty>();
147
148 mHeight = parameterAsDouble( parameters, u"HEIGHT"_s, context );
149 mDynamicHeight = QgsProcessingParameters::isDynamic( parameters, u"HEIGHT"_s );
150 if ( mDynamicHeight )
151 mHeightProperty = parameters.value( u"HEIGHT"_s ).value<QgsProperty>();
152
153 mRotation = parameterAsDouble( parameters, u"ROTATION"_s, context );
154 mDynamicRotation = QgsProcessingParameters::isDynamic( parameters, u"ROTATION"_s );
155 if ( mDynamicRotation )
156 mRotationProperty = parameters.value( u"ROTATION"_s ).value<QgsProperty>();
157
158 mSegments = parameterAsDouble( parameters, u"SEGMENTS"_s, context );
159
160 return true;
161}
162
163QgsFeatureList QgsRectanglesOvalsDiamondsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
164{
165 QgsFeature outFeature = feature;
166 if ( outFeature.hasGeometry() )
167 {
168 const QgsGeometry geometry = outFeature.geometry();
169 if ( geometry.isMultipart() )
170 {
171 throw QgsProcessingException( QObject::tr( "Multipart geometry. Please promote input layer to singleparts first." ) );
172 }
173
174 double width = mWidth;
175 if ( mDynamicWidth )
176 width = mWidthProperty.valueAsDouble( context.expressionContext(), width );
177
178 double height = mHeight;
179 if ( mDynamicHeight )
180 height = mHeightProperty.valueAsDouble( context.expressionContext(), height );
181
182 double rotation = mRotation;
183 if ( mDynamicRotation )
184 rotation = mRotationProperty.valueAsDouble( context.expressionContext(), rotation );
185
186 if ( width == 0 || height == 0 )
187 {
188 throw QgsProcessingException( QObject::tr( "Width and height should be greater than 0." ) );
189 }
190
191 const double phi = rotation * M_PI / 180;
192 const double xOffset = width / 2.0;
193 const double yOffset = height / 2.0;
194 const QgsPointXY point = geometry.asPoint();
195 const double x = point.x();
196 const double y = point.y();
197
198 QVector<double> ringX( 5 );
199 QVector<double> ringY( 5 );
200
201 switch ( mShape )
202 {
203 case 0:
204 // rectangle
205 ringX = { -xOffset + x, -xOffset + x, xOffset + x, xOffset + x, -xOffset + x };
206 ringY = { -yOffset + y, yOffset + y, yOffset + y, -yOffset + y, -yOffset + y };
207 break;
208 case 1:
209 // diamond
210 ringX = { x, -xOffset + x, x, xOffset + x, x };
211 ringY = { -yOffset + y, y, yOffset + y, y, -yOffset + y };
212 break;
213 case 2:
214 // oval
215 ringX.resize( mSegments + 1 );
216 ringY.resize( mSegments + 1 );
217 for ( int i = 0; i < mSegments; i++ )
218 {
219 const double t = ( 2 * M_PI ) / mSegments * i;
220 ringX[i] = xOffset * cos( t ) + x;
221 ringY[i] = yOffset * sin( t ) + y;
222 }
223 ringX[mSegments] = ringX.at( 0 );
224 ringY[mSegments] = ringY.at( 0 );
225 break;
226 }
227
228 if ( phi != 0 )
229 {
230 for ( int i = 0; i < ringX.size(); ++i )
231 {
232 const double px = ringX.at( i );
233 const double py = ringY.at( i );
234 ringX[i] = ( px - x ) * cos( phi ) + ( py - y ) * sin( phi ) + x;
235 ringY[i] = -( px - x ) * sin( phi ) + ( py - y ) * cos( phi ) + y;
236 }
237 }
238
239 auto poly = std::make_unique<QgsPolygon>();
240 poly->setExteriorRing( new QgsLineString( ringX, ringY ) );
241
242 if ( geometry.constGet()->is3D() )
243 {
244 poly->addZValue( static_cast<const QgsPoint *>( geometry.constGet() )->z() );
245 }
246 if ( geometry.constGet()->isMeasure() )
247 {
248 poly->addMValue( static_cast<const QgsPoint *>( geometry.constGet() )->m() );
249 }
250
251 outFeature.setGeometry( std::move( poly ) );
252 }
253
254 return QgsFeatureList() << outFeature;
255}
256
ProcessingSourceType
Processing data source types.
Definition qgis.h:3645
@ VectorPoint
Vector point layers.
Definition qgis.h:3648
@ VectorPolygon
Vector polygon layers.
Definition qgis.h:3650
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:294
@ Polygon
Polygon.
Definition qgis.h:298
@ Double
Double/float values.
Definition qgis.h:3921
bool isMeasure() const
Returns true if the geometry contains m values.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
Definition qgsfeature.h:60
QgsGeometry geometry
Definition qgsfeature.h:71
bool hasGeometry() const
Returns true if the feature has an associated geometry.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
Line string geometry type, with support for z-dimension and m-values.
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
double z
Definition qgspoint.h:58
double m
Definition qgspoint.h:59
Contains information about the context in which a processing algorithm is executed.
QgsExpressionContext & expressionContext()
Returns the expression context.
Custom exception class for processing related exceptions.
Base class for providing feedback from a processing algorithm.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
A numeric parameter for processing algorithms.
static bool isDynamic(const QVariantMap &parameters, const QString &name)
Returns true if the parameter with matching name is a dynamic parameter, and must be evaluated once f...
Definition for a property.
Definition qgsproperty.h:47
@ Double
Double value (including negative values).
Definition qgsproperty.h:56
@ DoublePositive
Positive double value (including 0).
Definition qgsproperty.h:57
A store for object properties.
double valueAsDouble(const QgsExpressionContext &context, double defaultValue=0.0, bool *ok=nullptr) const
Calculates the current value of the property and interprets it as a double.
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 Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
QList< QgsFeature > QgsFeatureList