QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsalgorithmrotate.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmrotate.cpp
3  ---------------------
4  begin : March 2018
5  copyright : (C) 2018 by Nyall Dawson
6  email : nyall dot dawson 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 
18 #include "qgsalgorithmrotate.h"
19 
21 
22 QString QgsRotateFeaturesAlgorithm::name() const
23 {
24  return QStringLiteral( "rotatefeatures" );
25 }
26 
27 QString QgsRotateFeaturesAlgorithm::displayName() const
28 {
29  return QObject::tr( "Rotate" );
30 }
31 
32 QStringList QgsRotateFeaturesAlgorithm::tags() const
33 {
34  return QObject::tr( "rotate,around,center,point" ).split( ',' );
35 }
36 
37 QString QgsRotateFeaturesAlgorithm::group() const
38 {
39  return QObject::tr( "Vector geometry" );
40 }
41 
42 QString QgsRotateFeaturesAlgorithm::groupId() const
43 {
44  return QStringLiteral( "vectorgeometry" );
45 }
46 
47 QString QgsRotateFeaturesAlgorithm::outputName() const
48 {
49  return QObject::tr( "Rotated" );
50 }
51 
52 QString QgsRotateFeaturesAlgorithm::shortHelpString() const
53 {
54  return QObject::tr( "This algorithm rotates feature geometries, by the specified angle clockwise" )
55  + QStringLiteral( "\n\n" )
56  + QObject::tr( "Optionally, the rotation can occur around a preset point. If not set the rotation occurs around each feature's centroid." );
57 }
58 
59 QgsRotateFeaturesAlgorithm *QgsRotateFeaturesAlgorithm::createInstance() const
60 {
61  return new QgsRotateFeaturesAlgorithm();
62 }
63 
64 void QgsRotateFeaturesAlgorithm::initParameters( const QVariantMap & )
65 {
66  std::unique_ptr< QgsProcessingParameterNumber > rotation = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "ANGLE" ),
67  QObject::tr( "Rotation (degrees clockwise)" ), QgsProcessingParameterNumber::Double,
68  0.0 );
69  rotation->setIsDynamic( true );
70  rotation->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "ANGLE" ), QObject::tr( "Rotation (degrees clockwise)" ), QgsPropertyDefinition::Rotation ) );
71  rotation->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
72  addParameter( rotation.release() );
73 
74  std::unique_ptr< QgsProcessingParameterPoint > anchor = qgis::make_unique< QgsProcessingParameterPoint >( QStringLiteral( "ANCHOR" ),
75  QObject::tr( "Rotation anchor point" ), QVariant(), true );
76  addParameter( anchor.release() );
77 }
78 
79 bool QgsRotateFeaturesAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
80 {
81  mAngle = parameterAsDouble( parameters, QStringLiteral( "ANGLE" ), context );
82  mDynamicAngle = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ANGLE" ) );
83  if ( mDynamicAngle )
84  mAngleProperty = parameters.value( QStringLiteral( "ANGLE" ) ).value< QgsProperty >();
85 
86  mUseAnchor = parameters.value( QStringLiteral( "ANCHOR" ) ).isValid();
87  if ( mUseAnchor )
88  {
89  mAnchor = parameterAsPoint( parameters, QStringLiteral( "ANCHOR" ), context );
90  mAnchorCrs = parameterAsPointCrs( parameters, QStringLiteral( "ANCHOR" ), context );
91  }
92 
93  return true;
94 }
95 
96 QgsFeatureList QgsRotateFeaturesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
97 {
98  if ( mUseAnchor && !mTransformedAnchor )
99  {
100  mTransformedAnchor = true;
101  if ( mAnchorCrs != sourceCrs() )
102  {
103  QgsCoordinateTransform ct( mAnchorCrs, sourceCrs(), context.transformContext() );
104  try
105  {
106  mAnchor = ct.transform( mAnchor );
107  }
108  catch ( QgsCsException & )
109  {
110  throw QgsProcessingException( QObject::tr( "Could not transform anchor point to destination CRS" ) );
111  }
112  }
113  }
114 
115  QgsFeature f = feature;
116  if ( f.hasGeometry() )
117  {
118  QgsGeometry geometry = f.geometry();
119 
120  double angle = mAngle;
121  if ( mDynamicAngle )
122  angle = mAngleProperty.valueAsDouble( context.expressionContext(), angle );
123 
124  if ( mUseAnchor )
125  {
126  geometry.rotate( angle, mAnchor );
127  f.setGeometry( geometry );
128  }
129  else
130  {
131  QgsGeometry centroid = geometry.centroid();
132  if ( !centroid.isNull() )
133  {
134  geometry.rotate( angle, centroid.asPoint() );
135  f.setGeometry( geometry );
136  }
137  else
138  {
139  feedback->reportError( QObject::tr( "Could not calculate centroid for feature %1: %2" ).arg( feature.id() ).arg( centroid.lastError() ) );
140  }
141  }
142  }
143  return QgsFeatureList() << f;
144 }
145 
146 
148 
149 
QgsFeatureId id
Definition: qgsfeature.h:64
Base class for providing feedback from a processing algorithm.
bool isNull() const
Returns true if the geometry is null (ie, contains no underlying geometry accessible via geometry() )...
QgsPointXY transform(const QgsPointXY &point, TransformDirection direction=ForwardTransform) const SIP_THROW(QgsCsException)
Transform the point from the source CRS to the destination CRS.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
OperationResult rotate(double rotation, const QgsPointXY &center)
Rotate this geometry around the Z axis.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
QgsPointXY asPoint() const
Returns the contents of the geometry as a 2-dimensional point.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
Rotation (value between 0-360 degrees)
Definition: qgsproperty.h:60
QString lastError() const
Returns an error string referring to the last error encountered either when this geometry was created...
Custom exception class for processing related exceptions.
Definition: qgsexception.h:82
A store for object properties.
Definition: qgsproperty.h:229
QgsExpressionContext & expressionContext()
Returns the expression context.
Definition for a property.
Definition: qgsproperty.h:46
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
QgsCoordinateTransformContext transformContext() const
Returns the coordinate transform context.
void setGeometry(const QgsGeometry &geometry)
Set the feature&#39;s geometry.
Definition: qgsfeature.cpp:137
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
Class for doing transforms between two map coordinate systems.
QgsGeometry geometry
Definition: qgsfeature.h:67
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
Contains information about the context in which a processing algorithm is executed.
virtual void reportError(const QString &error, bool fatalError=false)
Reports that the algorithm encountered an error while executing.
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...
QgsGeometry centroid() const
Returns the center of mass of a geometry.