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