Skip to content

Commit 05484dc

Browse files
committedMar 6, 2018
[FEATURE][processing] Rotate features algorithm
Allows rotation of features by a set angle. The rotation can occur around a preset point or the individual feature's centroids.
1 parent f2e8c37 commit 05484dc

9 files changed

+448
-0
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://ogr.maptools.org/ rotate_around_centroid.xsd"
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1.739047663012093</gml:X><gml:Y>-3.657852097554699</gml:Y></gml:coord>
10+
<gml:coord><gml:X>10.6578520975547</gml:X><gml:Y>6.164463024388675</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:rotate_around_centroid fid="polys.0">
16+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-1.73904766301209,-0.102859347390987 -0.048574616049295,3.52237180075561 3.5766565320973,1.83189875379281 3.15403827035661,0.925590966756165 2.24773048331995,1.34820922849686 0.979875698097857,-1.37071413261309 -1.73904766301209,-0.102859347390987</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
17+
<ogr:name>aaaaa</ogr:name>
18+
<ogr:intval>33</ogr:intval>
19+
<ogr:floatval>44.123456</ogr:floatval>
20+
</ogr:rotate_around_centroid>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:rotate_around_centroid fid="polys.1">
24+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5.28174550782713,4.9375385246911 5.76543503312308,3.60861247591375 3.95281945904978,4.45384899939515 5.28174550782713,4.9375385246911</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
25+
<ogr:name>Aaaaa</ogr:name>
26+
<ogr:intval>-33</ogr:intval>
27+
<ogr:floatval>0</ogr:floatval>
28+
</ogr:rotate_around_centroid>
29+
</gml:featureMember>
30+
<gml:featureMember>
31+
<ogr:rotate_around_centroid fid="polys.2">
32+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>1.83553697561133,5.25815523735202 2.25815523735203,6.16446302438867 3.16446302438868,5.74184476264798 2.74184476264798,4.83553697561132 1.83553697561133,5.25815523735202</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
33+
<ogr:name>bbaaa</ogr:name>
34+
<ogr:floatval>0.123</ogr:floatval>
35+
</ogr:rotate_around_centroid>
36+
</gml:featureMember>
37+
<gml:featureMember>
38+
<ogr:rotate_around_centroid fid="polys.3">
39+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>7.0326209494081,1.6578520975547 10.6578520975547,-0.032620949408099 8.9673790505919,-3.6578520975547 5.3421479024453,-1.9673790505919 7.0326209494081,1.6578520975547</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>7.51631047470405,0.328926048777349 6.67107395122265,-1.48368952529595 8.48368952529595,-2.32892604877735 9.32892604877735,-0.51631047470405 7.51631047470405,0.328926048777349</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></ogr:geometryProperty>
40+
<ogr:name>ASDF</ogr:name>
41+
<ogr:intval>0</ogr:intval>
42+
</ogr:rotate_around_centroid>
43+
</gml:featureMember>
44+
<gml:featureMember>
45+
<ogr:rotate_around_centroid fid="polys.4">
46+
<ogr:intval>120</ogr:intval>
47+
<ogr:floatval>-100291.43213</ogr:floatval>
48+
</ogr:rotate_around_centroid>
49+
</gml:featureMember>
50+
<gml:featureMember>
51+
<ogr:rotate_around_centroid fid="polys.5">
52+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.03876313258057,2.24877608622643 6.33506823194982,0.074613513967679 4.64459518498703,-3.55061763417892 1.86460056032183,-0.047529013142823 3.13245534554392,2.67139434796713 4.03876313258057,2.24877608622643</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
53+
<ogr:name>elim</ogr:name>
54+
<ogr:intval>2</ogr:intval>
55+
<ogr:floatval>3.33</ogr:floatval>
56+
</ogr:rotate_around_centroid>
57+
</gml:featureMember>
58+
</ogr:FeatureCollection>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
3+
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
4+
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
5+
<xs:complexType name="FeatureCollectionType">
6+
<xs:complexContent>
7+
<xs:extension base="gml:AbstractFeatureCollectionType">
8+
<xs:attribute name="lockId" type="xs:string" use="optional"/>
9+
<xs:attribute name="scope" type="xs:string" use="optional"/>
10+
</xs:extension>
11+
</xs:complexContent>
12+
</xs:complexType>
13+
<xs:element name="rotate_around_centroid" type="ogr:rotate_around_centroid_Type" substitutionGroup="gml:_Feature"/>
14+
<xs:complexType name="rotate_around_centroid_Type">
15+
<xs:complexContent>
16+
<xs:extension base="gml:AbstractFeatureType">
17+
<xs:sequence>
18+
<xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
19+
<xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
20+
<xs:simpleType>
21+
<xs:restriction base="xs:string">
22+
<xs:maxLength value="5"/>
23+
</xs:restriction>
24+
</xs:simpleType>
25+
</xs:element>
26+
<xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
27+
<xs:simpleType>
28+
<xs:restriction base="xs:integer">
29+
<xs:totalDigits value="10"/>
30+
</xs:restriction>
31+
</xs:simpleType>
32+
</xs:element>
33+
<xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
34+
<xs:simpleType>
35+
<xs:restriction base="xs:decimal">
36+
</xs:restriction>
37+
</xs:simpleType>
38+
</xs:element>
39+
</xs:sequence>
40+
</xs:extension>
41+
</xs:complexContent>
42+
</xs:complexType>
43+
</xs:schema>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://ogr.maptools.org/ rotate_around_point.xsd"
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-2.381288744183742</gml:X><gml:Y>-5.692007337623284</gml:Y></gml:coord>
10+
<gml:coord><gml:X>8.433333436700806</gml:X><gml:Y>5.845708839632159</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:rotate_around_point fid="polys.0">
16+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>-2.38128874418374,0.769409115597709 -0.690815697220945,4.39464026374431 2.93441545092566,2.70416721678151 2.51179718918496,1.79785942974486 1.60548940214831,2.22047769148556 0.337634616926207,-0.49844566962439 -2.38128874418374,0.769409115597709</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
17+
<ogr:name>aaaaa</ogr:name>
18+
<ogr:intval>33</ogr:intval>
19+
<ogr:floatval>44.123456</ogr:floatval>
20+
</ogr:rotate_around_point>
21+
</gml:featureMember>
22+
<gml:featureMember>
23+
<ogr:rotate_around_point fid="polys.1">
24+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>5.59226754848035,3.67154626737341 6.0759570737763,2.34262021859606 4.263341499703,3.18785674207746 5.59226754848035,3.67154626737341</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
25+
<ogr:name>Aaaaa</ogr:name>
26+
<ogr:intval>-33</ogr:intval>
27+
<ogr:floatval>0</ogr:floatval>
28+
</ogr:rotate_around_point>
29+
</gml:featureMember>
30+
<gml:featureMember>
31+
<ogr:rotate_around_point fid="polys.2">
32+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.8733441873704,4.93940105259551 3.2959624491111,5.84570883963216 4.20227023614775,5.42309057789146 3.77965197440705,4.51678279085481 2.8733441873704,4.93940105259551</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
33+
<ogr:name>bbaaa</ogr:name>
34+
<ogr:floatval>0.123</ogr:floatval>
35+
</ogr:rotate_around_point>
36+
</gml:featureMember>
37+
<gml:featureMember>
38+
<ogr:rotate_around_point fid="polys.3">
39+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>4.80810228855421,-0.376303142513887 8.43333343670081,-2.06677618947669 6.74286038973801,-5.69200733762328 3.11762924159141,-4.00153429066049 4.80810228855421,-0.376303142513887</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>5.29179181385016,-1.70522919129124 4.44655529036876,-3.51784476536454 6.25917086444206,-4.36308128884593 7.10440738792346,-2.55046571477264 5.29179181385016,-1.70522919129124</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon></ogr:geometryProperty>
40+
<ogr:name>ASDF</ogr:name>
41+
<ogr:intval>0</ogr:intval>
42+
</ogr:rotate_around_point>
43+
</gml:featureMember>
44+
<gml:featureMember>
45+
<ogr:rotate_around_point fid="polys.4">
46+
<ogr:intval>120</ogr:intval>
47+
<ogr:floatval>-100291.43213</ogr:floatval>
48+
</ogr:rotate_around_point>
49+
</gml:featureMember>
50+
<gml:featureMember>
51+
<ogr:rotate_around_point fid="polys.5">
52+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>2.51179718918496,1.79785942974486 4.80810228855421,-0.376303142513887 3.11762924159141,-4.00153429066049 0.337634616926207,-0.49844566962439 1.60548940214831,2.22047769148556 2.51179718918496,1.79785942974486</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
53+
<ogr:name>elim</ogr:name>
54+
<ogr:intval>2</ogr:intval>
55+
<ogr:floatval>3.33</ogr:floatval>
56+
</ogr:rotate_around_point>
57+
</gml:featureMember>
58+
</ogr:FeatureCollection>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
3+
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
4+
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
5+
<xs:complexType name="FeatureCollectionType">
6+
<xs:complexContent>
7+
<xs:extension base="gml:AbstractFeatureCollectionType">
8+
<xs:attribute name="lockId" type="xs:string" use="optional"/>
9+
<xs:attribute name="scope" type="xs:string" use="optional"/>
10+
</xs:extension>
11+
</xs:complexContent>
12+
</xs:complexType>
13+
<xs:element name="rotate_around_point" type="ogr:rotate_around_point_Type" substitutionGroup="gml:_Feature"/>
14+
<xs:complexType name="rotate_around_point_Type">
15+
<xs:complexContent>
16+
<xs:extension base="gml:AbstractFeatureType">
17+
<xs:sequence>
18+
<xs:element name="geometryProperty" type="gml:PolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
19+
<xs:element name="name" nillable="true" minOccurs="0" maxOccurs="1">
20+
<xs:simpleType>
21+
<xs:restriction base="xs:string">
22+
<xs:maxLength value="5"/>
23+
</xs:restriction>
24+
</xs:simpleType>
25+
</xs:element>
26+
<xs:element name="intval" nillable="true" minOccurs="0" maxOccurs="1">
27+
<xs:simpleType>
28+
<xs:restriction base="xs:integer">
29+
<xs:totalDigits value="10"/>
30+
</xs:restriction>
31+
</xs:simpleType>
32+
</xs:element>
33+
<xs:element name="floatval" nillable="true" minOccurs="0" maxOccurs="1">
34+
<xs:simpleType>
35+
<xs:restriction base="xs:decimal">
36+
</xs:restriction>
37+
</xs:simpleType>
38+
</xs:element>
39+
</xs:sequence>
40+
</xs:extension>
41+
</xs:complexContent>
42+
</xs:complexType>
43+
</xs:schema>

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

