QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
qgscircle.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscircle.cpp
3 --------------
4 begin : March 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 "qgscircle.h"
19
20#include <memory>
21#include <utility>
22
23#include "qgsgeometryutils.h"
24#include "qgslinestring.h"
25#include "qgstriangle.h"
26
28 : QgsEllipse( QgsPoint(), 0.0, 0.0, 0.0 )
29{
30}
31
36
38{
40 const double azimuth = QgsGeometryUtilsBase::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ) * 180.0 / M_PI;
41 const double radius = pt1.distance( pt2 ) / 2.0;
42
44
45 return QgsCircle( center, radius, azimuth );
46}
47
48static bool isPerpendicular( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
49{
50 // check the given point are perpendicular to x or y axis
51
52 const double yDelta_a = pt2.y() - pt1.y();
53 const double xDelta_a = pt2.x() - pt1.x();
54 const double yDelta_b = pt3.y() - pt2.y();
55 const double xDelta_b = pt3.x() - pt2.x();
56
57 if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
58 {
59 return false;
60 }
61
62 if ( std::fabs( yDelta_a ) <= epsilon )
63 {
64 return true;
65 }
66 else if ( std::fabs( yDelta_b ) <= epsilon )
67 {
68 return true;
69 }
70 else if ( std::fabs( xDelta_a ) <= epsilon )
71 {
72 return true;
73 }
74 else if ( std::fabs( xDelta_b ) <= epsilon )
75 {
76 return true;
77 }
78
79 return false;
80}
81
82QgsCircle QgsCircle::from3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
83{
84 QgsPoint p1, p2, p3;
85
86 if ( !isPerpendicular( pt1, pt2, pt3, epsilon ) )
87 {
88 p1 = pt1;
89 p2 = pt2;
90 p3 = pt3;
91 }
92 else if ( !isPerpendicular( pt1, pt3, pt2, epsilon ) )
93 {
94 p1 = pt1;
95 p2 = pt3;
96 p3 = pt2;
97 }
98 else if ( !isPerpendicular( pt2, pt1, pt3, epsilon ) )
99 {
100 p1 = pt2;
101 p2 = pt1;
102 p3 = pt3;
103 }
104 else if ( !isPerpendicular( pt2, pt3, pt1, epsilon ) )
105 {
106 p1 = pt2;
107 p2 = pt3;
108 p3 = pt1;
109 }
110 else if ( !isPerpendicular( pt3, pt2, pt1, epsilon ) )
111 {
112 p1 = pt3;
113 p2 = pt2;
114 p3 = pt1;
115 }
116 else if ( !isPerpendicular( pt3, pt1, pt2, epsilon ) )
117 {
118 p1 = pt3;
119 p2 = pt1;
120 p3 = pt2;
121 }
122 else
123 {
124 return QgsCircle();
125 }
127 double radius = -0.0;
128 // Paul Bourke's algorithm
129 const double yDelta_a = p2.y() - p1.y();
130 const double xDelta_a = p2.x() - p1.x();
131 const double yDelta_b = p3.y() - p2.y();
132 const double xDelta_b = p3.x() - p2.x();
133
134 if ( qgsDoubleNear( xDelta_a, 0.0, epsilon ) || qgsDoubleNear( xDelta_b, 0.0, epsilon ) )
135 {
136 return QgsCircle();
137 }
138
139 const double aSlope = yDelta_a / xDelta_a;
140 const double bSlope = yDelta_b / xDelta_b;
141
142 // set z and m coordinate for center
144
145 if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
146 {
147 center.setX( 0.5 * ( p2.x() + p3.x() ) );
148 center.setY( 0.5 * ( p1.y() + p2.y() ) );
149 radius = center.distance( pt1 );
150
151 return QgsCircle( center, radius );
152 }
153
154 if ( std::fabs( aSlope - bSlope ) <= epsilon )
155 {
156 return QgsCircle();
157 }
158
159 center.setX(
160 ( aSlope * bSlope * ( p1.y() - p3.y() ) + bSlope * ( p1.x() + p2.x() ) - aSlope * ( p2.x() + p3.x() ) ) / ( 2.0 * ( bSlope - aSlope ) )
161 );
162 center.setY(
163 -1.0 * ( center.x() - ( p1.x() + p2.x() ) / 2.0 ) / aSlope + ( p1.y() + p2.y() ) / 2.0
164 );
165
166 radius = center.distance( p1 );
167
168 return QgsCircle( center, radius );
169}
170
172{
173 return QgsCircle( center, diameter / 2.0, azimuth );
174}
175
176QgsCircle QgsCircle::fromCenterPoint( const QgsPoint &center, const QgsPoint &pt1 ) // cppcheck-suppress duplInheritedMember
177{
178 const double azimuth = QgsGeometryUtilsBase::lineAngle( center.x(), center.y(), pt1.x(), pt1.y() ) * 180.0 / M_PI;
179
180 QgsPoint centerPt( center );
182
183 return QgsCircle( centerPt, centerPt.distance( pt1 ), azimuth );
184}
185
186static QVector<QgsCircle> from2ParallelsLine( const QgsPoint &pt1_par1, const QgsPoint &pt2_par1, const QgsPoint &pt1_par2, const QgsPoint &pt2_par2, const QgsPoint &pt1_line1, const QgsPoint &pt2_line1, const QgsPoint &pos, double epsilon )
187{
188 const double radius = QgsGeometryUtils::perpendicularSegment( pt1_par2, pt1_par1, pt2_par1 ).length() / 2.0;
189
190 bool isInter;
191 const QgsPoint ptInter;
192 QVector<QgsCircle> circles;
193
194 QgsPoint ptInter_par1line1, ptInter_par2line1;
195 double angle1, angle2;
196 double x, y;
197 QgsGeometryUtilsBase::angleBisector( pt1_par1.x(), pt1_par1.y(), pt2_par1.x(), pt2_par1.y(), pt1_line1.x(), pt1_line1.y(), pt2_line1.x(), pt2_line1.y(), x, y, angle1 );
198 ptInter_par1line1.setX( x );
199 ptInter_par1line1.setY( y );
200
201 QgsGeometryUtilsBase::angleBisector( pt1_par2.x(), pt1_par2.y(), pt2_par2.x(), pt2_par2.y(), pt1_line1.x(), pt1_line1.y(), pt2_line1.x(), pt2_line1.y(), x, y, angle2 );
202 ptInter_par2line1.setX( x );
203 ptInter_par2line1.setY( y );
204
205 QgsPoint center;
206 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
207 if ( isInter )
208 {
209 if ( !pos.isEmpty() )
210 {
211 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
212 {
213 circles.append( QgsCircle( center, radius ) );
214 }
215 }
216 else
217 {
218 circles.append( QgsCircle( center, radius ) );
219 }
220 }
221
222 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 + 90.0 ), center, isInter, epsilon, true );
223 if ( isInter )
224 {
225 if ( !pos.isEmpty() )
226 {
227 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
228 {
229 circles.append( QgsCircle( center, radius ) );
230 }
231 }
232 else
233 {
234 circles.append( QgsCircle( center, radius ) );
235 }
236 }
237
238 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 + 90.0 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
239 if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
240 {
241 if ( !pos.isEmpty() )
242 {
243 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
244 {
245 circles.append( QgsCircle( center, radius ) );
246 }
247 }
248 else
249 {
250 circles.append( QgsCircle( center, radius ) );
251 }
252 }
253 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 + 90.0 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 + 90.0 ), center, isInter, epsilon, true );
254 if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
255 {
256 if ( !pos.isEmpty() )
257 {
258 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
259 {
260 circles.append( QgsCircle( center, radius ) );
261 }
262 }
263 else
264 {
265 circles.append( QgsCircle( center, radius ) );
266 }
267 }
268
269 return circles;
270}
271
272QVector<QgsCircle> QgsCircle::from3TangentsMulti( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon, const QgsPoint &pos )
273{
274 QgsPoint p1, p2, p3;
275 bool isIntersect_tg1tg2 = false;
276 bool isIntersect_tg1tg3 = false;
277 bool isIntersect_tg2tg3 = false;
278 QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect_tg1tg2, epsilon );
279 QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, isIntersect_tg1tg3, epsilon );
280 QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, isIntersect_tg2tg3, epsilon );
281
282 QVector<QgsCircle> circles;
283 if ( !isIntersect_tg1tg2 && !isIntersect_tg2tg3 ) // three lines are parallels
284 return circles;
285
286 if ( !isIntersect_tg1tg2 )
287 return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pos, epsilon );
288 else if ( !isIntersect_tg1tg3 )
289 return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, pt1_tg2, pt2_tg2, pos, epsilon );
290 else if ( !isIntersect_tg2tg3 )
291 return from2ParallelsLine( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pt1_tg1, pt1_tg1, pos, epsilon );
292
293 if ( p1.is3D() )
294 {
296 }
297
298 if ( p2.is3D() )
299 {
301 }
302
303 if ( p3.is3D() )
304 {
306 }
307
308 circles.append( QgsTriangle( p1, p2, p3 ).inscribedCircle() );
309 return circles;
310}
311
312QgsCircle QgsCircle::from3Tangents( const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon, const QgsPoint &pos )
313{
314 const QVector<QgsCircle> circles = from3TangentsMulti( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, epsilon, pos );
315 if ( circles.length() != 1 )
316 return QgsCircle();
317 return circles.at( 0 );
318}
319
320QgsCircle QgsCircle::minimalCircleFrom3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
321{
322 const double l1 = pt2.distance( pt3 );
323 const double l2 = pt3.distance( pt1 );
324 const double l3 = pt1.distance( pt2 );
325
326 if ( ( l1 * l1 ) - ( l2 * l2 + l3 * l3 ) >= epsilon )
327 return QgsCircle().from2Points( pt2, pt3 );
328 else if ( ( l2 * l2 ) - ( l1 * l1 + l3 * l3 ) >= epsilon )
329 return QgsCircle().from2Points( pt3, pt1 );
330 else if ( ( l3 * l3 ) - ( l1 * l1 + l2 * l2 ) >= epsilon )
331 return QgsCircle().from2Points( pt1, pt2 );
332 else
333 return QgsCircle().from3Points( pt1, pt2, pt3, epsilon );
334}
335
336int QgsCircle::intersections( const QgsCircle &other, QgsPoint &intersection1, QgsPoint &intersection2, bool useZ ) const
337{
338 if ( useZ && mCenter.is3D() && other.center().is3D() && !qgsDoubleNear( mCenter.z(), other.center().z() ) )
339 return 0;
340
341 QgsPointXY int1, int2;
342
343 const int res = QgsGeometryUtils::circleCircleIntersections( QgsPointXY( mCenter ), radius(), QgsPointXY( other.center() ), other.radius(), int1, int2 );
344 if ( res == 0 )
345 return 0;
346
347 intersection1 = QgsPoint( int1 );
348 intersection2 = QgsPoint( int2 );
349 if ( useZ && mCenter.is3D() )
350 {
351 intersection1.addZValue( mCenter.z() );
352 intersection2.addZValue( mCenter.z() );
353 }
354 return res;
355}
356
358{
360}
361
362int QgsCircle::outerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
363{
364 return QgsGeometryUtils::circleCircleOuterTangents( QgsPointXY( mCenter ), radius(), QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
365}
366
367int QgsCircle::innerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
368{
369 return QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( mCenter ), radius(), QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
370}
371
372QgsCircle QgsCircle::fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ) // cppcheck-suppress duplInheritedMember
373{
374 const double delta_x = std::fabs( pt1.x() - pt2.x() );
375 const double delta_y = std::fabs( pt1.x() - pt2.y() );
376 if ( !qgsDoubleNear( delta_x, delta_y ) )
377 {
378 return QgsCircle();
379 }
380
383
384 return QgsCircle( center, delta_x / 2.0, 0 );
385}
386
387double QgsCircle::area() const
388{
389 return M_PI * mSemiMajorAxis * mSemiMajorAxis;
390}
391
393{
394 return 2.0 * M_PI * mSemiMajorAxis;
395}
396
402
408
409QVector<QgsPoint> QgsCircle::northQuadrant() const
410{
411 QVector<QgsPoint> quad;
412 quad.append( QgsPoint( mCenter.x(), mCenter.y() + mSemiMajorAxis, mCenter.z(), mCenter.m() ) );
413 quad.append( QgsPoint( mCenter.x() + mSemiMajorAxis, mCenter.y(), mCenter.z(), mCenter.m() ) );
414 quad.append( QgsPoint( mCenter.x(), mCenter.y() - mSemiMajorAxis, mCenter.z(), mCenter.m() ) );
415 quad.append( QgsPoint( mCenter.x() - mSemiMajorAxis, mCenter.y(), mCenter.z(), mCenter.m() ) );
416
417 return quad;
418}
419
421{
422 auto circString = std::make_unique<QgsCircularString>();
424 QVector<QgsPoint> quad;
425 if ( oriented )
426 {
427 quad = quadrant();
428 }
429 else
430 {
431 quad = northQuadrant();
432 }
433 quad.append( quad.at( 0 ) );
434 for ( QVector<QgsPoint>::const_iterator it = quad.constBegin(); it != quad.constEnd(); ++it )
435 {
436 points.append( *it );
437 }
438 circString->setPoints( points );
439
440 return circString.release();
441}
442
443bool QgsCircle::contains( const QgsPoint &point, double epsilon ) const
444{
445 return ( mCenter.distance( point ) <= mSemiMajorAxis + epsilon );
446}
447
452
453QString QgsCircle::toString( int pointPrecision, int radiusPrecision, int azimuthPrecision ) const
454{
455 QString rep;
456 if ( isEmpty() )
457 rep = QStringLiteral( "Empty" );
458 else
459 rep = QStringLiteral( "Circle (Center: %1, Radius: %2, Azimuth: %3)" )
460 .arg( mCenter.asWkt( pointPrecision ), 0, 's' )
461 .arg( qgsDoubleToString( mSemiMajorAxis, radiusPrecision ), 0, 'f' )
462 .arg( qgsDoubleToString( mAzimuth, azimuthPrecision ), 0, 'f' );
463
464 return rep;
465}
466
467QDomElement QgsCircle::asGml2( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
468{
469 // Gml2 does not support curve. It will be converted to a linestring via CircularString
470 std::unique_ptr< QgsCircularString > circularString( toCircularString() );
471 const QDomElement gml = circularString->asGml2( doc, precision, ns, axisOrder );
472 return gml;
473}
474
475QDomElement QgsCircle::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
476{
478 pts << northQuadrant().at( 0 ) << northQuadrant().at( 1 ) << northQuadrant().at( 2 );
479
480 QDomElement elemCircle = doc.createElementNS( ns, QStringLiteral( "Circle" ) );
481
482 if ( isEmpty() )
483 return elemCircle;
484
485 elemCircle.appendChild( QgsGeometryUtils::pointsToGML3( pts, doc, precision, ns, mCenter.is3D(), axisOrder ) );
486 return elemCircle;
487}
488
489int QgsCircle::calculateSegments( double radius, double parameter, int minSegments, Qgis::SegmentCalculationMethod method )
490{
491 if ( radius <= 0.0 )
492 {
493 return minSegments;
494 }
495
496 if ( parameter <= 0.0 )
497 {
498 parameter = 0.01;
499 }
500
501 if ( minSegments < 3 )
502 {
503 minSegments = 3;
504 }
505
506 switch ( method )
507 {
509 return calculateSegmentsStandard( radius, parameter, minSegments );
511 return calculateSegmentsAdaptive( radius, parameter, minSegments );
513 return calculateSegmentsByAreaError( radius, parameter, minSegments );
515 return calculateSegmentsByConstant( radius, parameter, minSegments );
516 default:
517 return calculateSegmentsStandard( radius, parameter, minSegments );
518 }
519}
SegmentCalculationMethod
brief Method used to calculate the number of segments for circle approximation
Definition qgis.h:6097
@ AreaError
Calculation based on area error.
Definition qgis.h:6100
@ Adaptive
Adaptive calculation based on radius size.
Definition qgis.h:6099
@ ConstantDensity
Simple calculation with constant segment density.
Definition qgis.h:6101
@ Standard
Standard sagitta-based calculation.
Definition qgis.h:6098
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
Circle geometry type.
Definition qgscircle.h:44
static QgsCircle from2Points(const QgsPoint &pt1, const QgsPoint &pt2)
Constructs a circle by 2 points on the circle.
Definition qgscircle.cpp:37
int intersections(const QgsCircle &other, QgsPoint &intersection1, QgsPoint &intersection2, bool useZ=false) const
Calculates the intersections points between this circle and an other circle.
double radius() const
Returns the radius of the circle.
Definition qgscircle.h:299
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const
Returns a GML3 representation of the geometry.
int innerTangents(const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2) const
Calculates the inner tangent points between this circle and an other circle.
void setSemiMinorAxis(double semiMinorAxis) override
Inherited method.
int outerTangents(const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2) const
Calculates the outer tangent points between this circle and an other circle.
void setSemiMajorAxis(double semiMajorAxis) override
Inherited method.
QString toString(int pointPrecision=17, int radiusPrecision=17, int azimuthPrecision=2) const override
returns a string representation of the ellipse.
static QgsCircle from3Tangents(const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon=1E-8, const QgsPoint &pos=QgsPoint())
Constructs a circle by 3 tangents on the circle (aka inscribed circle of a triangle).
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the ellipse.
bool contains(const QgsPoint &point, double epsilon=1E-8) const
Returns true if the circle contains the point.
static QVector< QgsCircle > from3TangentsMulti(const QgsPoint &pt1_tg1, const QgsPoint &pt2_tg1, const QgsPoint &pt1_tg2, const QgsPoint &pt2_tg2, const QgsPoint &pt1_tg3, const QgsPoint &pt2_tg3, double epsilon=1E-8, const QgsPoint &pos=QgsPoint())
Returns an array of circle constructed by 3 tangents on the circle (aka inscribed circle of a triangl...
static QgsCircle fromExtent(const QgsPoint &pt1, const QgsPoint &pt2)
Constructs a circle by an extent (aka bounding box / QgsRectangle).
double area() const override
The area of the ellipse.
static QgsCircle fromCenterDiameter(const QgsPoint &center, double diameter, double azimuth=0)
Constructs a circle by a center point and a diameter.
static int calculateSegments(double radius, double parameter, int minSegments, Qgis::SegmentCalculationMethod method)
Calculates the number of segments needed to approximate a circle.
static QgsCircle fromCenterPoint(const QgsPoint &center, const QgsPoint &pt1)
Constructs a circle by a center point and another point.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const
Returns a GML2 representation of the geometry.
QgsCircularString * toCircularString(bool oriented=false) const
Returns a circular string from the circle.
double perimeter() const override
The circumference of the ellipse using first approximation of Ramanujan.
bool tangentToPoint(const QgsPointXY &p, QgsPointXY &pt1, QgsPointXY &pt2) const
Calculates the tangent points between this circle and the point p.
static QgsCircle from3Points(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon=1E-8)
Constructs a circle by 3 points on the circle.
Definition qgscircle.cpp:82
QVector< QgsPoint > northQuadrant() const
The four quadrants of the ellipse.
static QgsCircle minimalCircleFrom3Points(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon=1E-8)
Constructs the smallest circle from 3 points.
Circular string geometry type.
QgsPoint mCenter
Definition qgsellipse.h:251
QgsPoint center() const
Returns the center point.
Definition qgsellipse.h:120
double semiMajorAxis() const
Returns the semi-major axis.
Definition qgsellipse.h:126
double mAzimuth
Definition qgsellipse.h:254
virtual QgsPointSequence points(unsigned int segments=36) const
Returns a list of points with segmentation from segments.
double mSemiMajorAxis
Definition qgsellipse.h:252
double azimuth() const
Returns the azimuth.
Definition qgsellipse.h:138
virtual QVector< QgsPoint > quadrant() const
The four quadrants of the ellipse.
QgsEllipse()=default
Constructor for QgsEllipse.
virtual bool isEmpty() const
An ellipse is empty if axes are equal to 0.
double mSemiMinorAxis
Definition qgsellipse.h:253
double semiMinorAxis() const
Returns the semi-minor axis.
Definition qgsellipse.h:132
static double lineAngle(double x1, double y1, double x2, double y2)
Calculates the direction of line joining two points in radians, clockwise from the north direction.
static bool angleBisector(double aX, double aY, double bX, double bY, double cX, double cY, double dX, double dY, double &pointX, double &pointY, double &angle)
Returns the point (pointX, pointY) forming the bisector from segment (aX aY) (bX bY) and segment (bX,...
static int circleCircleIntersections(const QgsPointXY &center1, double radius1, const QgsPointXY &center2, double radius2, QgsPointXY &intersection1, QgsPointXY &intersection2)
Calculates the intersections points between the circle with center center1 and radius radius1 and the...
static int leftOfLine(const QgsPoint &point, const QgsPoint &p1, const QgsPoint &p2)
Returns a value < 0 if the point point is left of the line from p1 -> p2.
static bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
static QgsLineString perpendicularSegment(const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2)
Create a perpendicular line segment from p to segment [s1, s2].
static QgsPoint midpoint(const QgsPoint &pt1, const QgsPoint &pt2)
Returns a middle point between points pt1 and pt2.
static bool tangentPointAndCircle(const QgsPointXY &center, double radius, const QgsPointXY &p, QgsPointXY &pt1, QgsPointXY &pt2)
Calculates the tangent points between the circle with the specified center and radius and the point p...
static int circleCircleOuterTangents(const QgsPointXY &center1, double radius1, const QgsPointXY &center2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the outer tangent points for two circles, centered at center1 and center2 and with radii o...
static bool transferFirstZOrMValueToPoint(Iterator verticesBegin, Iterator verticesEnd, QgsPoint &point)
A Z or M dimension is added to point if one of the points in the list points contains Z or M value.
static QDomElement pointsToGML3(const QgsPointSequence &points, QDomDocument &doc, int precision, const QString &ns, bool is3D, QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY)
Returns a gml::posList DOM element.
static int circleCircleInnerTangents(const QgsPointXY &center1, double radius1, const QgsPointXY &center2, double radius2, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2)
Calculates the inner tangent points for two circles, centered at center1 and center2 and with radii o...
double length() const override
Returns the planar, 2-dimensional length of the geometry.
Represents a 2D point.
Definition qgspointxy.h:60
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
void setY(double y)
Sets the point's y-coordinate.
Definition qgspoint.h:337
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition qgspoint.cpp:561
void setX(double x)
Sets the point's x-coordinate.
Definition qgspoint.h:326
double z
Definition qgspoint.h:54
double x
Definition qgspoint.h:52
bool convertTo(Qgis::WkbType type) override
Converts the geometry to a specified type.
Definition qgspoint.cpp:630
bool isEmpty() const override
Returns true if the geometry is empty.
Definition qgspoint.cpp:739
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
double y
Definition qgspoint.h:53
A rectangle specified with double values.
Triangle geometry type.
Definition qgstriangle.h:33
static Qgis::WkbType dropZ(Qgis::WkbType type)
Drops the z dimension (if present) for a WKB type and returns the new type.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Definition qgis.h:6524
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
Definition qgis.h:6607
QVector< QgsPoint > QgsPointSequence