QGIS API Documentation 3.43.0-Master (e01d6d7c4c0)
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#include "qgsapplication.h"
20#include "qgslinestring.h"
21#include "qgspolygon.h"
22
24
25QString QgsRectanglesOvalsDiamondsAlgorithm::name() const
26{
27 return QStringLiteral( "rectanglesovalsdiamonds" );
28}
29
30QString QgsRectanglesOvalsDiamondsAlgorithm::displayName() const
31{
32 return QObject::tr( "Rectangles, ovals, diamonds" );
33}
34
35QStringList QgsRectanglesOvalsDiamondsAlgorithm::tags() const
36{
37 return QObject::tr( "buffer,grow,fixed,variable,distance,rectangle,oval,diamond,point" ).split( ',' );
38}
39
40QString QgsRectanglesOvalsDiamondsAlgorithm::group() const
41{
42 return QObject::tr( "Vector geometry" );
43}
44
45QString QgsRectanglesOvalsDiamondsAlgorithm::groupId() const
46{
47 return QStringLiteral( "vectorgeometry" );
48}
49
50QString QgsRectanglesOvalsDiamondsAlgorithm::shortHelpString() const
51{
52 return QObject::tr( "This algorithm creates rectangle, oval or diamond-shaped polygons from the input point layer using "
53 "specified width, height and (optional) rotation values. Multipart inputs should be promoted "
54 "to singleparts first." );
55}
56
57QString QgsRectanglesOvalsDiamondsAlgorithm::shortDescription() const
58{
59 return QObject::tr( "Creates rectangle, oval or diamond-shaped polygons from an input point layer." );
60}
61
62QIcon QgsRectanglesOvalsDiamondsAlgorithm::icon() const
63{
64 return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmRectanglesOvalsDiamonds.svg" ) );
65}
66
67QString QgsRectanglesOvalsDiamondsAlgorithm::svgIconPath() const
68{
69 return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmRectanglesOvalsDiamonds.svg" ) );
70}
71
72QString QgsRectanglesOvalsDiamondsAlgorithm::outputName() const
73{
74 return QObject::tr( "Polygon" );
75}
76
77QList<int> QgsRectanglesOvalsDiamondsAlgorithm::inputLayerTypes() const
78{
79 return QList<int>() << static_cast<int>( Qgis::ProcessingSourceType::VectorPoint );
80}
81
82Qgis::ProcessingSourceType QgsRectanglesOvalsDiamondsAlgorithm::outputLayerType() const
83{
85}
86
87Qgis::WkbType QgsRectanglesOvalsDiamondsAlgorithm::outputWkbType( Qgis::WkbType inputWkbType ) const
88{
90 if ( QgsWkbTypes::hasM( inputWkbType ) )
91 {
92 outputWkbType = QgsWkbTypes::addM( outputWkbType );
93 }
94 if ( QgsWkbTypes::hasZ( inputWkbType ) )
95 {
96 outputWkbType = QgsWkbTypes::addZ( outputWkbType );
97 }
98
99 return outputWkbType;
100}
101
102QgsRectanglesOvalsDiamondsAlgorithm *QgsRectanglesOvalsDiamondsAlgorithm::createInstance() const
103{
104 return new QgsRectanglesOvalsDiamondsAlgorithm();
105}
106
107void QgsRectanglesOvalsDiamondsAlgorithm::initParameters( const QVariantMap & )
108{
109 addParameter( new QgsProcessingParameterEnum( QStringLiteral( "SHAPE" ), QObject::tr( "Shape" ), QStringList() << QObject::tr( "Rectangle" ) << QObject::tr( "Diamond" ) << QObject::tr( "Oval" ), false, 0 ) );
110
111 auto widthParam = std::make_unique<QgsProcessingParameterDistance>( QStringLiteral( "WIDTH" ), QObject::tr( "Width" ), 1.0, QStringLiteral( "INPUT" ), false, 0.0 );
112 widthParam->setIsDynamic( true );
113 widthParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Width" ), QObject::tr( "Width" ), QgsPropertyDefinition::DoublePositive ) );
114 widthParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
115 addParameter( widthParam.release() );
116
117 auto heightParam = std::make_unique<QgsProcessingParameterDistance>( QStringLiteral( "HEIGHT" ), QObject::tr( "Height" ), 1.0, QStringLiteral( "INPUT" ), false, 0.0 );
118 heightParam->setIsDynamic( true );
119 heightParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Height" ), QObject::tr( "Height" ), QgsPropertyDefinition::DoublePositive ) );
120 heightParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
121 addParameter( heightParam.release() );
122
123 auto rotationParam = std::make_unique<QgsProcessingParameterNumber>( QStringLiteral( "ROTATION" ), QObject::tr( "Rotation" ), Qgis::ProcessingNumberParameterType::Double, 0.0, true, -360.0, 360.0 );
124 rotationParam->setIsDynamic( true );
125 rotationParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Rotation" ), QObject::tr( "Rotation" ), QgsPropertyDefinition::Double ) );
126 rotationParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
127 addParameter( rotationParam.release() );
128
129 addParameter( new QgsProcessingParameterNumber( QStringLiteral( "SEGMENTS" ), QObject::tr( "Segments" ), Qgis::ProcessingNumberParameterType::Integer, 36, false, 1 ) );
130}
131
132bool QgsRectanglesOvalsDiamondsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
133{
134 mShape = parameterAsEnum( parameters, QStringLiteral( "SHAPE" ), context );
135
136 mWidth = parameterAsDouble( parameters, QStringLiteral( "WIDTH" ), context );
137 mDynamicWidth = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "WIDTH" ) );
138 if ( mDynamicWidth )
139 mWidthProperty = parameters.value( QStringLiteral( "WIDTH" ) ).value<QgsProperty>();
140
141 mHeight = parameterAsDouble( parameters, QStringLiteral( "HEIGHT" ), context );
142 mDynamicHeight = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "HEIGHT" ) );
143 if ( mDynamicHeight )
144 mHeightProperty = parameters.value( QStringLiteral( "HEIGHT" ) ).value<QgsProperty>();
145
146 mRotation = parameterAsDouble( parameters, QStringLiteral( "ROTATION" ), context );
147 mDynamicRotation = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ROTATION" ) );
148 if ( mDynamicRotation )
149 mRotationProperty = parameters.value( QStringLiteral( "ROTATION" ) ).value<QgsProperty>();
150
151 mSegments = parameterAsDouble( parameters, QStringLiteral( "SEGMENTS" ), context );
152
153 return true;
154}
155
156QgsFeatureList QgsRectanglesOvalsDiamondsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
157{
158 QgsFeature outFeature = feature;
159 if ( outFeature.hasGeometry() )
160 {
161 const QgsGeometry geometry = outFeature.geometry();
162 if ( geometry.isMultipart() )
163 {
164 throw QgsProcessingException( QObject::tr( "Multipart geometry. Please promote input layer to singleparts first." ) );
165 }
166
167 double width = mWidth;
168 if ( mDynamicWidth )
169 width = mWidthProperty.valueAsDouble( context.expressionContext(), width );
170
171 double height = mHeight;
172 if ( mDynamicHeight )
173 height = mHeightProperty.valueAsDouble( context.expressionContext(), height );
174
175 double rotation = mRotation;
176 if ( mDynamicRotation )
177 rotation = mRotationProperty.valueAsDouble( context.expressionContext(), rotation );
178
179 if ( width == 0 || height == 0 )
180 {
181 throw QgsProcessingException( QObject::tr( "Width and height should be greater than 0." ) );
182 }
183
184 const double phi = rotation * M_PI / 180;
185 const double xOffset = width / 2.0;
186 const double yOffset = height / 2.0;
187 const QgsPointXY point = geometry.asPoint();
188 const double x = point.x();
189 const double y = point.y();
190
191 QVector<double> ringX( 5 );
192 QVector<double> ringY( 5 );
193
194 switch ( mShape )
195 {
196 case 0:
197 // rectangle
198 ringX = { -xOffset + x, -xOffset + x, xOffset + x, xOffset + x, -xOffset + x };
199 ringY = { -yOffset + y, yOffset + y, yOffset + y, -yOffset + y, -yOffset + y };
200 break;
201 case 1:
202 // diamond
203 ringX = { x, -xOffset + x, x, xOffset + x, x };
204 ringY = { -yOffset + y, y, yOffset + y, y, -yOffset + y };
205 break;
206 case 2:
207 // oval
208 ringX.resize( mSegments + 1 );
209 ringY.resize( mSegments + 1 );
210 for ( int i = 0; i < mSegments; i++ )
211 {
212 const double t = ( 2 * M_PI ) / mSegments * i;
213 ringX[i] = xOffset * cos( t ) + x;
214 ringY[i] = yOffset * sin( t ) + y;
215 }
216 ringX[mSegments] = ringX.at( 0 );
217 ringY[mSegments] = ringY.at( 0 );
218 break;
219 }
220
221 if ( phi != 0 )
222 {
223 for ( int i = 0; i < ringX.size(); ++i )
224 {
225 const double px = ringX.at( i );
226 const double py = ringY.at( i );
227 ringX[i] = ( px - x ) * cos( phi ) + ( py - y ) * sin( phi ) + x;
228 ringY[i] = -( px - x ) * sin( phi ) + ( py - y ) * cos( phi ) + y;
229 }
230 }
231
232 auto poly = std::make_unique<QgsPolygon>();
233 poly->setExteriorRing( new QgsLineString( ringX, ringY ) );
234
235 if ( geometry.constGet()->is3D() )
236 {
237 poly->addZValue( static_cast<const QgsPoint *>( geometry.constGet() )->z() );
238 }
239 if ( geometry.constGet()->isMeasure() )
240 {
241 poly->addMValue( static_cast<const QgsPoint *>( geometry.constGet() )->m() );
242 }
243
244 outFeature.setGeometry( std::move( poly ) );
245 }
246
247 return QgsFeatureList() << outFeature;
248}
249
ProcessingSourceType
Processing data source types.
Definition qgis.h:3399
@ VectorPoint
Vector point layers.
@ VectorPolygon
Vector polygon layers.
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:256
@ Polygon
Polygon.
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:58
QgsGeometry geometry
Definition qgsfeature.h:69
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:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
double z
Definition qgspoint.h:54
double m
Definition qgspoint.h:55
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:45
@ Double
Double value (including negative values)
Definition qgsproperty.h:55
@ DoublePositive
Positive double value (including 0)
Definition qgsproperty.h:56
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 bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
QList< QgsFeature > QgsFeatureList