+25
Original file line numberDiff line numberDiff line change
@@ -4842,3 +4842,28 @@ tests:
48424842
OUTPUT:
48434843
name: expected/segmentize_by_distance.gml
48444844
type: vector
4845+
4846+
- algorithm: native:rotatefeatures
4847+
name: Rotate around centroid
4848+
params:
4849+
ANGLE: 25.0
4850+
INPUT:
4851+
name: polys.gml
4852+
type: vector
4853+
results:
4854+
OUTPUT:
4855+
name: expected/rotate_around_centroid.gml
4856+
type: vector
4857+
4858+
- algorithm: native:rotatefeatures
4859+
name: Rotate around point
4860+
params:
4861+
ANCHOR: 2.3,3 [EPSG:4326]
4862+
ANGLE: 25.0
4863+
INPUT:
4864+
name: polys.gml
4865+
type: vector
4866+
results:
4867+
OUTPUT:
4868+
name: expected/rotate_around_point.gml
4869+
type: vector

‎src/analysis/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ SET(QGIS_ANALYSIS_SRCS
5858
processing/qgsalgorithmremoveduplicatevertices.cpp
5959
processing/qgsalgorithmremovenullgeometry.cpp
6060
processing/qgsalgorithmrenamelayer.cpp
61+
processing/qgsalgorithmrotate.cpp
6162
processing/qgsalgorithmsaveselectedfeatures.cpp
6263
processing/qgsalgorithmsegmentize.cpp
6364
processing/qgsalgorithmsimplify.cpp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
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+
20+
///@cond PRIVATE
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( "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 )
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+
147+
///@endcond
148+
149+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/***************************************************************************
2+
qgsalgorithmrotate.h
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+
#ifndef QGSALGORITHMROTATE_H
19+
#define QGSALGORITHMROTATE_H
20+
21+
#define SIP_NO_FILE
22+
23+
#include "qgis.h"
24+
#include "qgsprocessingalgorithm.h"
25+
26+
///@cond PRIVATE
27+
28+
/**
29+
* Native rotate features algorithm.
30+
*/
31+
class QgsRotateFeaturesAlgorithm : public QgsProcessingFeatureBasedAlgorithm
32+
{
33+
34+
public:
35+
36+
QgsRotateFeaturesAlgorithm() = default;
37+
QString name() const override;
38+
QString displayName() const override;
39+
QStringList tags() const override;
40+
QString group() const override;
41+
QString groupId() const override;
42+
QString shortHelpString() const override;
43+
QgsRotateFeaturesAlgorithm *createInstance() const override SIP_FACTORY;
44+
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
45+
46+
protected:
47+
QString outputName() const override;
48+
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
49+
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
50+
51+
private:
52+
53+
double mAngle = 0.0;
54+
bool mDynamicAngle = false;
55+
QgsProperty mAngleProperty;
56+
57+
bool mUseAnchor = false;
58+
QgsPointXY mAnchor;
59+
QgsCoordinateReferenceSystem mAnchorCrs;
60+
bool mTransformedAnchor = false;
61+
62+
};
63+
64+
65+
///@endcond PRIVATE
66+
67+
#endif // QGSALGORITHMROTATE_H
68+
69+

‎src/analysis/processing/qgsnativealgorithms.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "qgsalgorithmremoveduplicatevertices.h"
5656
#include "qgsalgorithmremovenullgeometry.h"
5757
#include "qgsalgorithmrenamelayer.h"
58+
#include "qgsalgorithmrotate.h"
5859
#include "qgsalgorithmsaveselectedfeatures.h"
5960
#include "qgsalgorithmsegmentize.h"
6061
#include "qgsalgorithmsimplify.h"
@@ -148,6 +149,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
148149
addAlgorithm( new QgsAlgorithmRemoveDuplicateVertices() );
149150
addAlgorithm( new QgsRemoveNullGeometryAlgorithm() );
150151
addAlgorithm( new QgsRenameLayerAlgorithm() );
152+
addAlgorithm( new QgsRotateFeaturesAlgorithm() );
151153
addAlgorithm( new QgsSaveSelectedFeatures() );
152154
addAlgorithm( new QgsSegmentizeByMaximumAngleAlgorithm() );
153155
addAlgorithm( new QgsSegmentizeByMaximumDistanceAlgorithm() );

0 commit comments

Comments
 (0)
Please sign in to comment.