QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsregularpolygon.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsregularpolygon.cpp
3 --------------
4 begin : May 2017
5 copyright : (C) 2017 by Loîc Bartoletti
6 email : lbartoletti at tuxfamily dot org
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 "qgsregularpolygon.h"
19#include "qgsgeometryutils.h"
20
21#include <memory>
22
23QgsRegularPolygon::QgsRegularPolygon( const QgsPoint &center, const double radius, const double azimuth, const unsigned int numSides, const ConstructionOption circle )
24 : mCenter( center )
25{
26 // TODO: inclination
27
28 if ( numSides >= 3 )
29 {
30 mNumberSides = numSides;
31
32 switch ( circle )
33 {
34 case InscribedCircle:
35 {
36 mRadius = std::fabs( radius );
37 mFirstVertex = mCenter.project( mRadius, azimuth );
38 break;
39 }
41 {
42 mRadius = apothemToRadius( std::fabs( radius ), numSides );
43 mFirstVertex = mCenter.project( mRadius, azimuth - centralAngle( numSides ) / 2 );
44 break;
45 }
46 }
47
48 }
49
50}
51
52QgsRegularPolygon::QgsRegularPolygon( const QgsPoint &center, const QgsPoint &pt1, const unsigned int numSides, const ConstructionOption circle )
53 : mCenter( center )
54{
55 if ( numSides >= 3 )
56 {
57 mNumberSides = numSides;
58
59 switch ( circle )
60 {
61 case InscribedCircle:
62 {
63 mFirstVertex = pt1;
64 mRadius = center.distance( pt1 );
65 break;
66 }
68 {
69 mRadius = apothemToRadius( center.distance( pt1 ), numSides );
70 const double azimuth = center.azimuth( pt1 );
71 // TODO: inclination
72 mFirstVertex = mCenter.project( mRadius, azimuth - centralAngle( numSides ) / 2 );
73 break;
74 }
75 }
76
77 }
78
79}
80
81QgsRegularPolygon::QgsRegularPolygon( const QgsPoint &pt1, const QgsPoint &pt2, const unsigned int numSides )
82{
83 if ( numSides >= 3 )
84 {
85 mNumberSides = numSides;
86
87 const double azimuth = pt1.azimuth( pt2 );
88 const QgsPoint pm = QgsGeometryUtils::midpoint( pt1, pt2 );
89 const double length = pt1.distance( pm );
90
91 const double angle = ( 180 - ( 360 / numSides ) ) / 2.0;
92 const double hypothenuse = length / std::cos( angle * M_PI / 180 );
93 // TODO: inclination
94
95 mCenter = pt1.project( hypothenuse, azimuth + angle );
96 mFirstVertex = pt1;
97 mRadius = std::fabs( hypothenuse );
98 }
99}
100
102{
103 return ( ( mCenter == rp.mCenter ) &&
104 ( mFirstVertex == rp.mFirstVertex ) &&
105 ( mNumberSides == rp.mNumberSides )
106 );
107}
108
110{
111 return !operator==( rp );
112}
113
115{
116 return ( ( mNumberSides < 3 ) ||
117 ( mCenter.isEmpty() ) ||
118 ( mFirstVertex.isEmpty() ) ||
119 ( mCenter == mFirstVertex )
120 );
121}
122
124{
125 const double azimuth = mFirstVertex.isEmpty() ? 0 : mCenter.azimuth( mFirstVertex );
126 // TODO: double inclination = mCenter.inclination(mFirstVertex);
127 mCenter = center;
128 mFirstVertex = center.project( mRadius, azimuth );
129}
130
131void QgsRegularPolygon::setRadius( const double radius )
132{
133 mRadius = std::fabs( radius );
134 const double azimuth = mFirstVertex.isEmpty() ? 0 : mCenter.azimuth( mFirstVertex );
135 // TODO: double inclination = mCenter.inclination(mFirstVertex);
136 mFirstVertex = mCenter.project( mRadius, azimuth );
137}
138
140{
141 const double azimuth = mCenter.azimuth( mFirstVertex );
142 // TODO: double inclination = mCenter.inclination(firstVertex);
143 mFirstVertex = firstVertex;
144 mCenter = mFirstVertex.project( mRadius, azimuth );
145}
146
147void QgsRegularPolygon::setNumberSides( const unsigned int numSides )
148{
149 if ( numSides >= 3 )
150 {
151 mNumberSides = numSides;
152 }
153}
154
156{
158 if ( isEmpty() )
159 {
160 return pts;
161 }
162
163 double azimuth = mCenter.azimuth( mFirstVertex );
164 const double azimuth_add = centralAngle();
165 // TODO: inclination
166
167 unsigned int n = 1;
168 while ( n <= mNumberSides )
169 {
170 pts.push_back( mCenter.project( mRadius, azimuth ) );
171 azimuth += azimuth_add;
172 if ( ( azimuth_add > 0 ) && ( azimuth > 180.0 ) )
173 {
174 azimuth -= 360.0;
175 }
176
177 n++;
178 }
179
180 return pts;
181}
182
184{
185 std::unique_ptr<QgsPolygon> polygon( new QgsPolygon() );
186 if ( isEmpty() )
187 {
188 return polygon.release();
189 }
190
191 polygon->setExteriorRing( toLineString() );
192
193 return polygon.release();
194}
195
197{
198 std::unique_ptr<QgsLineString> ext( new QgsLineString() );
199 if ( isEmpty() )
200 {
201 return ext.release();
202 }
203
205 pts = points();
206
207 ext->setPoints( pts );
208 ext->addVertex( pts.at( 0 ) ); //close regular polygon
209
210 return ext.release();
211}
212
214{
215 if ( isEmpty() || ( mNumberSides != 3 ) )
216 {
217 return QgsTriangle();
218 }
219
221 pts = points();
222
223 return QgsTriangle( pts.at( 0 ), pts.at( 1 ), pts.at( 2 ) );
224}
225
226QVector<QgsTriangle> QgsRegularPolygon::triangulate() const
227{
228 QVector<QgsTriangle> l_tri;
229 if ( isEmpty() )
230 {
231 return l_tri;
232 }
233
235 pts = points();
236
237 unsigned int n = 0;
238 while ( n < mNumberSides - 1 )
239 {
240 l_tri.append( QgsTriangle( pts.at( n ), pts.at( n + 1 ), mCenter ) );
241 n++;
242 }
243 l_tri.append( QgsTriangle( pts.at( n ), pts.at( 0 ), mCenter ) );
244
245 return l_tri;
246}
247
249{
250 // TODO: inclined circle
251 return QgsCircle( mCenter, apothem() );
252}
253
255{
256 // TODO: inclined circle
257 return QgsCircle( mCenter, mRadius );
258}
259
260QString QgsRegularPolygon::toString( int pointPrecision, int radiusPrecision, int anglePrecision ) const
261{
262 QString rep;
263 if ( isEmpty() )
264 rep = QStringLiteral( "Empty" );
265 else
266 rep = QStringLiteral( "RegularPolygon (Center: %1, First Vertex: %2, Radius: %3, Azimuth: %4)" )
267 .arg( mCenter.asWkt( pointPrecision ), 0, 's' )
268 .arg( mFirstVertex.asWkt( pointPrecision ), 0, 's' )
269 .arg( qgsDoubleToString( mRadius, radiusPrecision ), 0, 'f' )
270 .arg( qgsDoubleToString( mCenter.azimuth( mFirstVertex ), anglePrecision ), 0, 'f' );
271 // TODO: inclination
272 // .arg( qgsDoubleToString( mCenter.inclination(mFirstVertex), anglePrecision ), 0, 'f' );
273
274 return rep;
275}
276
278{
279 if ( isEmpty() )
280 {
281 return 0.0;
282 }
283
284 return ( mRadius * mRadius * mNumberSides * std::sin( centralAngle() * M_PI / 180.0 ) ) / 2;
285}
286
288{
289 if ( isEmpty() )
290 {
291 return 0.0;
292 }
293
294 return length() * mNumberSides;
295}
296
298{
299 if ( isEmpty() )
300 {
301 return 0.0;
302 }
303
304 return mRadius * 2 * std::sin( M_PI / mNumberSides );
305}
306
307double QgsRegularPolygon::apothemToRadius( const double apothem, const unsigned int numSides ) const
308{
309 return apothem / std::cos( M_PI / numSides );
310}
311
312double QgsRegularPolygon::interiorAngle( const unsigned int nbSides ) const
313{
314 return ( nbSides - 2 ) * 180 / nbSides;
315}
316
317double QgsRegularPolygon::centralAngle( const unsigned int nbSides ) const
318{
319 return 360.0 / nbSides;
320}
321
323{
324 return interiorAngle( mNumberSides );
325}
326
328{
329 return centralAngle( mNumberSides );
330}
Circle geometry type.
Definition: qgscircle.h:43
static QgsPoint midpoint(const QgsPoint &pt1, const QgsPoint &pt2)
Returns a middle point between points pt1 and pt2.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:45
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
double azimuth(const QgsPoint &other) const
Calculates Cartesian azimuth between this point and other one (clockwise in degree,...
Definition: qgspoint.cpp:682
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgspoint.cpp:261
bool isEmpty() const override
Returns true if the geometry is empty.
Definition: qgspoint.cpp:733
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition: qgspoint.h:393
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which corresponds to this point projected by a specified distance with specified ...
Definition: qgspoint.cpp:701
Polygon geometry type.
Definition: qgspolygon.h:33
Regular Polygon geometry type.
QgsPointSequence points() const
Returns a list including the vertices of the regular polygon.
QString toString(int pointPrecision=17, int radiusPrecision=17, int anglePrecision=2) const
Returns a string representation of the regular polygon.
QgsRegularPolygon()=default
Constructor for QgsRegularPolygon.
double interiorAngle() const
Returns the measure of the interior angles in degrees.
QgsPoint center() const
Returns the center point of the regular polygon.
QgsCircle circumscribedCircle() const
Returns the circumscribed circle.
QgsPoint firstVertex() const
Returns the first vertex (corner) of the regular polygon.
QgsLineString * toLineString() const
Returns as a linestring.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle.
@ CircumscribedCircle
Circumscribed about a circle (the radius is the distance from the center to the midpoints of the side...
@ InscribedCircle
Inscribed in a circle (the radius is the distance between the center and vertices)
double length() const
Returns the length of a side.
double perimeter() const
Returns the perimeter.
QgsTriangle toTriangle() const
Returns as a triangle.
double radius() const
Returns the radius.
void setNumberSides(unsigned int numberSides)
Sets the number of sides.
void setCenter(const QgsPoint &center)
Sets the center point.
QgsPolygon * toPolygon() const
Returns as a polygon.
bool operator==(const QgsRegularPolygon &rp) const
bool operator!=(const QgsRegularPolygon &rp) const
double area() const
Returns the area.
bool isEmpty() const
A regular polygon is empty if radius equal to 0 or number of sides < 3.
double apothem() const
Returns the apothem of the regular polygon.
void setRadius(double radius)
Sets the radius.
QVector< QgsTriangle > triangulate() const
Returns a triangulation (vertices from sides to the center) of the regular polygon.
double centralAngle() const
Returns the measure of the central angle (the angle subtended at the center of the polygon by one of ...
void setFirstVertex(const QgsPoint &firstVertex)
Sets the first vertex.
QgsCircle inscribedCircle() const
Returns the inscribed circle.
Triangle geometry type.
Definition: qgstriangle.h:33
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:716
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:5124
QVector< QgsPoint > QgsPointSequence