QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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.isEmpty() ) ||
118  ( mFirstVertex.isEmpty() ) ||
119  ( mCenter == mFirstVertex )
120  );
121 }
122 
124 {
125  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 
132 {
133  mRadius = std::fabs( radius );
134  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  double azimuth = mCenter.azimuth( mFirstVertex );
142  // TODO: double inclination = mCenter.inclination(firstVertex);
143  mFirstVertex = firstVertex;
144  mCenter = mFirstVertex.project( mRadius, azimuth );
145 }
146 
147 void QgsRegularPolygon::setNumberSides( const unsigned int numSides )
148 {
149  if ( numSides >= 3 )
150  {
151  mNumberSides = numSides;
152  }
153 }
154 
156 {
157  QgsPointSequence pts;
158  if ( isEmpty() )
159  {
160  return pts;
161  }
162 
163  double azimuth = mCenter.azimuth( mFirstVertex );
164  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 
204  QgsPointSequence pts;
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 
220  QgsPointSequence pts;
221  pts = points();
222 
223  return QgsTriangle( pts.at( 0 ), pts.at( 1 ), pts.at( 2 ) );
224 }
225 
226 QVector<QgsTriangle> QgsRegularPolygon::triangulate() const
227 {
228  QVector<QgsTriangle> l_tri;
229  if ( isEmpty() )
230  {
231  return l_tri;
232  }
233 
234  QgsPointSequence pts;
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 
260 QString 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 
307 double QgsRegularPolygon::apothemToRadius( const double apothem, const unsigned int numSides ) const
308 {
309  return apothem / std::cos( M_PI / numSides );
310 }
311 
312 double QgsRegularPolygon::interiorAngle( const unsigned int nbSides ) const
313 {
314  return ( nbSides - 2 ) * 180 / nbSides;
315 }
316 
317 double 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 }
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 Cartesian 2D distance between this point and a specified x, y coordinate.
Definition: qgspoint.h:325
double azimuth(const QgsPoint &other) const
Calculates Cartesian azimuth between this point and other one (clockwise in degree, starting from north)
Definition: qgspoint.cpp:656
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:240
double perimeter() const
Returns the perimeter.
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition: qgspoint.cpp:229
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:675
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 isEmpty() const override
Returns true if the geometry is empty.
Definition: qgspoint.cpp:702
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.