QGIS API Documentation 3.99.0-Master (e9821da5c6b)
Loading...
Searching...
No Matches
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 : lituus at free dot fr
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
20#include <memory>
21
22#include "qgsgeometryutils.h"
23
24#include <QString>
25
26using namespace Qt::StringLiterals;
27
28QgsRegularPolygon::QgsRegularPolygon( const QgsPoint &center, const double radius, const double azimuth, const unsigned int numSides, const ConstructionOption circle )
29 : mCenter( center )
30{
31 // TODO: inclination
32
33 if ( numSides >= 3 )
34 {
35 mNumberSides = numSides;
36
37 switch ( circle )
38 {
39 case InscribedCircle:
40 {
41 mRadius = std::fabs( radius );
42 mFirstVertex = mCenter.project( mRadius, azimuth );
43 break;
44 }
46 {
47 mRadius = apothemToRadius( std::fabs( radius ), numSides );
48 mFirstVertex = mCenter.project( mRadius, azimuth - centralAngle( numSides ) / 2 );
49 break;
50 }
51 }
52
53 }
54
55}
56
57QgsRegularPolygon::QgsRegularPolygon( const QgsPoint &center, const QgsPoint &pt1, const unsigned int numSides, const ConstructionOption circle )
58 : mCenter( center )
59{
60 if ( numSides >= 3 )
61 {
62 mNumberSides = numSides;
63
64 switch ( circle )
65 {
66 case InscribedCircle:
67 {
68 mFirstVertex = pt1;
69 mRadius = center.distance( pt1 );
70 break;
71 }
73 {
74 mRadius = apothemToRadius( center.distance( pt1 ), numSides );
75 const double azimuth = center.azimuth( pt1 );
76 // TODO: inclination
77 mFirstVertex = mCenter.project( mRadius, azimuth - centralAngle( numSides ) / 2 );
78 break;
79 }
80 }
81
82 }
83
84}
85
86QgsRegularPolygon::QgsRegularPolygon( const QgsPoint &pt1, const QgsPoint &pt2, const unsigned int numSides )
87{
88 if ( numSides >= 3 )
89 {
90 mNumberSides = numSides;
91
92 const double azimuth = pt1.azimuth( pt2 );
93 const QgsPoint pm = QgsGeometryUtils::midpoint( pt1, pt2 );
94 const double length = pt1.distance( pm );
95
96 const double angle = ( 180 - ( 360 / numSides ) ) / 2.0;
97 const double hypothenuse = length / std::cos( angle * M_PI / 180 );
98 // TODO: inclination
99
100 mCenter = pt1.project( hypothenuse, azimuth + angle );
101 mFirstVertex = pt1;
102 mRadius = std::fabs( hypothenuse );
103 }
104}
105
107{
108 return ( ( mCenter == rp.mCenter ) &&
109 ( mFirstVertex == rp.mFirstVertex ) &&
110 ( mNumberSides == rp.mNumberSides )
111 );
112}
113
115{
116 return !operator==( rp );
117}
118
120{
121 return ( ( mNumberSides < 3 ) ||
122 ( mCenter.isEmpty() ) ||
123 ( mFirstVertex.isEmpty() ) ||
124 ( mCenter == mFirstVertex )
125 );
126}
127
129{
130 const double azimuth = mFirstVertex.isEmpty() ? 0 : mCenter.azimuth( mFirstVertex );
131 // TODO: double inclination = mCenter.inclination(mFirstVertex);
132 mCenter = center;
133 mFirstVertex = center.project( mRadius, azimuth );
134}
135
137{
138 mRadius = std::fabs( radius );
139 const double azimuth = mFirstVertex.isEmpty() ? 0 : mCenter.azimuth( mFirstVertex );
140 // TODO: double inclination = mCenter.inclination(mFirstVertex);
141 mFirstVertex = mCenter.project( mRadius, azimuth );
142}
143
145{
146 const double azimuth = mCenter.azimuth( mFirstVertex );
147 // TODO: double inclination = mCenter.inclination(firstVertex);
148 mFirstVertex = firstVertex;
149 mCenter = mFirstVertex.project( mRadius, azimuth );
150}
151
152void QgsRegularPolygon::setNumberSides( const unsigned int numSides )
153{
154 if ( numSides >= 3 )
155 {
156 mNumberSides = numSides;
157 }
158}
159
161{
163 if ( isEmpty() )
164 {
165 return pts;
166 }
167
168 double azimuth = mCenter.azimuth( mFirstVertex );
169 const double azimuth_add = centralAngle();
170 // TODO: inclination
171
172 unsigned int n = 1;
173 while ( n <= mNumberSides )
174 {
175 pts.push_back( mCenter.project( mRadius, azimuth ) );
176 azimuth += azimuth_add;
177 if ( ( azimuth_add > 0 ) && ( azimuth > 180.0 ) )
178 {
179 azimuth -= 360.0;
180 }
181
182 n++;
183 }
184
185 return pts;
186}
187
189{
190 auto polygon = std::make_unique<QgsPolygon>();
191 if ( isEmpty() )
192 {
193 return polygon.release();
194 }
195
196 polygon->setExteriorRing( toLineString() );
197
198 return polygon.release();
199}
200
202{
203 auto ext = std::make_unique<QgsLineString>();
204 if ( isEmpty() )
205 {
206 return ext.release();
207 }
208
210 pts = points();
211
212 ext->setPoints( pts );
213 ext->addVertex( pts.at( 0 ) ); //close regular polygon
214
215 return ext.release();
216}
217
219{
220 if ( isEmpty() || ( mNumberSides != 3 ) )
221 {
222 return QgsTriangle();
223 }
224
226 pts = points();
227
228 return QgsTriangle( pts.at( 0 ), pts.at( 1 ), pts.at( 2 ) );
229}
230
231QVector<QgsTriangle> QgsRegularPolygon::triangulate() const
232{
233 QVector<QgsTriangle> l_tri;
234 if ( isEmpty() )
235 {
236 return l_tri;
237 }
238
240 pts = points();
241
242 unsigned int n = 0;
243 while ( n < mNumberSides - 1 )
244 {
245 l_tri.append( QgsTriangle( pts.at( n ), pts.at( n + 1 ), mCenter ) );
246 n++;
247 }
248 l_tri.append( QgsTriangle( pts.at( n ), pts.at( 0 ), mCenter ) );
249
250 return l_tri;
251}
252
254{
255 // TODO: inclined circle
256 return QgsCircle( mCenter, apothem() );
257}
258
260{
261 // TODO: inclined circle
262 return QgsCircle( mCenter, mRadius );
263}
264
265QString QgsRegularPolygon::toString( int pointPrecision, int radiusPrecision, int anglePrecision ) const
266{
267 QString rep;
268 if ( isEmpty() )
269 rep = u"Empty"_s;
270 else
271 rep = u"RegularPolygon (Center: %1, First Vertex: %2, Radius: %3, Azimuth: %4)"_s
272 .arg( mCenter.asWkt( pointPrecision ), 0, 's' )
273 .arg( mFirstVertex.asWkt( pointPrecision ), 0, 's' )
274 .arg( qgsDoubleToString( mRadius, radiusPrecision ), 0, 'f' )
275 .arg( qgsDoubleToString( mCenter.azimuth( mFirstVertex ), anglePrecision ), 0, 'f' );
276 // TODO: inclination
277 // .arg( qgsDoubleToString( mCenter.inclination(mFirstVertex), anglePrecision ), 0, 'f' );
278
279 return rep;
280}
281
283{
284 if ( isEmpty() )
285 {
286 return 0.0;
287 }
288
289 return ( mRadius * mRadius * mNumberSides * std::sin( centralAngle() * M_PI / 180.0 ) ) / 2;
290}
291
293{
294 if ( isEmpty() )
295 {
296 return 0.0;
297 }
298
299 return length() * mNumberSides;
300}
301
303{
304 if ( isEmpty() )
305 {
306 return 0.0;
307 }
308
309 return mRadius * 2 * std::sin( M_PI / mNumberSides );
310}
311
312double QgsRegularPolygon::apothemToRadius( const double apothem, const unsigned int numSides ) const
313{
314 return apothem / std::cos( M_PI / numSides );
315}
316
317double QgsRegularPolygon::interiorAngle( const unsigned int nbSides ) const
318{
319 return ( nbSides - 2 ) * 180 / nbSides;
320}
321
322double QgsRegularPolygon::centralAngle( const unsigned int nbSides ) const
323{
324 return 360.0 / nbSides;
325}
326
328{
329 return interiorAngle( mNumberSides );
330}
331
333{
334 return centralAngle( mNumberSides );
335}
Circle geometry type.
Definition qgscircle.h:46
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.
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
double azimuth(const QgsPoint &other) const
Calculates Cartesian azimuth between this point and other one (clockwise in degree,...
Definition qgspoint.cpp:693
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition qgspoint.h:391
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:710
Polygon geometry type.
Definition qgspolygon.h:37
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
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6841
QVector< QgsPoint > QgsPointSequence