QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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( "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
57QIcon QgsRectanglesOvalsDiamondsAlgorithm::icon() const
58{
59 return QgsApplication::getThemeIcon( QStringLiteral( "/algorithms/mAlgorithmRectanglesOvalsDiamonds.svg" ) );
60}
61
62QString QgsRectanglesOvalsDiamondsAlgorithm::svgIconPath() const
63{
64 return QgsApplication::iconPath( QStringLiteral( "/algorithms/mAlgorithmRectanglesOvalsDiamonds.svg" ) );
65}
66
67QString QgsRectanglesOvalsDiamondsAlgorithm::outputName() const
68{
69 return QObject::tr( "Polygon" );
70}
71
72QList<int> QgsRectanglesOvalsDiamondsAlgorithm::inputLayerTypes() const
73{
74 return QList<int>() << static_cast< int >( Qgis::ProcessingSourceType::VectorPoint );
75}
76
77Qgis::ProcessingSourceType QgsRectanglesOvalsDiamondsAlgorithm::outputLayerType() const
78{
80}
81
82Qgis::WkbType QgsRectanglesOvalsDiamondsAlgorithm::outputWkbType( Qgis::WkbType inputWkbType ) const
83{
85 if ( QgsWkbTypes::hasM( inputWkbType ) )
86 {
87 outputWkbType = QgsWkbTypes::addM( outputWkbType );
88 }
89 if ( QgsWkbTypes::hasZ( inputWkbType ) )
90 {
91 outputWkbType = QgsWkbTypes::addZ( outputWkbType );
92 }
93
94 return outputWkbType;
95}
96
97QgsRectanglesOvalsDiamondsAlgorithm *QgsRectanglesOvalsDiamondsAlgorithm::createInstance() const
98{
99 return new QgsRectanglesOvalsDiamondsAlgorithm();
100}
101
102void QgsRectanglesOvalsDiamondsAlgorithm::initParameters( const QVariantMap & )
103{
104 addParameter( new QgsProcessingParameterEnum( QStringLiteral( "SHAPE" ), QObject::tr( "Shape" ), QStringList() << QObject::tr( "Rectangle" ) << QObject::tr( "Diamond" ) << QObject::tr( "Oval" ), false, 0 ) );
105
106 auto widthParam = std::make_unique < QgsProcessingParameterDistance >( QStringLiteral( "WIDTH" ), QObject::tr( "Width" ), 1.0, QStringLiteral( "INPUT" ), false, 0.0 );
107 widthParam->setIsDynamic( true );
108 widthParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Width" ), QObject::tr( "Width" ), QgsPropertyDefinition::DoublePositive ) );
109 widthParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
110 addParameter( widthParam.release() );
111
112 auto heightParam = std::make_unique < QgsProcessingParameterDistance >( QStringLiteral( "HEIGHT" ), QObject::tr( "Height" ), 1.0, QStringLiteral( "INPUT" ), false, 0.0 );
113 heightParam->setIsDynamic( true );
114 heightParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Height" ), QObject::tr( "Height" ), QgsPropertyDefinition::DoublePositive ) );
115 heightParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
116 addParameter( heightParam.release() );
117
118 auto rotationParam = std::make_unique < QgsProcessingParameterNumber >( QStringLiteral( "ROTATION" ), QObject::tr( "Rotation" ), Qgis::ProcessingNumberParameterType::Double, 0.0, true, -360.0, 360.0 );
119 rotationParam->setIsDynamic( true );
120 rotationParam->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Rotation" ), QObject::tr( "Rotation" ), QgsPropertyDefinition::Double ) );
121 rotationParam->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
122 addParameter( rotationParam.release() );
123
124 addParameter( new QgsProcessingParameterNumber( QStringLiteral( "SEGMENTS" ), QObject::tr( "Segments" ), Qgis::ProcessingNumberParameterType::Integer, 36, false, 1 ) );
125}
126
127bool QgsRectanglesOvalsDiamondsAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
128{
129 mShape = parameterAsEnum( parameters, QStringLiteral( "SHAPE" ), context );
130
131 mWidth = parameterAsDouble( parameters, QStringLiteral( "WIDTH" ), context );
132 mDynamicWidth = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "WIDTH" ) );
133 if ( mDynamicWidth )
134 mWidthProperty = parameters.value( QStringLiteral( "WIDTH" ) ).value< QgsProperty >();
135
136 mHeight = parameterAsDouble( parameters, QStringLiteral( "HEIGHT" ), context );
137 mDynamicHeight = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "HEIGHT" ) );
138 if ( mDynamicHeight )
139 mHeightProperty = parameters.value( QStringLiteral( "HEIGHT" ) ).value< QgsProperty >();
140
141 mRotation = parameterAsDouble( parameters, QStringLiteral( "ROTATION" ), context );
142 mDynamicRotation = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ROTATION" ) );
143 if ( mDynamicRotation )
144 mRotationProperty = parameters.value( QStringLiteral( "ROTATION" ) ).value< QgsProperty >();
145
146 mSegments = parameterAsDouble( parameters, QStringLiteral( "SEGMENTS" ), context );
147
148 return true;
149}
150
151QgsFeatureList QgsRectanglesOvalsDiamondsAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
152{
153 QgsFeature outFeature = feature;
154 if ( outFeature.hasGeometry() )
155 {
156 const QgsGeometry geometry = outFeature.geometry();
157 if ( geometry.isMultipart() )
158 {
159 throw QgsProcessingException( QObject::tr( "Multipart geometry. Please promote input layer to singleparts first." ) );
160 }
161
162 double width = mWidth;
163 if ( mDynamicWidth )
164 width = mWidthProperty.valueAsDouble( context.expressionContext(), width );
165
166 double height = mHeight;
167 if ( mDynamicHeight )
168 height = mHeightProperty.valueAsDouble( context.expressionContext(), height );
169
170 double rotation = mRotation;
171 if ( mDynamicRotation )
172 rotation = mRotationProperty.valueAsDouble( context.expressionContext(), rotation );
173
174 if ( width == 0 || height == 0 )
175 {
176 throw QgsProcessingException( QObject::tr( "Width and height should be greater than 0." ) );
177 }
178
179 const double phi = rotation * M_PI / 180;
180 const double xOffset = width / 2.0;
181 const double yOffset = height / 2.0;
182 const QgsPointXY point = geometry.asPoint();
183 const double x = point.x();
184 const double y = point.y();
185
186 QVector< double > ringX( 5 );
187 QVector< double > ringY( 5 );
188
189 switch ( mShape )
190 {
191 case 0:
192 // rectangle
193 ringX = { -xOffset + x, -xOffset + x, xOffset + x, xOffset + x, -xOffset + x };
194 ringY = { -yOffset + y, yOffset + y, yOffset + y, -yOffset + y, -yOffset + y };
195 break;
196 case 1:
197 // diamond
198 ringX = { x, -xOffset + x, x, xOffset + x, x };
199 ringY = { -yOffset + y, y, yOffset + y, y, -yOffset + y };
200 break;
201 case 2:
202 // oval
203 ringX.resize( mSegments + 1 );
204 ringY.resize( mSegments + 1 );
205 for ( int i = 0; i < mSegments; i ++ )
206 {
207 const double t = ( 2 * M_PI ) / mSegments * i;
208 ringX[ i ] = xOffset * cos( t ) + x;
209 ringY[ i ] = yOffset * sin( t ) + y;
210 }
211 ringX[ mSegments ] = ringX.at( 0 );
212 ringY[ mSegments ] = ringY.at( 0 );
213 break;
214 }
215
216 if ( phi != 0 )
217 {
218 for ( int i = 0; i < ringX.size(); ++i )
219 {
220 const double px = ringX.at( i );
221 const double py = ringY.at( i );
222 ringX[ i ] = ( px - x ) * cos( phi ) + ( py - y ) * sin( phi ) + x;
223 ringY[ i ] = -( px - x ) * sin( phi ) + ( py - y ) * cos( phi ) + y;
224 }
225 }
226
227 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
228 poly->setExteriorRing( new QgsLineString( ringX, ringY ) );
229
230 if ( geometry.constGet()->is3D() )
231 {
232 poly->addZValue( static_cast< const QgsPoint * >( geometry.constGet() )->z() );
233 }
234 if ( geometry.constGet()->isMeasure() )
235 {
236 poly->addMValue( static_cast< const QgsPoint * >( geometry.constGet() )->m() );
237 }
238
239 outFeature.setGeometry( std::move( poly ) );
240 }
241
242 return QgsFeatureList() << outFeature;
243}
244
ProcessingSourceType
Processing data source types.
Definition: qgis.h:2858
@ VectorPoint
Vector point layers.
@ VectorPolygon
Vector polygon layers.
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
@ 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:56
QgsGeometry geometry
Definition: qgsfeature.h:67
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:230
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
Definition: qgsfeature.cpp:167
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:162
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.
Definition: qgslinestring.h:45
A class to represent a 2D point.
Definition: qgspointxy.h:60
double y
Definition: qgspointxy.h:64
Q_GADGET 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.
Definition: qgsexception.h:83
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.
Definition: qgsproperty.h:228
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.
Definition: qgswkbtypes.h:1092
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1068
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:973
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1023
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:917