diff --git a/python/core/auto_generated/geometry/qgsgeometryutils.sip.in b/python/core/auto_generated/geometry/qgsgeometryutils.sip.in index ddd3fb09d7e..58cc20bdbb2 100644 --- a/python/core/auto_generated/geometry/qgsgeometryutils.sip.in +++ b/python/core/auto_generated/geometry/qgsgeometryutils.sip.in @@ -797,6 +797,14 @@ Returns a weighted point inside the triangle denoted by the points (``aX``, ``aY - pointY: y-coordinate of generated point .. versionadded:: 3.10 +%End + + static bool pointsAreCollinear( double x1, double y1, double x2, double y2, double x3, double y3, double epsilon ); +%Docstring +Given the points (``x1``, ``y1``), (``x2``, ``y2``) and (``x3``, ``y3``) returns ``True`` if these +points can be considered collinear with a specified tolerance. + +.. versionadded:: 3.32 %End static bool setZValueFromPoints( const QgsPointSequence &points, QgsPoint &point ) /Deprecated/; diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index 2e3982a791f..3fb3b7d0c89 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -1864,6 +1864,11 @@ void QgsGeometryUtils::weightedPointInTriangle( const double aX, const double aY pointY = rBy + rCy + aY; } +bool QgsGeometryUtils::pointsAreCollinear( double x1, double y1, double x2, double y2, double x3, double y3, double epsilon ) +{ + return qgsDoubleNear( x1 * ( y2 - y3 ) + x2 * ( y3 - y1 ) + x3 * ( y1 - y2 ), 0, epsilon ); +}; + bool QgsGeometryUtils::transferFirstMValueToPoint( const QgsPointSequence &points, QgsPoint &point ) { bool rc = false; diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index a4425586490..49bb6261cf9 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -819,6 +819,14 @@ class CORE_EXPORT QgsGeometryUtils static void weightedPointInTriangle( double aX, double aY, double bX, double bY, double cX, double cY, double weightB, double weightC, double &pointX SIP_OUT, double &pointY SIP_OUT ) SIP_HOLDGIL; + /** + * Given the points (\a x1, \a y1), (\a x2, \a y2) and (\a x3, \a y3) returns TRUE if these + * points can be considered collinear with a specified tolerance. + * + * \since QGIS 3.32 + */ + static bool pointsAreCollinear( double x1, double y1, double x2, double y2, double x3, double y3, double epsilon ); + /** * A Z dimension is added to \a point if one of the point in the list * \a points is in 3D. Moreover, the Z value of \a point is updated diff --git a/tests/src/core/geometry/testqgsgeometryutils.cpp b/tests/src/core/geometry/testqgsgeometryutils.cpp index 9c2077b4309..b11bb0e6ed7 100644 --- a/tests/src/core/geometry/testqgsgeometryutils.cpp +++ b/tests/src/core/geometry/testqgsgeometryutils.cpp @@ -75,6 +75,7 @@ class TestQgsGeometryUtils: public QObject void testInterpolatePointOnLineByValue(); void testPointOnLineWithDistance(); void testPointFractionAlongLine(); + void testPointsAreCollinear(); void interpolatePointOnArc(); void testSegmentizeArcHalfCircle(); void testSegmentizeArcHalfCircleOtherDirection(); @@ -1386,6 +1387,20 @@ void TestQgsGeometryUtils::testPointFractionAlongLine() QGSCOMPARENEAR( QgsGeometryUtils::pointFractionAlongLine( 0, 10, 20, 10, 10, 10 ), 0.5, 0.00001 ); } +void TestQgsGeometryUtils::testPointsAreCollinear() +{ + QVERIFY( QgsGeometryUtils::pointsAreCollinear( 0, 10, 10, 10, 20, 10, 0.00001 ) ); + QVERIFY( QgsGeometryUtils::pointsAreCollinear( 10, 10, 0, 10, 20, 10, 0.00001 ) ); + QVERIFY( QgsGeometryUtils::pointsAreCollinear( 20, 10, 10, 10, 0, 10, 0.00001 ) ); + QVERIFY( !QgsGeometryUtils::pointsAreCollinear( 20, 15, 10, 10, 0, 10, 0.00001 ) ); + QVERIFY( !QgsGeometryUtils::pointsAreCollinear( 20, 10, 10, 15, 0, 10, 0.00001 ) ); + QVERIFY( !QgsGeometryUtils::pointsAreCollinear( 20, 10, 10, 10, 0, 15, 0.00001 ) ); + QVERIFY( QgsGeometryUtils::pointsAreCollinear( 10, 0, 10, 10, 10, 20, 0.00001 ) ); + QVERIFY( QgsGeometryUtils::pointsAreCollinear( 10, 0, 10, 20, 10, 10, 0.00001 ) ); + QVERIFY( QgsGeometryUtils::pointsAreCollinear( 10, 20, 10, 0, 10, 10, 0.00001 ) ); + QVERIFY( !QgsGeometryUtils::pointsAreCollinear( 15, 20, 10, 10, 10, 20, 0.00001 ) ); +} + void TestQgsGeometryUtils::interpolatePointOnArc() { QgsPoint p;