QGIS API Documentation  3.6.0-Noosa (5873452)
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 
23 QgsRegularPolygon::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 
52 QgsRegularPolygon::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  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 
81 QgsRegularPolygon::QgsRegularPolygon( const QgsPoint &pt1, const QgsPoint &pt2, const unsigned int numSides )
82 {
83  if ( numSides >= 3 )
84  {
85  mNumberSides = numSides;
86 
87  double azimuth = pt1.azimuth( pt2 );
88  QgsPoint pm = QgsGeometryUtils::midpoint( pt1, pt2 );
89  double length = pt1.distance( pm );
90 
91  double angle = ( 180 - ( 360 / numSides ) ) / 2.0;
92  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 == mFirstVertex )
118  );
119 }
120 
122 {
123  double azimuth = mCenter.azimuth( mFirstVertex );
124  // TODO: double inclination = mCenter.inclination(mFirstVertex);
125  mCenter = center;
126  mFirstVertex = center.project( mRadius, azimuth );
127 }
128 
130 {
131  mRadius = std::fabs( radius );
132  double azimuth = mCenter.azimuth( mFirstVertex );
133  // TODO: double inclination = mCenter.inclination(mFirstVertex);
134  mFirstVertex = mCenter.project( mRadius, azimuth );
135 }
136 
138 {
139  double azimuth = mCenter.azimuth( mFirstVertex );
140  // TODO: double inclination = mCenter.inclination(firstVertex);
141  mFirstVertex = firstVertex;
142  mCenter = mFirstVertex.project( mRadius, azimuth );
143 }
144 
145 void QgsRegularPolygon::setNumberSides( const unsigned int numSides )
146 {
147  if ( numSides >= 3 )
148  {
149  mNumberSides = numSides;
150  }
151 }
152 
154 {
155  QgsPointSequence pts;
156  if ( isEmpty() )
157  {
158  return pts;
159  }
160 
161  double azimuth = mCenter.azimuth( mFirstVertex );
162  double azimuth_add = centralAngle();
163  // TODO: inclination
164 
165  unsigned int n = 1;
166  while ( n <= mNumberSides )
167  {
168  pts.push_back( mCenter.project( mRadius, azimuth ) );
169  azimuth += azimuth_add;
170  if ( ( azimuth_add > 0 ) && ( azimuth > 180.0 ) )
171  {
172  azimuth -= 360.0;
173  }
174 
175  n++;
176  }
177 
178  return pts;
179 }
180 
182 {
183  std::unique_ptr<QgsPolygon> polygon( new QgsPolygon() );
184  if ( isEmpty() )
185  {
186  return polygon.release();
187  }
188 
189  polygon->setExteriorRing( toLineString() );
190 
191  return polygon.release();
192 }
193 
195 {
196  std::unique_ptr<QgsLineString> ext( new QgsLineString() );
197  if ( isEmpty() )
198  {
199  return ext.release();
200  }
201 
202  QgsPointSequence pts;
203  pts = points();
204 
205  ext->setPoints( pts );
206  ext->addVertex( pts.at( 0 ) ); //close regular polygon
207 
208  return ext.release();
209 }
210 
212 {
213  if ( isEmpty() || ( mNumberSides != 3 ) )
214  {
215  return QgsTriangle();
216  }
217 
218  QgsPointSequence pts;
219  pts = points();
220 
221  return QgsTriangle( pts.at( 0 ), pts.at( 1 ), pts.at( 2 ) );
222 }
223 
224 QVector<QgsTriangle> QgsRegularPolygon::triangulate() const
225 {
226  QVector<QgsTriangle> l_tri;
227  if ( isEmpty() )
228  {
229  return l_tri;
230  }
231 
232  QgsPointSequence pts;
233  pts = points();
234 
235  unsigned int n = 0;
236  while ( n < mNumberSides - 1 )
237  {
238  l_tri.append( QgsTriangle( pts.at( n ), pts.at( n + 1 ), mCenter ) );
239  n++;
240  }
241  l_tri.append( QgsTriangle( pts.at( n ), pts.at( 0 ), mCenter ) );
242 
243  return l_tri;
244 }
245 
247 {
248  // TODO: inclined circle
249  return QgsCircle( mCenter, apothem() );
250 }
251 
253 {
254  // TODO: inclined circle
255  return QgsCircle( mCenter, mRadius );
256 }
257 
258 QString QgsRegularPolygon::toString( int pointPrecision, int radiusPrecision, int anglePrecision ) const
259 {
260  QString rep;
261  if ( isEmpty() )
262  rep = QStringLiteral( "Empty" );
263  else
264  rep = QStringLiteral( "RegularPolygon (Center: %1, First Vertex: %2, Radius: %3, Azimuth: %4)" )
265  .arg( mCenter.asWkt( pointPrecision ), 0, 's' )
266  .arg( mFirstVertex.asWkt( pointPrecision ), 0, 's' )
267  .arg( qgsDoubleToString( mRadius, radiusPrecision ), 0, 'f' )
268  .arg( qgsDoubleToString( mCenter.azimuth( mFirstVertex ), anglePrecision ), 0, 'f' );
269  // TODO: inclination
270  // .arg( qgsDoubleToString( mCenter.inclination(mFirstVertex), anglePrecision ), 0, 'f' );
271 
272  return rep;
273 }
274 
276 {
277  if ( isEmpty() )
278  {
279  return 0.0;
280  }
281 
282  return ( mRadius * mRadius * mNumberSides * std::sin( centralAngle() * M_PI / 180.0 ) ) / 2;
283 }
284 
286 {
287  if ( isEmpty() )
288  {
289  return 0.0;
290  }
291 
292  return length() * mNumberSides;
293 }
294 
296 {
297  if ( isEmpty() )
298  {
299  return 0.0;
300  }
301 
302  return mRadius * 2 * std::sin( M_PI / mNumberSides );
303 }
304 
305 double QgsRegularPolygon::apothemToRadius( const double apothem, const unsigned int numSides ) const
306 {
307  return apothem / std::cos( M_PI / numSides );
308 }
309 
310 double QgsRegularPolygon::interiorAngle( const unsigned int nbSides ) const
311 {
312  return ( nbSides - 2 ) * 180 / nbSides;
313 }
314 
315 double QgsRegularPolygon::centralAngle( const unsigned int nbSides ) const
316 {
317  return 360.0 / nbSides;
318 }
319 
321 {
322  return interiorAngle( mNumberSides );
323 }
324 
326 {
327  return centralAngle( mNumberSides );
328 }
double radius() const
Returns the radius.
Circle geometry type.
Definition: qgscircle.h:43
bool operator!=(const QgsRegularPolygon &rp) const
void setFirstVertex(const QgsPoint &firstVertex)
Sets the first vertex.
QgsPoint center() const
Returns the center point of the regular polygon.
double distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate.
Definition: qgspoint.h:276
double azimuth(const QgsPoint &other) const
Calculates azimuth between this point and other one (clockwise in degree, starting from north) ...
Definition: qgspoint.cpp:624
QVector< QgsTriangle > triangulate() const
Returns a triangulation (vertices from sides to the center) of the regular polygon.
QString toString(int pointPrecision=17, int radiusPrecision=17, int anglePrecision=2) const
Returns a string representation of the regular polygon.
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:786
QgsCircle circumscribedCircle() const
Returns the circumscribed circle.
QgsPointSequence points() const
Returns a list including the vertices of the regular polygon.
bool isEmpty() const
A regular polygon is empty if radius equal to 0 or number of sides < 3.
double area() const
Returns the area.
static QgsPoint midpoint(const QgsPoint &pt1, const QgsPoint &pt2)
Returns a middle point between points pt1 and pt2.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition: qgis.h:225
double perimeter() const
Returns the perimeter.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgspoint.cpp:223
Regular Polygon geometry type.
ConstructionOption
A regular polygon can be constructed inscribed in a circle or circumscribed about a circle...
QgsRegularPolygon()=default
Constructor for QgsRegularPolygon.
void setNumberSides(unsigned int numberSides)
Sets the number of sides.
double length() const
Returns the length of a side.
QgsPoint project(double distance, double azimuth, double inclination=90.0) const
Returns a new point which correspond to this point projected by a specified distance with specified a...
Definition: qgspoint.cpp:643
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
double interiorAngle() const
Returns the measure of the interior angles in degrees.
QVector< QgsPoint > QgsPointSequence
void setCenter(const QgsPoint &center)
Sets the center point.
bool operator==(const QgsRegularPolygon &rp) const
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
QgsLineString * toLineString() const
Returns as a linestring.
double apothem() const
Returns the apothem 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 setRadius(double radius)
Sets the radius.
QgsPolygon * toPolygon() const
Returns as a polygon.
Polygon geometry type.
Definition: qgspolygon.h:31
QgsPoint firstVertex() const
Returns the first vertex (corner) of the regular polygon.
QgsTriangle toTriangle() const
Returns as a triangle.