QGIS API Documentation 3.41.0-Master (88383c3d16f)
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#include "qgslinestring.h"
20#include "qgsgeometryutils.h"
21#include "qgstriangle.h"
22
23#include <memory>
24#include <utility>
25
27 : QgsEllipse( QgsPoint(), 0.0, 0.0, 0.0 )
28{
29}
30
31QgsCircle::QgsCircle( const QgsPoint &center, double radius, double azimuth )
32 : QgsEllipse( center, radius, radius, azimuth )
33{
34}
35
37{
39 const double azimuth = QgsGeometryUtilsBase::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ) * 180.0 / M_PI;
40 const double radius = pt1.distance( pt2 ) / 2.0;
41
43
44 return QgsCircle( center, radius, azimuth );
45}
46
47static bool isPerpendicular( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
48{
49 // check the given point are perpendicular to x or y axis
50
51 const double yDelta_a = pt2.y() - pt1.y();
52 const double xDelta_a = pt2.x() - pt1.x();
53 const double yDelta_b = pt3.y() - pt2.y();
54 const double xDelta_b = pt3.x() - pt2.x();
55
56 if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
57 {
58 return false;
59 }
60
61 if ( std::fabs( yDelta_a ) <= epsilon )
62 {
63 return true;
64 }
65 else if ( std::fabs( yDelta_b ) <= epsilon )
66 {
67 return true;
68 }
69 else if ( std::fabs( xDelta_a ) <= epsilon )
70 {
71 return true;
72 }
73 else if ( std::fabs( xDelta_b ) <= epsilon )
74 {
75 return true;
76 }
77
78 return false;
79}
80
81QgsCircle QgsCircle::from3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
82{
83 QgsPoint p1, p2, p3;
84
85 if ( !isPerpendicular( pt1, pt2, pt3, epsilon ) )
86 {
87 p1 = pt1;
88 p2 = pt2;
89 p3 = pt3;
90 }
91 else if ( !isPerpendicular( pt1, pt3, pt2, epsilon ) )
92 {
93 p1 = pt1;
94 p2 = pt3;
95 p3 = pt2;
96 }
97 else if ( !isPerpendicular( pt2, pt1, pt3, epsilon ) )
98 {
99 p1 = pt2;
100 p2 = pt1;
101 p3 = pt3;
102 }
103 else if ( !isPerpendicular( pt2, pt3, pt1, epsilon ) )
104 {
105 p1 = pt2;
106 p2 = pt3;
107 p3 = pt1;
108 }
109 else if ( !isPerpendicular( pt3, pt2, pt1, epsilon ) )
110 {
111 p1 = pt3;
112 p2 = pt2;
113 p3 = pt1;
114 }
115 else if ( !isPerpendicular( pt3, pt1, pt2, epsilon ) )
116 {
117 p1 = pt3;
118 p2 = pt1;
119 p3 = pt2;
120 }
121 else
122 {
123 return QgsCircle();
124 }
126 double radius = -0.0;
127 // Paul Bourke's algorithm
128 const double yDelta_a = p2.y() - p1.y();
129 const double xDelta_a = p2.x() - p1.x();
130 const double yDelta_b = p3.y() - p2.y();
131 const double xDelta_b = p3.x() - p2.x();
132
133 if ( qgsDoubleNear( xDelta_a, 0.0, epsilon ) || qgsDoubleNear( xDelta_b, 0.0, epsilon ) )
134 {
135 return QgsCircle();
136 }
137
138 const double aSlope = yDelta_a / xDelta_a;
139 const double bSlope = yDelta_b / xDelta_b;
140
141 // set z and m coordinate for center
143
144 if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
145 {
146 center.setX( 0.5 * ( p2.x() + p3.x() ) );
147 center.setY( 0.5 * ( p1.y() + p2.y() ) );
148 radius = center.distance( pt1 );
149
150 return QgsCircle( center, radius );
151 }
152
153 if ( std::fabs( aSlope - bSlope ) <= epsilon )
154 {
155 return QgsCircle();
156 }
157
158 center.setX(
159 ( aSlope * bSlope * ( p1.y() - p3.y() ) + bSlope * ( p1.x() + p2.x() ) - aSlope * ( p2.x() + p3.x() ) ) / ( 2.0 * ( bSlope - aSlope ) )
160 );
161 center.setY(
162 -1.0 * ( center.x() - ( p1.x() + p2.x() ) / 2.0 ) / aSlope + ( p1.y() + p2.y() ) / 2.0
163 );
164
165 radius = center.distance( p1 );
166
167 return QgsCircle( center, radius );
168}
169
170QgsCircle QgsCircle::fromCenterDiameter( const QgsPoint &center, double diameter, double azimuth )
171{
172 return QgsCircle( center, diameter / 2.0, azimuth );
173}
174
175QgsCircle QgsCircle::fromCenterPoint( const QgsPoint &center, const QgsPoint &pt1 ) // cppcheck-suppress duplInheritedMember
176{
177 const double azimuth = QgsGeometryUtilsBase::lineAngle( center.x(), center.y(), pt1.x(), pt1.y() ) * 180.0 / M_PI;
178
179 QgsPoint centerPt( center );
181
182 return QgsCircle( centerPt, centerPt.distance( pt1 ), azimuth );
183}
184
185static 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 )
186{
187 const double radius = QgsGeometryUtils::perpendicularSegment( pt1_par2, pt1_par1, pt2_par1 ).length() / 2.0;
188
189 bool isInter;
190 const QgsPoint ptInter;
191 QVector<QgsCircle> circles;
192
193 QgsPoint ptInter_par1line1, ptInter_par2line1;
194 double angle1, angle2;
195 double x, y;
196 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 );
197 ptInter_par1line1.setX( x );
198 ptInter_par1line1.setY( y );
199
200 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 );
201 ptInter_par2line1.setX( x );
202 ptInter_par2line1.setY( y );
203
204 QgsPoint center;
205 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
206 if ( isInter )
207 {
208 if ( !pos.isEmpty() )
209 {
210 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
211 {
212 circles.append( QgsCircle( center, radius ) );
213 }
214 }
215 else
216 {
217 circles.append( QgsCircle( center, radius ) );
218 }
219 }
220
221 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 + 90.0 ), center, isInter, epsilon, true );
222 if ( isInter )
223 {
224 if ( !pos.isEmpty() )
225 {
226 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
227 {
228 circles.append( QgsCircle( center, radius ) );
229 }
230 }
231 else
232 {
233 circles.append( QgsCircle( center, radius ) );
234 }
235 }
236
237 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 + 90.0 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
238 if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
239 {
240 if ( !pos.isEmpty() )
241 {
242 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
243 {
244 circles.append( QgsCircle( center, radius ) );
245 }
246 }
247 else
248 {
249 circles.append( QgsCircle( center, radius ) );
250 }
251 }
252 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 );
253 if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
254 {
255 if ( !pos.isEmpty() )
256 {
257 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
258 {
259 circles.append( QgsCircle( center, radius ) );
260 }
261 }
262 else
263 {
264 circles.append( QgsCircle( center, radius ) );
265 }
266 }
267
268 return circles;
269}
270
271QVector<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 )
272{
273 QgsPoint p1, p2, p3;
274 bool isIntersect_tg1tg2 = false;
275 bool isIntersect_tg1tg3 = false;
276 bool isIntersect_tg2tg3 = false;
277 QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect_tg1tg2, epsilon );
278 QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, isIntersect_tg1tg3, epsilon );
279 QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, isIntersect_tg2tg3, epsilon );
280
281 QVector<QgsCircle> circles;
282 if ( !isIntersect_tg1tg2 && !isIntersect_tg2tg3 ) // three lines are parallels
283 return circles;
284
285 if ( !isIntersect_tg1tg2 )
286 return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pos, epsilon );
287 else if ( !isIntersect_tg1tg3 )
288 return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, pt1_tg2, pt2_tg2, pos, epsilon );
289 else if ( !isIntersect_tg2tg3 )
290 return from2ParallelsLine( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pt1_tg1, pt1_tg1, pos, epsilon );
291
292 if ( p1.is3D() )
293 {
295 }
296
297 if ( p2.is3D() )
298 {
300 }
301
302 if ( p3.is3D() )
303 {
305 }
306
307 circles.append( QgsTriangle( p1, p2, p3 ).inscribedCircle() );
308 return circles;
309}
310
311QgsCircle 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 )
312{
313 const QVector<QgsCircle> circles = from3TangentsMulti( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, epsilon, pos );
314 if ( circles.length() != 1 )
315 return QgsCircle();
316 return circles.at( 0 );
317}
318
319QgsCircle QgsCircle::minimalCircleFrom3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
320{
321 const double l1 = pt2.distance( pt3 );
322 const double l2 = pt3.distance( pt1 );
323 const double l3 = pt1.distance( pt2 );
324
325 if ( ( l1 * l1 ) - ( l2 * l2 + l3 * l3 ) >= epsilon )
326 return QgsCircle().from2Points( pt2, pt3 );
327 else if ( ( l2 * l2 ) - ( l1 * l1 + l3 * l3 ) >= epsilon )
328 return QgsCircle().from2Points( pt3, pt1 );
329 else if ( ( l3 * l3 ) - ( l1 * l1 + l2 * l2 ) >= epsilon )
330 return QgsCircle().from2Points( pt1, pt2 );
331 else
332 return QgsCircle().from3Points( pt1, pt2, pt3, epsilon );
333}
334
335int QgsCircle::intersections( const QgsCircle &other, QgsPoint &intersection1, QgsPoint &intersection2, bool useZ ) const
336{
337 if ( useZ && mCenter.is3D() && other.center().is3D() && !qgsDoubleNear( mCenter.z(), other.center().z() ) )
338 return 0;
339
340 QgsPointXY int1, int2;
341
342 const int res = QgsGeometryUtils::circleCircleIntersections( QgsPointXY( mCenter ), radius(), QgsPointXY( other.center() ), other.radius(), int1, int2 );
343 if ( res == 0 )
344 return 0;
345
346 intersection1 = QgsPoint( int1 );
347 intersection2 = QgsPoint( int2 );
348 if ( useZ && mCenter.is3D() )
349 {
350 intersection1.addZValue( mCenter.z() );
351 intersection2.addZValue( mCenter.z() );
352 }
353 return res;
354}
355
357{
359}
360
361int QgsCircle::outerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
362{
363 return QgsGeometryUtils::circleCircleOuterTangents( QgsPointXY( mCenter ), radius(), QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
364}
365
366int QgsCircle::innerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
367{
368 return QgsGeometryUtils::circleCircleInnerTangents( QgsPointXY( mCenter ), radius(), QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
369}
370
371QgsCircle QgsCircle::fromExtent( const QgsPoint &pt1, const QgsPoint &pt2 ) // cppcheck-suppress duplInheritedMember
372{
373 const double delta_x = std::fabs( pt1.x() - pt2.x() );
374 const double delta_y = std::fabs( pt1.x() - pt2.y() );
375 if ( !qgsDoubleNear( delta_x, delta_y ) )
376 {
377 return QgsCircle();
378 }
379
382
383 return QgsCircle( center, delta_x / 2.0, 0 );
384}
385
386double QgsCircle::area() const
387{
388 return M_PI * mSemiMajorAxis * mSemiMajorAxis;
389}
390
392{
393 return 2.0 * M_PI * mSemiMajorAxis;
394}
395
396void QgsCircle::setSemiMajorAxis( const double semiMajorAxis )
397{
398 mSemiMajorAxis = std::fabs( semiMajorAxis );
400}
401
402void QgsCircle::setSemiMinorAxis( const double semiMinorAxis )
403{
404 mSemiMajorAxis = std::fabs( semiMinorAxis );
406}
407
408QVector<QgsPoint> QgsCircle::northQuadrant() const
409{
410 QVector<QgsPoint> quad;
411 quad.append( QgsPoint( mCenter.x(), mCenter.y() + mSemiMajorAxis, mCenter.z(), mCenter.m() ) );
412 quad.append( QgsPoint( mCenter.x() + mSemiMajorAxis, mCenter.y(), mCenter.z(), mCenter.m() ) );
413 quad.append( QgsPoint( mCenter.x(), mCenter.y() - mSemiMajorAxis, mCenter.z(), mCenter.m() ) );
414 quad.append( QgsPoint( mCenter.x() - mSemiMajorAxis, mCenter.y(), mCenter.z(), mCenter.m() ) );
415
416 return quad;
417}
418
420{
421 auto circString = std::make_unique<QgsCircularString>();
423 QVector<QgsPoint> quad;
424 if ( oriented )
425 {
426 quad = quadrant();
427 }
428 else
429 {
430 quad = northQuadrant();
431 }
432 quad.append( quad.at( 0 ) );
433 for ( QVector<QgsPoint>::const_iterator it = quad.constBegin(); it != quad.constEnd(); ++it )
434 {
435 points.append( *it );
436 }
437 circString->setPoints( points );
438
439 return circString.release();
440}
441
442bool QgsCircle::contains( const QgsPoint &point, double epsilon ) const
443{
444 return ( mCenter.distance( point ) <= mSemiMajorAxis + epsilon );
445}
446
451
452QString QgsCircle::toString( int pointPrecision, int radiusPrecision, int azimuthPrecision ) const
453{
454 QString rep;
455 if ( isEmpty() )
456 rep = QStringLiteral( "Empty" );
457 else
458 rep = QStringLiteral( "Circle (Center: %1, Radius: %2, Azimuth: %3)" )
459 .arg( mCenter.asWkt( pointPrecision ), 0, 's' )
460 .arg( qgsDoubleToString( mSemiMajorAxis, radiusPrecision ), 0, 'f' )
461 .arg( qgsDoubleToString( mAzimuth, azimuthPrecision ), 0, 'f' );
462
463 return rep;
464}
465
466QDomElement QgsCircle::asGml2( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
467{
468 // Gml2 does not support curve. It will be converted to a linestring via CircularString
469 std::unique_ptr< QgsCircularString > circularString( toCircularString() );
470 const QDomElement gml = circularString->asGml2( doc, precision, ns, axisOrder );
471 return gml;
472}
473
474QDomElement QgsCircle::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
475{
477 pts << northQuadrant().at( 0 ) << northQuadrant().at( 1 ) << northQuadrant().at( 2 );
478
479 QDomElement elemCircle = doc.createElementNS( ns, QStringLiteral( "Circle" ) );
480
481 if ( isEmpty() )
482 return elemCircle;
483
484 elemCircle.appendChild( QgsGeometryUtils::pointsToGML3( pts, doc, precision, ns, mCenter.is3D(), axisOrder ) );
485 return elemCircle;
486}
487
488int QgsCircle::calculateSegments( double radius, double parameter, int minSegments, Qgis::SegmentCalculationMethod method )
489{
490 if ( radius <= 0.0 )
491 {
492 return minSegments;
493 }
494
495 if ( parameter <= 0.0 )
496 {
497 parameter = 0.01;
498 }
499
500 if ( minSegments < 3 )
501 {
502 minSegments = 3;
503 }
504
505 switch ( method )
506 {
508 return calculateSegmentsStandard( radius, parameter, minSegments );
510 return calculateSegmentsAdaptive( radius, parameter, minSegments );
512 return calculateSegmentsByAreaError( radius, parameter, minSegments );
514 return calculateSegmentsByConstant( radius, parameter, minSegments );
515 default:
516 return calculateSegmentsStandard( radius, parameter, minSegments );
517 }
518}
SegmentCalculationMethod
brief Method used to calculate the number of segments for circle approximation
Definition qgis.h:5774
@ AreaError
Calculation based on area error.
@ Adaptive
Adaptive calculation based on radius size.
@ ConstantDensity
Simple calculation with constant segment density.
@ Standard
Standard sagitta-based calculation.
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:45
static QgsCircle from2Points(const QgsPoint &pt1, const QgsPoint &pt2)
Constructs a circle by 2 points on the circle.
Definition qgscircle.cpp:36
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:300
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:81
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.
Ellipse geometry type.
Definition qgsellipse.h:39
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.
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.
A class to represent 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:343
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
Definition qgspoint.cpp:558
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition qgspoint.cpp:266
void setX(double x)
Sets the point's x-coordinate.
Definition qgspoint.h:332
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:627
bool isEmpty() const override
Returns true if the geometry is empty.
Definition qgspoint.cpp:738
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition qgspoint.h:393
double m
Definition qgspoint.h:55
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:706
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:6042
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:6125
QVector< QgsPoint > QgsPointSequence
int precision