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