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 *
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}
31
32QgsCircle::QgsCircle( const QgsPoint &center, double radius, double azimuth ) :
34{
35
36}
37
39{
41 const double azimuth = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ) * 180.0 / M_PI;
42 const double radius = pt1.distance( pt2 ) / 2.0;
43
45
46 return QgsCircle( center, radius, azimuth );
47}
48
49static bool isPerpendicular( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
50{
51 // check the given point are perpendicular to x or y axis
52
53 const double yDelta_a = pt2.y() - pt1.y();
54 const double xDelta_a = pt2.x() - pt1.x();
55 const double yDelta_b = pt3.y() - pt2.y();
56 const double xDelta_b = pt3.x() - pt2.x();
57
58 if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
59 {
60 return false;
61 }
62
63 if ( std::fabs( yDelta_a ) <= epsilon )
64 {
65 return true;
66 }
67 else if ( std::fabs( yDelta_b ) <= epsilon )
68 {
69 return true;
70 }
71 else if ( std::fabs( xDelta_a ) <= epsilon )
72 {
73 return true;
74 }
75 else if ( std::fabs( xDelta_b ) <= epsilon )
76 {
77 return true;
78 }
79
80 return false;
81
82}
83
84QgsCircle QgsCircle::from3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
85{
86 QgsPoint p1, p2, p3;
87
88 if ( !isPerpendicular( pt1, pt2, pt3, epsilon ) )
89 {
90 p1 = pt1;
91 p2 = pt2;
92 p3 = pt3;
93 }
94 else if ( !isPerpendicular( pt1, pt3, pt2, epsilon ) )
95 {
96 p1 = pt1;
97 p2 = pt3;
98 p3 = pt2;
99 }
100 else if ( !isPerpendicular( pt2, pt1, pt3, epsilon ) )
101 {
102 p1 = pt2;
103 p2 = pt1;
104 p3 = pt3;
105 }
106 else if ( !isPerpendicular( pt2, pt3, pt1, epsilon ) )
107 {
108 p1 = pt2;
109 p2 = pt3;
110 p3 = pt1;
111 }
112 else if ( !isPerpendicular( pt3, pt2, pt1, epsilon ) )
113 {
114 p1 = pt3;
115 p2 = pt2;
116 p3 = pt1;
117 }
118 else if ( !isPerpendicular( pt3, pt1, pt2, epsilon ) )
119 {
120 p1 = pt3;
121 p2 = pt1;
122 p3 = pt2;
123 }
124 else
125 {
126 return QgsCircle();
127 }
130 // Paul Bourke's algorithm
131 const double yDelta_a = p2.y() - p1.y();
132 const double xDelta_a = p2.x() - p1.x();
133 const double yDelta_b = p3.y() - p2.y();
134 const double xDelta_b = p3.x() - p2.x();
135
136 if ( qgsDoubleNear( xDelta_a, 0.0, epsilon ) || qgsDoubleNear( xDelta_b, 0.0, epsilon ) )
137 {
138 return QgsCircle();
139 }
140
141 const double aSlope = yDelta_a / xDelta_a;
142 const double bSlope = yDelta_b / xDelta_b;
143
144 // set z and m coordinate for center
146
147 if ( ( std::fabs( xDelta_a ) <= epsilon ) && ( std::fabs( yDelta_b ) <= epsilon ) )
148 {
149 center.setX( 0.5 * ( p2.x() + p3.x() ) );
150 center.setY( 0.5 * ( p1.y() + p2.y() ) );
151 radius = center.distance( pt1 );
152
153 return QgsCircle( center, radius );
154 }
155
156 if ( std::fabs( aSlope - bSlope ) <= epsilon )
157 {
158 return QgsCircle();
159 }
160
161 center.setX(
162 ( aSlope * bSlope * ( p1.y() - p3.y() ) +
163 bSlope * ( p1.x() + p2.x() ) -
164 aSlope * ( p2.x() + p3.x() ) ) /
165 ( 2.0 * ( bSlope - aSlope ) )
166 );
167 center.setY(
168 -1.0 * ( center.x() - ( p1.x() + p2.x() ) / 2.0 ) /
169 aSlope + ( p1.y() + p2.y() ) / 2.0
170 );
171
172 radius = center.distance( p1 );
173
174 return QgsCircle( center, radius );
175}
176
177QgsCircle QgsCircle::fromCenterDiameter( const QgsPoint &center, double diameter, double azimuth )
178{
179 return QgsCircle( center, diameter / 2.0, azimuth );
180}
181
183{
184 const double azimuth = QgsGeometryUtils::lineAngle( center.x(), center.y(), pt1.x(), pt1.y() ) * 180.0 / M_PI;
185
186 QgsPoint centerPt( center );
188
189 return QgsCircle( centerPt, centerPt.distance( pt1 ), azimuth );
190}
191
192static 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 )
193{
194 const double radius = QgsGeometryUtils::perpendicularSegment( pt1_par2, pt1_par1, pt2_par1 ).length() / 2.0;
195
196 bool isInter;
197 const QgsPoint ptInter;
198 QVector<QgsCircle> circles;
199
200 QgsPoint ptInter_par1line1, ptInter_par2line1;
201 double angle1, angle2;
202 double x, y;
203 QgsGeometryUtils::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 );
204 ptInter_par1line1.setX( x );
205 ptInter_par1line1.setY( y );
206
207 QgsGeometryUtils::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 );
208 ptInter_par2line1.setX( x );
209 ptInter_par2line1.setY( y );
210
211 QgsPoint center;
212 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
213 if ( isInter )
214 {
215 if ( !pos.isEmpty() )
216 {
217 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
218 {
219 circles.append( QgsCircle( center, radius ) );
220 }
221 }
222 else
223 {
224 circles.append( QgsCircle( center, radius ) );
225 }
226 }
227
228 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 + 90.0 ), center, isInter, epsilon, true );
229 if ( isInter )
230 {
231 if ( !pos.isEmpty() )
232 {
233 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
234 {
235 circles.append( QgsCircle( center, radius ) );
236 }
237 }
238 else
239 {
240 circles.append( QgsCircle( center, radius ) );
241 }
242 }
243
244 QgsGeometryUtils::segmentIntersection( ptInter_par1line1, ptInter_par1line1.project( 1.0, angle1 + 90.0 ), ptInter_par2line1, ptInter_par2line1.project( 1.0, angle2 ), center, isInter, epsilon, true );
245 if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
246 {
247 if ( !pos.isEmpty() )
248 {
249 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
250 {
251 circles.append( QgsCircle( center, radius ) );
252 }
253 }
254 else
255 {
256 circles.append( QgsCircle( center, radius ) );
257 }
258 }
259 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 );
260 if ( isInter && !circles.contains( QgsCircle( center, radius ) ) )
261 {
262 if ( !pos.isEmpty() )
263 {
264 if ( QgsGeometryUtils::leftOfLine( center, pt1_line1, pt2_line1 ) == QgsGeometryUtils::leftOfLine( pos, pt1_line1, pt2_line1 ) )
265 {
266 circles.append( QgsCircle( center, radius ) );
267 }
268 }
269 else
270 {
271 circles.append( QgsCircle( center, radius ) );
272 }
273 }
274
275 return circles;
276}
277
278QVector<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 )
279{
280 QgsPoint p1, p2, p3;
281 bool isIntersect_tg1tg2 = false;
282 bool isIntersect_tg1tg3 = false;
283 bool isIntersect_tg2tg3 = false;
284 QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect_tg1tg2, epsilon );
285 QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, isIntersect_tg1tg3, epsilon );
286 QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, isIntersect_tg2tg3, epsilon );
287
288 QVector<QgsCircle> circles;
289 if ( !isIntersect_tg1tg2 && !isIntersect_tg2tg3 ) // three lines are parallels
290 return circles;
291
292 if ( !isIntersect_tg1tg2 )
293 return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pos, epsilon );
294 else if ( !isIntersect_tg1tg3 )
295 return from2ParallelsLine( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, pt1_tg2, pt2_tg2, pos, epsilon );
296 else if ( !isIntersect_tg2tg3 )
297 return from2ParallelsLine( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, pt1_tg1, pt1_tg1, pos, epsilon );
298
299 if ( p1.is3D() )
300 {
302 }
303
304 if ( p2.is3D() )
305 {
307 }
308
309 if ( p3.is3D() )
310 {
312 }
313
314 circles.append( QgsTriangle( p1, p2, p3 ).inscribedCircle() );
315 return circles;
316}
317
318QgsCircle 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 )
319{
320 const QVector<QgsCircle> circles = from3TangentsMulti( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, epsilon, pos );
321 if ( circles.length() != 1 )
322 return QgsCircle();
323 return circles.at( 0 );
324}
325
326QgsCircle QgsCircle::minimalCircleFrom3Points( const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon )
327{
328 const double l1 = pt2.distance( pt3 );
329 const double l2 = pt3.distance( pt1 );
330 const double l3 = pt1.distance( pt2 );
331
332 if ( ( l1 * l1 ) - ( l2 * l2 + l3 * l3 ) >= epsilon )
333 return QgsCircle().from2Points( pt2, pt3 );
334 else if ( ( l2 * l2 ) - ( l1 * l1 + l3 * l3 ) >= epsilon )
335 return QgsCircle().from2Points( pt3, pt1 );
336 else if ( ( l3 * l3 ) - ( l1 * l1 + l2 * l2 ) >= epsilon )
337 return QgsCircle().from2Points( pt1, pt2 );
338 else
339 return QgsCircle().from3Points( pt1, pt2, pt3, epsilon );
340}
341
342int QgsCircle::intersections( const QgsCircle &other, QgsPoint &intersection1, QgsPoint &intersection2, bool useZ ) const
343{
344 if ( useZ && mCenter.is3D() && other.center().is3D() && !qgsDoubleNear( mCenter.z(), other.center().z() ) )
345 return 0;
346
347 QgsPointXY int1, int2;
348
351 int1, int2 );
352 if ( res == 0 )
353 return 0;
354
355 intersection1 = QgsPoint( int1 );
356 intersection2 = QgsPoint( int2 );
357 if ( useZ && mCenter.is3D() )
358 {
361 }
362 return res;
363}
364
366{
368}
369
370int QgsCircle::outerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
371{
373 QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
374}
375
376int QgsCircle::innerTangents( const QgsCircle &other, QgsPointXY &line1P1, QgsPointXY &line1P2, QgsPointXY &line2P1, QgsPointXY &line2P2 ) const
377{
379 QgsPointXY( other.center() ), other.radius(), line1P1, line1P2, line2P1, line2P2 );
380}
381
383{
384 const double delta_x = std::fabs( pt1.x() - pt2.x() );
385 const double delta_y = std::fabs( pt1.x() - pt2.y() );
386 if ( !qgsDoubleNear( delta_x, delta_y ) )
387 {
388 return QgsCircle();
389 }
390
393
394 return QgsCircle( center, delta_x / 2.0, 0 );
395}
396
397double QgsCircle::area() const
398{
399 return M_PI * mSemiMajorAxis * mSemiMajorAxis;
400}
401
403{
404 return 2.0 * M_PI * mSemiMajorAxis;
405}
406
407void QgsCircle::setSemiMajorAxis( const double semiMajorAxis )
408{
409 mSemiMajorAxis = std::fabs( semiMajorAxis );
411}
412
413void QgsCircle::setSemiMinorAxis( const double semiMinorAxis )
414{
415 mSemiMajorAxis = std::fabs( semiMinorAxis );
417}
418
420{
422 quad.append( QgsPoint( mCenter.x(), mCenter.y() + mSemiMajorAxis, mCenter.z(), mCenter.m() ) );
423 quad.append( QgsPoint( mCenter.x() + mSemiMajorAxis, mCenter.y(), mCenter.z(), mCenter.m() ) );
424 quad.append( QgsPoint( mCenter.x(), mCenter.y() - mSemiMajorAxis, mCenter.z(), mCenter.m() ) );
425 quad.append( QgsPoint( mCenter.x() - mSemiMajorAxis, mCenter.y(), mCenter.z(), mCenter.m() ) );
426
428}
429
431{
432 std::unique_ptr<QgsCircularString> circString( new QgsCircularString() );
435 if ( oriented )
436 {
438 }
439 else
440 {
442 }
444 for ( QVector<QgsPoint>::const_iterator it = quad.constBegin(); it != quad.constEnd(); ++it )
445 {
446 points.append( *it );
447 }
448 circString->setPoints( points );
449
450 return circString.release();
451}
452
453bool QgsCircle::contains( const QgsPoint &point, double epsilon ) const
454{
455 return ( mCenter.distance( point ) <= mSemiMajorAxis + epsilon );
456}
457
462
463QString QgsCircle::toString( int pointPrecision, int radiusPrecision, int azimuthPrecision ) const
464{
465 QString rep;
466 if ( isEmpty() )
467 rep = QStringLiteral( "Empty" );
468 else
469 rep = QStringLiteral( "Circle (Center: %1, Radius: %2, Azimuth: %3)" )
470 .arg( mCenter.asWkt( pointPrecision ), 0, 's' )
471 .arg( qgsDoubleToString( mSemiMajorAxis, radiusPrecision ), 0, 'f' )
472 .arg( qgsDoubleToString( mAzimuth, azimuthPrecision ), 0, 'f' );
473
474 return rep;
475
476}
477
478QDomElement QgsCircle::asGml2( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
479{
480 // Gml2 does not support curve. It will be converted to a linestring via CircularString
481 std::unique_ptr< QgsCircularString > circularString( toCircularString() );
482 const QDomElement gml = circularString->asGml2( doc, precision, ns, axisOrder );
483 return gml;
484}
485
486QDomElement QgsCircle::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
487{
490
491 QDomElement elemCircle = doc.createElementNS( ns, QStringLiteral( "Circle" ) );
492
493 if ( isEmpty() )
494 return elemCircle;
495
496 elemCircle.appendChild( QgsGeometryUtils::pointsToGML3( pts, doc, precision, ns, mCenter.is3D(), axisOrder ) );
497 return elemCircle;
498}
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:38
int intersections(const QgsCircle &other, QgsPoint &intersection1, QgsPoint &intersection2, bool useZ=false) const
Calculates the intersections points between this circle and an other circle.
Returns the radius of the circle.
Definition qgscircle.h:311
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 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:84
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:40
QgsPoint mCenter
Definition qgsellipse.h:252
QgsPoint center() const
Returns the center point.
Definition qgsellipse.h:121
double semiMajorAxis() const
Returns the semi-major axis.
Definition qgsellipse.h:127
double mAzimuth
Definition qgsellipse.h:255
virtual QgsPointSequence points(unsigned int segments=36) const
Returns a list of points with segmentation from segments.
double mSemiMajorAxis
Definition qgsellipse.h:253
double azimuth() const
Returns the azimuth.
Definition qgsellipse.h:139
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:254
double semiMinorAxis() const
Returns the semi-minor axis.
Definition qgsellipse.h:133
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 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 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 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...
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 leftOfLine(const double x, const double y, const double x1, const double y1, const double x2, const double y2)
Returns a value < 0 if the point (x, y) is left of the line from (x1, y1) -> (x2, y2).
double length() const override
Returns the planar, 2-dimensional length of the geometry.
A class to represent a 2D point.
Definition qgspointxy.h:59
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:291
Adds a z-dimension to the geometry, initialized to a preset value.
Definition qgspoint.cpp:557
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
Definition qgspoint.cpp:265
void setX(double x)
Sets the point's x-coordinate.
Definition qgspoint.h:280
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:626
bool isEmpty() const override
Returns true if the geometry is empty.
Definition qgspoint.cpp:773
double distance(double x, double y) const
Returns the Cartesian 2D distance between this point and a specified x, y coordinate.
Definition qgspoint.h:343
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:741
double y
Definition qgspoint.h:53
A rectangle specified with double values.
Triangle geometry type.
Definition qgstriangle.h:34
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:4319
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition qgis.h:4380
QVector< QgsPoint > QgsPointSequence
int precision