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