From 342985f162c9f58091948e6e2d8867103e24970d Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Tue, 12 Dec 2017 21:36:30 +0100 Subject: [PATCH 1/9] improve segmentIntersection --- python/core/geometry/qgsgeometryutils.sip | 4 +- .../qgsgeometrycheckerutils.cpp | 3 +- .../qgsgeometryselfintersectioncheck.cpp | 3 +- src/core/geometry/qgscircle.cpp | 7 +- src/core/geometry/qgsgeometryutils.cpp | 26 ++++++- src/core/geometry/qgsgeometryutils.h | 4 +- src/core/geometry/qgstriangle.cpp | 10 ++- tests/src/core/testqgsgeometryutils.cpp | 77 +++++++++++++++++++ 8 files changed, 120 insertions(+), 14 deletions(-) diff --git a/python/core/geometry/qgsgeometryutils.sip b/python/core/geometry/qgsgeometryutils.sip index 3f039c583b2..4c03cd0e1db 100644 --- a/python/core/geometry/qgsgeometryutils.sip +++ b/python/core/geometry/qgsgeometryutils.sip @@ -98,7 +98,7 @@ class QgsGeometryUtils :rtype: bool %End - static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter /Out/, double tolerance ); + static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter /Out/, bool &isIntersect /Out/, double tolerance, bool acceptImproperIntersection = false ); %Docstring Compute the intersection between two segments \param p1 First segment start point @@ -106,7 +106,9 @@ class QgsGeometryUtils \param q1 Second segment start point \param q2 Second segment end point \param inter Output parameter, the intersection point + \param isIntersect Output parameter, return true if an intersection is found \param tolerance The tolerance to use + \param acceptImproperIntersection By defaut this method return only intersection point if segments are not contigus. If set on true, return also contigus point as an intersection point. :return: Whether the segments intersect :rtype: bool %End diff --git a/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp b/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp index a079cedb398..4153c6c03f7 100644 --- a/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp +++ b/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp @@ -257,6 +257,7 @@ namespace QgsGeometryCheckerUtils { QList intersections; QgsPoint inter; + bool intersection; for ( int i = 0, n = line1->vertexCount() - 1; i < n; ++i ) { for ( int j = 0, m = line2->vertexCount() - 1; j < m; ++j ) @@ -265,7 +266,7 @@ namespace QgsGeometryCheckerUtils QgsPoint p2 = line1->vertexAt( QgsVertexId( 0, 0, i + 1 ) ); QgsPoint q1 = line2->vertexAt( QgsVertexId( 0, 0, j ) ); QgsPoint q2 = line2->vertexAt( QgsVertexId( 0, 0, j + 1 ) ); - if ( QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, inter, tol ) ) + if ( QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, inter, intersection, tol ) ) { intersections.append( inter ); } diff --git a/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp b/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp index 20a84d11fc3..f8114bee79c 100644 --- a/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp +++ b/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp @@ -114,7 +114,8 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i QgsPoint p2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment1 + 1 ) % nVerts ) ); QgsPoint q2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment2 + 1 ) % nVerts ) ); QgsPoint s; - if ( !QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, s, mContext->tolerance ) ) + bool intersection; + if ( !QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, s, intersection, mContext->tolerance ) ) { error->setObsolete(); return; diff --git a/src/core/geometry/qgscircle.cpp b/src/core/geometry/qgscircle.cpp index 29ba7e6150a..2364f7568b0 100644 --- a/src/core/geometry/qgscircle.cpp +++ b/src/core/geometry/qgscircle.cpp @@ -182,9 +182,10 @@ QgsCircle QgsCircle::fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt QgsCircle 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 ) { QgsPoint p1, p2, p3; - QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, epsilon ); - QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, epsilon ); - QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, epsilon ); + bool intersection; + QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, intersection, epsilon ); + QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, intersection, epsilon ); + QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, intersection, epsilon ); return QgsTriangle( p1, p2, p3 ).inscribedCircle(); } diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index 5d5b8adebaa..23b4b02db12 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -251,14 +251,16 @@ bool QgsGeometryUtils::lineIntersection( const QgsPoint &p1, QgsVector v, const return true; } -bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter, double tolerance ) +bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter, bool &isIntersect, double tolerance, bool acceptImproperIntersection ) { + isIntersect = false; + QgsVector v( p2.x() - p1.x(), p2.y() - p1.y() ); QgsVector w( q2.x() - q1.x(), q2.y() - q1.y() ); double vl = v.length(); double wl = w.length(); - if ( qgsDoubleNear( vl, 0, 0.000000000001 ) || qgsDoubleNear( wl, 0, 0.000000000001 ) ) + if ( qgsDoubleNear( vl, 0.0, tolerance ) || qgsDoubleNear( wl, 0.0, tolerance ) ) { return false; } @@ -266,7 +268,24 @@ bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint & w = w / wl; if ( !QgsGeometryUtils::lineIntersection( p1, v, q1, w, inter ) ) + { return false; + } + + isIntersect = true; + if ( acceptImproperIntersection ) + { + if ( ( p1 == q1 ) || ( p1 == q2 ) ) + { + inter = p1; + return true; + } + else if ( ( p2 == q1 ) || ( p2 == q2 ) ) + { + inter == p2; + return true; + } + } double lambdav = QgsVector( inter.x() - p1.x(), inter.y() - p1.y() ) * v; if ( lambdav < 0. + tolerance || lambdav > vl - tolerance ) @@ -299,7 +318,8 @@ QVector QgsGeometryUtils::getSelfIntersectio QgsPoint pl = geom->vertexAt( QgsVertexId( part, ring, l ) ); QgsPoint inter; - if ( !QgsGeometryUtils::segmentIntersection( pi, pj, pk, pl, inter, tolerance ) ) continue; + bool intersection; + if ( !QgsGeometryUtils::segmentIntersection( pi, pj, pk, pl, inter, intersection, tolerance ) ) continue; SelfIntersection s; s.segment1 = i; diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index 77d7c2184c3..496806213a7 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -107,10 +107,12 @@ class CORE_EXPORT QgsGeometryUtils * \param q1 Second segment start point * \param q2 Second segment end point * \param inter Output parameter, the intersection point + * \param isIntersect Output parameter, return true if an intersection is found * \param tolerance The tolerance to use + * \param acceptImproperIntersection By defaut this method return only intersection point if segments are not contigus. If set on true, return also contigus point as an intersection point. * \returns Whether the segments intersect */ - static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter SIP_OUT, double tolerance ); + static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter SIP_OUT, bool &isIntersect SIP_OUT, double tolerance, bool acceptImproperIntersection = false ); /** * \brief Project the point on a segment diff --git a/src/core/geometry/qgstriangle.cpp b/src/core/geometry/qgstriangle.cpp index 40b6204ec97..a86c2addaa5 100644 --- a/src/core/geometry/qgstriangle.cpp +++ b/src/core/geometry/qgstriangle.cpp @@ -495,14 +495,15 @@ QVector QgsTriangle::bisectors( double lengthTolerance ) const QgsLineString bis3; QgsPoint incenter = inscribedCenter(); QgsPoint out; + bool intersection; - QgsGeometryUtils::segmentIntersection( vertexAt( 0 ), incenter, vertexAt( 1 ), vertexAt( 2 ), out, lengthTolerance ); + QgsGeometryUtils::segmentIntersection( vertexAt( 0 ), incenter, vertexAt( 1 ), vertexAt( 2 ), out, intersection, lengthTolerance ); bis1.setPoints( QgsPointSequence() << vertexAt( 0 ) << out ); - QgsGeometryUtils::segmentIntersection( vertexAt( 1 ), incenter, vertexAt( 0 ), vertexAt( 2 ), out, lengthTolerance ); + QgsGeometryUtils::segmentIntersection( vertexAt( 1 ), incenter, vertexAt( 0 ), vertexAt( 2 ), out, intersection, lengthTolerance ); bis2.setPoints( QgsPointSequence() << vertexAt( 1 ) << out ); - QgsGeometryUtils::segmentIntersection( vertexAt( 2 ), incenter, vertexAt( 0 ), vertexAt( 1 ), out, lengthTolerance ); + QgsGeometryUtils::segmentIntersection( vertexAt( 2 ), incenter, vertexAt( 0 ), vertexAt( 1 ), out, intersection, lengthTolerance ); bis3.setPoints( QgsPointSequence() << vertexAt( 2 ) << out ); bis.append( bis1 ); @@ -529,7 +530,8 @@ QgsPoint QgsTriangle::orthocenter( double lengthTolerance ) const return QgsPoint(); QVector alt = altitudes(); QgsPoint ortho; - QgsGeometryUtils::segmentIntersection( alt.at( 0 ).pointN( 0 ), alt.at( 0 ).pointN( 1 ), alt.at( 1 ).pointN( 0 ), alt.at( 1 ).pointN( 1 ), ortho, lengthTolerance ); + bool intersection; + QgsGeometryUtils::segmentIntersection( alt.at( 0 ).pointN( 0 ), alt.at( 0 ).pointN( 1 ), alt.at( 1 ).pointN( 0 ), alt.at( 1 ).pointN( 1 ), ortho, intersection, lengthTolerance ); return ortho; } diff --git a/tests/src/core/testqgsgeometryutils.cpp b/tests/src/core/testqgsgeometryutils.cpp index 7aa03b65185..5a9bb44084f 100644 --- a/tests/src/core/testqgsgeometryutils.cpp +++ b/tests/src/core/testqgsgeometryutils.cpp @@ -54,6 +54,7 @@ class TestQgsGeometryUtils: public QObject void testCoefficients(); void testPerpendicularSegment(); void testClosestPoint(); + void testSegmentIntersection(); }; @@ -647,5 +648,81 @@ void TestQgsGeometryUtils::testClosestPoint() QGSCOMPARENEAR( pt4.m(), 1, 0.0001 ); } +void TestQgsGeometryUtils::testSegmentIntersection() +{ + const double epsilon = 1e-8; + bool intersection, isIntersect; + QgsPoint inter; + // parallel + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), inter, isIntersect, epsilon, true ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 1, 1 ), QgsPoint( 0, 1 ), QgsPoint( 1, 2 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 1, 1 ), QgsPoint( -1, -1 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 5, 5 ), QgsPoint( 1, 1 ), QgsPoint( 0, 0 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + // contigus + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + // colinear + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 0, 6 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 0, 6 ), inter, isIntersect, epsilon, true ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + // improper + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + // normal + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), inter, isIntersect, epsilon ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 0 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 0 ) ); +} + QGSTEST_MAIN( TestQgsGeometryUtils ) #include "testqgsgeometryutils.moc" From eb292c93bb7147812539efdefbdb8c6f76344de9 Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Wed, 13 Dec 2017 08:45:44 +0100 Subject: [PATCH 2/9] Apply segmentIntersection on some tools with tests. --- src/app/qgsmaptoolcircle2tangentspoint.cpp | 97 +++++----------------- src/app/qgsmaptoolcircle2tangentspoint.h | 3 - src/core/geometry/qgscircle.cpp | 14 +++- tests/src/core/testqgsgeometry.cpp | 7 ++ 4 files changed, 39 insertions(+), 82 deletions(-) diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index 339f67c9bc9..240d665e4f9 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -25,6 +25,7 @@ #include "qgslinestring.h" #include "qgsmultipolygon.h" #include "qgsspinbox.h" +#include "qgsgeometryutils.h" #include #include @@ -61,9 +62,12 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e } if ( mPoints.size() == 4 ) { - QgsPointXY ptInter = intersect( QgsPointXY( mPoints.at( 0 ) ), QgsPointXY( mPoints.at( 1 ) ), - QgsPointXY( mPoints.at( 2 ) ), QgsPointXY( mPoints.at( 3 ) ) ); - if ( ptInter == QgsPointXY() ) + bool isIntersect; + const double epsilon = 1e-8; + QgsPoint ptInter; + QgsGeometryUtils::segmentIntersection( mPoints.at( 0 ), mPoints.at( 1 ), + mPoints.at( 2 ), mPoints.at( 3 ), ptInter, isIntersect, epsilon ); + if ( !isIntersect ) { QgisApp::instance()->messageBar()->pushMessage( tr( "Error" ), tr( "Segments are parallels" ), QgsMessageBar::CRITICAL, QgisApp::instance()->messageTimeout() ); @@ -144,64 +148,6 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasMoveEvent( QgsMapMouseEvent *e ) } } -QgsPointXY QgsMapToolCircle2TangentsPoint::intersect( QgsPointXY seg1_pt1, QgsPointXY seg1_pt2, QgsPointXY seg2_pt1, QgsPointXY seg2_pt2 ) -{ - /* - * Public domain function by Darel Rex Finley, 2006 - * http://alienryderflex.com/intersect/ - */ - QgsPointXY ptInter; - - double Ax = seg1_pt1.x(); - double Ay = seg1_pt1.y(); - double Bx = seg1_pt2.x(); - double By = seg1_pt2.y(); - - double Cx = seg2_pt1.x(); - double Cy = seg2_pt1.y(); - double Dx = seg2_pt2.x(); - double Dy = seg2_pt2.y(); - - if ( ( ( Ax == Bx ) && ( Ay == By ) ) || ( ( Cx == Dx ) && ( Cy == Dy ) ) ) - return ptInter; - - // (1) Translate the system so that point A is on the origin. - Bx -= Ax; - By -= Ay; - Cx -= Ax; - Cy -= Ay; - Dx -= Ax; - Dy -= Ay; - - // Discover the length of segment A-B - double distAB = sqrt( Bx * Bx + By * By ); - - // (2) Rotate the system so that point B is on the positive X axis. - double theCos = Bx / distAB; - double theSin = By / distAB; - double newX = Cx * theCos + Cy * theSin; - Cy = Cy * theCos - Cx * theSin; - Cx = newX; - newX = Dx * theCos + Dy * theSin; - Dy = Dy * theCos - Dx * theSin; - Dx = newX; - - // Fail if the lines are parallel. - if ( Cy == Dy ) - return ptInter; - - // (3) Discover the position of the intersection point along line A-B. - double ABpos = Dx + ( Cx - Dx ) * Dy / ( Dy - Cy ); - - // (4) Apply the discovered position to line A-B - // in the original coordinate system. - ptInter.setX( Ax + ABpos * theCos ); - ptInter.setY( Ay + ABpos * theSin ); - - // Success - return ptInter; -} - void QgsMapToolCircle2TangentsPoint::getPossibleCenter( ) { @@ -226,20 +172,21 @@ void QgsMapToolCircle2TangentsPoint::getPossibleCenter( ) QgsGeometry line2m = line2.offsetCurve( - mRadius, 8, QgsGeometry::JoinStyleBevel, 5 ); QgsGeometry line2p = line2.offsetCurve( + mRadius, 8, QgsGeometry::JoinStyleBevel, 5 ); - QgsPointXY p1 = intersect( line1m.asPolyline().at( 0 ), line1m.asPolyline().at( 1 ), - line2m.asPolyline().at( 0 ), line2m.asPolyline().at( 1 ) ); - QgsPointXY p2 = intersect( line1m.asPolyline().at( 0 ), line1m.asPolyline().at( 1 ), - line2p.asPolyline().at( 0 ), line2p.asPolyline().at( 1 ) ); - QgsPointXY p3 = intersect( line1p.asPolyline().at( 0 ), line1p.asPolyline().at( 1 ), - line2m.asPolyline().at( 0 ), line2m.asPolyline().at( 1 ) ); - QgsPointXY p4 = intersect( line1p.asPolyline().at( 0 ), line1p.asPolyline().at( 1 ), - line2p.asPolyline().at( 0 ), line2p.asPolyline().at( 1 ) ); - - mCenters.append( p1 ); - mCenters.append( p2 ); - mCenters.append( p3 ); - mCenters.append( p4 ); - + bool isIntersect; + const double epsilon = 1e-8; + QgsPoint inter; + QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ), + QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + mCenters.append( QgsPointXY( inter ) ); + QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ), + QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + mCenters.append( QgsPointXY( inter ) ); + QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ), + QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + mCenters.append( QgsPointXY( inter ) ); + QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ), + QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + mCenters.append( QgsPointXY( inter ) ); } } diff --git a/src/app/qgsmaptoolcircle2tangentspoint.h b/src/app/qgsmaptoolcircle2tangentspoint.h index f39f83916ce..c021150b40f 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.h +++ b/src/app/qgsmaptoolcircle2tangentspoint.h @@ -38,9 +38,6 @@ class QgsMapToolCircle2TangentsPoint: public QgsMapToolAddCircle void radiusSpinBoxChanged( int radius ); private: - //! Return the point where segments are intersected. Method from QgsGeometryUtils doesn't work for special cases used by this tool. - QgsPointXY intersect( QgsPointXY seg1_pt1, QgsPointXY seg1_pt2, QgsPointXY seg2_pt1, QgsPointXY seg2_pt2 ); - //! Compute 4 possible centers void getPossibleCenter(); diff --git a/src/core/geometry/qgscircle.cpp b/src/core/geometry/qgscircle.cpp index 2364f7568b0..a94ab5cc17d 100644 --- a/src/core/geometry/qgscircle.cpp +++ b/src/core/geometry/qgscircle.cpp @@ -182,10 +182,16 @@ QgsCircle QgsCircle::fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt QgsCircle 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 ) { QgsPoint p1, p2, p3; - bool intersection; - QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, intersection, epsilon ); - QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, intersection, epsilon ); - QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, intersection, epsilon ); + bool isIntersect; + QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect, epsilon ); + if ( !isIntersect ) + return QgsCircle(); + QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg3, pt2_tg3, p2, isIntersect, epsilon ); + if ( !isIntersect ) + return QgsCircle(); + QgsGeometryUtils::segmentIntersection( pt1_tg2, pt2_tg2, pt1_tg3, pt2_tg3, p3, isIntersect, epsilon ); + if ( !isIntersect ) + return QgsCircle(); return QgsTriangle( p1, p2, p3 ).inscribedCircle(); } diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp index d6e31d18881..86a60135609 100644 --- a/tests/src/core/testqgsgeometry.cpp +++ b/tests/src/core/testqgsgeometry.cpp @@ -6973,6 +6973,13 @@ void TestQgsGeometry::circle() QgsCircle circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 2, 0 ), QgsPoint( 3, 0 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) ); QGSCOMPARENEARPOINT( circ_tgt.center(), QgsPoint( 1.4645, 1.4645 ), 0.0001 ); QGSCOMPARENEAR( circ_tgt.radius(), 1.4645, 0.0001 ); + // with parallels + circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ) ); + QVERIFY( circ_tgt.isEmpty() ); + circ_tgt = QgsCircle().from3Tangents( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) ); + QVERIFY( circ_tgt.isEmpty() ); + circ_tgt = QgsCircle().from3Tangents( QgsPoint( 5, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 0 ), QgsPoint( 1, 5 ) ); + QVERIFY( circ_tgt.isEmpty() ); // minimalCircleFrom3points QgsCircle minCircle3Points = QgsCircle().minimalCircleFrom3Points( QgsPoint( 0, 5 ), QgsPoint( 0, -5 ), QgsPoint( 1, 2 ) ); QGSCOMPARENEARPOINT( minCircle3Points.center(), QgsPoint( 0, 0 ), 0.0001 ); From 9bd72128a54e3a3dc9208ae21402eb3403028ba7 Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Wed, 13 Dec 2017 09:23:56 +0100 Subject: [PATCH 3/9] Fix missing cases and push --- src/core/geometry/qgsgeometryutils.cpp | 22 +++++++++++++++ tests/src/core/testqgsgeometryutils.cpp | 36 +++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index 23b4b02db12..fcd96b2d001 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -285,6 +285,28 @@ bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint & inter == p2; return true; } + + double x, y; + if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p1.x(), p1.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) ) + { + inter == p1; + return true; + } + else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p2.x(), p2.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) ) + { + inter == p2; + return true; + } + else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q1.x(), q1.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) ) + { + inter == q1; + return true; + } + else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q2.x(), q2.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) ) + { + inter == q2; + return true; + } } double lambdav = QgsVector( inter.x() - p1.x(), inter.y() - p1.y() ) * v; diff --git a/tests/src/core/testqgsgeometryutils.cpp b/tests/src/core/testqgsgeometryutils.cpp index 5a9bb44084f..9829a085032 100644 --- a/tests/src/core/testqgsgeometryutils.cpp +++ b/tests/src/core/testqgsgeometryutils.cpp @@ -707,10 +707,42 @@ void TestQgsGeometryUtils::testSegmentIntersection() QVERIFY( isIntersect ); QVERIFY( inter == QgsPoint( 0, 2 ) ); inter = QgsPoint(); - intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true ); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true ); QVERIFY( intersection ); QVERIFY( isIntersect ); - QVERIFY( inter == QgsPoint( 0, 5 ) ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); + + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); + + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); + + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 2 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 2 ) ); // normal inter = QgsPoint(); intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), inter, isIntersect, epsilon ); From c6838fdec6cb9ef09b90f75cdacc706f6fa83cf0 Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Wed, 13 Dec 2017 09:55:56 +0100 Subject: [PATCH 4/9] Update doc --- python/core/geometry/qgsgeometryutils.sip | 25 ++++++++++++++++++++++- src/core/geometry/qgsgeometryutils.h | 25 ++++++++++++++++++++++- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/python/core/geometry/qgsgeometryutils.sip b/python/core/geometry/qgsgeometryutils.sip index 4c03cd0e1db..cc5f29502ab 100644 --- a/python/core/geometry/qgsgeometryutils.sip +++ b/python/core/geometry/qgsgeometryutils.sip @@ -108,8 +108,31 @@ class QgsGeometryUtils \param inter Output parameter, the intersection point \param isIntersect Output parameter, return true if an intersection is found \param tolerance The tolerance to use - \param acceptImproperIntersection By defaut this method return only intersection point if segments are not contigus. If set on true, return also contigus point as an intersection point. + \param acceptImproperIntersection By default, this method returns true only if segments have proper intersection. If set true, returns also true if segments have improper intersection (end of one segment on other segment ; continuous segments). :return: Whether the segments intersect + * Example: + \code{.py} + epsilon = 1e-8 + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), epsilon ) + ret[0], ret[1].asWkt(), ret[2] + # Whether the segments intersect, the intersection point, is intersect + # (False, 'Point (0 0)', False) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon ) + ret[0], ret[1].asWkt(), ret[2] + # (False, 'Point (0 5)', True) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon, True ) + ret[0], ret[1].asWkt(), ret[2] + # (True, 'Point (0 5)', True) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon ) + ret[0], ret[1].asWkt(), ret[2] + # (False, 'Point (0 2)', True) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon, True ) + ret[0], ret[1].asWkt(), ret[2] + # (True, 'Point (0 2)', True) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), epsilon ) + ret[0], ret[1].asWkt(), ret[2] + # (True, 'Point (0 0)', True) + \endcode :rtype: bool %End diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index 496806213a7..eb648272854 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -109,8 +109,31 @@ class CORE_EXPORT QgsGeometryUtils * \param inter Output parameter, the intersection point * \param isIntersect Output parameter, return true if an intersection is found * \param tolerance The tolerance to use - * \param acceptImproperIntersection By defaut this method return only intersection point if segments are not contigus. If set on true, return also contigus point as an intersection point. + * \param acceptImproperIntersection By default, this method returns true only if segments have proper intersection. If set true, returns also true if segments have improper intersection (end of one segment on other segment ; continuous segments). * \returns Whether the segments intersect + * * Example: + * \code{.py} + * epsilon = 1e-8 + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), epsilon ) + * ret[0], ret[1].asWkt(), ret[2] + * # Whether the segments intersect, the intersection point, is intersect + * # (False, 'Point (0 0)', False) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon ) + * ret[0], ret[1].asWkt(), ret[2] + * # (False, 'Point (0 5)', True) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon, True ) + * ret[0], ret[1].asWkt(), ret[2] + * # (True, 'Point (0 5)', True) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon ) + * ret[0], ret[1].asWkt(), ret[2] + * # (False, 'Point (0 2)', True) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon, True ) + * ret[0], ret[1].asWkt(), ret[2] + * # (True, 'Point (0 2)', True) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), epsilon ) + * ret[0], ret[1].asWkt(), ret[2] + * # (True, 'Point (0 0)', True) + * \endcode */ static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter SIP_OUT, bool &isIntersect SIP_OUT, double tolerance, bool acceptImproperIntersection = false ); From 03d8565e2aa6351a34d3c06cb1b8a37b1596de8a Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Wed, 13 Dec 2017 14:03:55 +0100 Subject: [PATCH 5/9] - Update api_break.dox - rename isIntersect to isIntersection - rename inter to intersectionPoint --- doc/api_break.dox | 3 ++- python/core/geometry/qgsgeometryutils.sip | 6 +++--- src/core/geometry/qgsgeometryutils.cpp | 24 +++++++++++------------ src/core/geometry/qgsgeometryutils.h | 6 +++--- 4 files changed, 20 insertions(+), 19 deletions(-) diff --git a/doc/api_break.dox b/doc/api_break.dox index 803e7b0950a..6d52cd7ee4d 100644 --- a/doc/api_break.dox +++ b/doc/api_break.dox @@ -1453,7 +1453,8 @@ QgsGeometryUtils {#qgis_api_break_3_0_QgsGeometryUtils} - componentType enum has been renamed to ComponentType and its members were CamelCased too: VERTEX, RING and PART become Vertex, Ring and Part, respectively. - adjacentVertices was removed - use QgsAbstractGeometry.adjacentVertices instead. - +- segmentIntersection takes an optional boolean parameter "acceptImproperIntersection" returning true even if the intersection is improper. +Takes another boolean argument "isIntersection" returning if there is an intersection or not. The "inter" parameter has been renamed "intersectionPoint". QgsGPSConnectionRegistry {#qgis_api_break_3_0_QgsGPSConnectionRegistry} ------------------------ diff --git a/python/core/geometry/qgsgeometryutils.sip b/python/core/geometry/qgsgeometryutils.sip index cc5f29502ab..089b28d1a6b 100644 --- a/python/core/geometry/qgsgeometryutils.sip +++ b/python/core/geometry/qgsgeometryutils.sip @@ -98,15 +98,15 @@ class QgsGeometryUtils :rtype: bool %End - static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter /Out/, bool &isIntersect /Out/, double tolerance, bool acceptImproperIntersection = false ); + static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint /Out/, bool &isIntersection /Out/, double tolerance, bool acceptImproperIntersection = false ); %Docstring Compute the intersection between two segments \param p1 First segment start point \param p2 First segment end point \param q1 Second segment start point \param q2 Second segment end point - \param inter Output parameter, the intersection point - \param isIntersect Output parameter, return true if an intersection is found + \param intersectionPoint Output parameter, the intersection point + \param isIntersection Output parameter, return true if an intersection is found \param tolerance The tolerance to use \param acceptImproperIntersection By default, this method returns true only if segments have proper intersection. If set true, returns also true if segments have improper intersection (end of one segment on other segment ; continuous segments). :return: Whether the segments intersect diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index fcd96b2d001..539294ed0e9 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -251,9 +251,9 @@ bool QgsGeometryUtils::lineIntersection( const QgsPoint &p1, QgsVector v, const return true; } -bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter, bool &isIntersect, double tolerance, bool acceptImproperIntersection ) +bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance, bool acceptImproperIntersection ) { - isIntersect = false; + isIntersection = false; QgsVector v( p2.x() - p1.x(), p2.y() - p1.y() ); QgsVector w( q2.x() - q1.x(), q2.y() - q1.y() ); @@ -267,53 +267,53 @@ bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint & v = v / vl; w = w / wl; - if ( !QgsGeometryUtils::lineIntersection( p1, v, q1, w, inter ) ) + if ( !QgsGeometryUtils::lineIntersection( p1, v, q1, w, intersectionPoint ) ) { return false; } - isIntersect = true; + isIntersection = true; if ( acceptImproperIntersection ) { if ( ( p1 == q1 ) || ( p1 == q2 ) ) { - inter = p1; + intersectionPoint = p1; return true; } else if ( ( p2 == q1 ) || ( p2 == q2 ) ) { - inter == p2; + intersectionPoint == p2; return true; } double x, y; if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p1.x(), p1.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) ) { - inter == p1; + intersectionPoint == p1; return true; } else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p2.x(), p2.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) ) { - inter == p2; + intersectionPoint == p2; return true; } else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q1.x(), q1.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) ) { - inter == q1; + intersectionPoint == q1; return true; } else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q2.x(), q2.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) ) { - inter == q2; + intersectionPoint == q2; return true; } } - double lambdav = QgsVector( inter.x() - p1.x(), inter.y() - p1.y() ) * v; + double lambdav = QgsVector( intersectionPoint.x() - p1.x(), intersectionPoint.y() - p1.y() ) * v; if ( lambdav < 0. + tolerance || lambdav > vl - tolerance ) return false; - double lambdaw = QgsVector( inter.x() - q1.x(), inter.y() - q1.y() ) * w; + double lambdaw = QgsVector( intersectionPoint.x() - q1.x(), intersectionPoint.y() - q1.y() ) * w; return !( lambdaw < 0. + tolerance || lambdaw >= wl - tolerance ); } diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index eb648272854..e34aa8f9512 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -106,8 +106,8 @@ class CORE_EXPORT QgsGeometryUtils * \param p2 First segment end point * \param q1 Second segment start point * \param q2 Second segment end point - * \param inter Output parameter, the intersection point - * \param isIntersect Output parameter, return true if an intersection is found + * \param intersectionPoint Output parameter, the intersection point + * \param isIntersection Output parameter, return true if an intersection is found * \param tolerance The tolerance to use * \param acceptImproperIntersection By default, this method returns true only if segments have proper intersection. If set true, returns also true if segments have improper intersection (end of one segment on other segment ; continuous segments). * \returns Whether the segments intersect @@ -135,7 +135,7 @@ class CORE_EXPORT QgsGeometryUtils * # (True, 'Point (0 0)', True) * \endcode */ - static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &inter SIP_OUT, bool &isIntersect SIP_OUT, double tolerance, bool acceptImproperIntersection = false ); + static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint SIP_OUT, bool &isIntersection SIP_OUT, double tolerance, bool acceptImproperIntersection = false ); /** * \brief Project the point on a segment From fb3aac8ef27e44e9794fc238dc2677da0bf878d9 Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Thu, 14 Dec 2017 16:11:32 +0100 Subject: [PATCH 6/9] - init variables - fix equality - add tests --- .../qgsgeometrycheckerutils.cpp | 2 +- .../qgsgeometryselfintersectioncheck.cpp | 2 +- src/app/qgsmaptoolcircle2tangentspoint.cpp | 4 +- src/core/geometry/qgscircle.cpp | 2 +- src/core/geometry/qgsgeometryutils.cpp | 4 +- src/core/geometry/qgstriangle.cpp | 2 +- tests/src/core/testqgsgeometryutils.cpp | 43 ++++++++++++++++++- 7 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp b/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp index 4153c6c03f7..621207a02c3 100644 --- a/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp +++ b/src/analysis/vector/geometry_checker/qgsgeometrycheckerutils.cpp @@ -257,7 +257,7 @@ namespace QgsGeometryCheckerUtils { QList intersections; QgsPoint inter; - bool intersection; + bool intersection = false; for ( int i = 0, n = line1->vertexCount() - 1; i < n; ++i ) { for ( int j = 0, m = line2->vertexCount() - 1; j < m; ++j ) diff --git a/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp b/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp index f8114bee79c..81d27dc9161 100644 --- a/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp +++ b/src/analysis/vector/geometry_checker/qgsgeometryselfintersectioncheck.cpp @@ -114,7 +114,7 @@ void QgsGeometrySelfIntersectionCheck::fixError( QgsGeometryCheckError *error, i QgsPoint p2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment1 + 1 ) % nVerts ) ); QgsPoint q2 = geom->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( inter.segment2 + 1 ) % nVerts ) ); QgsPoint s; - bool intersection; + bool intersection = false; if ( !QgsGeometryUtils::segmentIntersection( p1, p2, q1, q2, s, intersection, mContext->tolerance ) ) { error->setObsolete(); diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index 240d665e4f9..d7ef8965cbf 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -62,7 +62,7 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e } if ( mPoints.size() == 4 ) { - bool isIntersect; + bool isIntersect = false; const double epsilon = 1e-8; QgsPoint ptInter; QgsGeometryUtils::segmentIntersection( mPoints.at( 0 ), mPoints.at( 1 ), @@ -172,7 +172,7 @@ void QgsMapToolCircle2TangentsPoint::getPossibleCenter( ) QgsGeometry line2m = line2.offsetCurve( - mRadius, 8, QgsGeometry::JoinStyleBevel, 5 ); QgsGeometry line2p = line2.offsetCurve( + mRadius, 8, QgsGeometry::JoinStyleBevel, 5 ); - bool isIntersect; + bool isIntersect = false; const double epsilon = 1e-8; QgsPoint inter; QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ), diff --git a/src/core/geometry/qgscircle.cpp b/src/core/geometry/qgscircle.cpp index a94ab5cc17d..2d4f203579e 100644 --- a/src/core/geometry/qgscircle.cpp +++ b/src/core/geometry/qgscircle.cpp @@ -182,7 +182,7 @@ QgsCircle QgsCircle::fromCenterPoint( const QgsPoint ¢er, const QgsPoint &pt QgsCircle 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 ) { QgsPoint p1, p2, p3; - bool isIntersect; + bool isIntersect = false; QgsGeometryUtils::segmentIntersection( pt1_tg1, pt2_tg1, pt1_tg2, pt2_tg2, p1, isIntersect, epsilon ); if ( !isIntersect ) return QgsCircle(); diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index 539294ed0e9..c2f7e6583ec 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -282,7 +282,7 @@ bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint & } else if ( ( p2 == q1 ) || ( p2 == q2 ) ) { - intersectionPoint == p2; + intersectionPoint = p2; return true; } @@ -340,7 +340,7 @@ QVector QgsGeometryUtils::getSelfIntersectio QgsPoint pl = geom->vertexAt( QgsVertexId( part, ring, l ) ); QgsPoint inter; - bool intersection; + bool intersection = false; if ( !QgsGeometryUtils::segmentIntersection( pi, pj, pk, pl, inter, intersection, tolerance ) ) continue; SelfIntersection s; diff --git a/src/core/geometry/qgstriangle.cpp b/src/core/geometry/qgstriangle.cpp index a86c2addaa5..ba88447985e 100644 --- a/src/core/geometry/qgstriangle.cpp +++ b/src/core/geometry/qgstriangle.cpp @@ -495,7 +495,7 @@ QVector QgsTriangle::bisectors( double lengthTolerance ) const QgsLineString bis3; QgsPoint incenter = inscribedCenter(); QgsPoint out; - bool intersection; + bool intersection = false; QgsGeometryUtils::segmentIntersection( vertexAt( 0 ), incenter, vertexAt( 1 ), vertexAt( 2 ), out, intersection, lengthTolerance ); bis1.setPoints( QgsPointSequence() << vertexAt( 0 ) << out ); diff --git a/tests/src/core/testqgsgeometryutils.cpp b/tests/src/core/testqgsgeometryutils.cpp index 9829a085032..2525c89cae7 100644 --- a/tests/src/core/testqgsgeometryutils.cpp +++ b/tests/src/core/testqgsgeometryutils.cpp @@ -651,9 +651,20 @@ void TestQgsGeometryUtils::testClosestPoint() void TestQgsGeometryUtils::testSegmentIntersection() { const double epsilon = 1e-8; - bool intersection, isIntersect; + bool intersection = false, isIntersect = false; QgsPoint inter; + // null + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 5, 5 ), QgsPoint( 5, 5 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 5, 5 ), QgsPoint( 5, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( !intersection ); + QVERIFY( !isIntersect ); + QVERIFY( inter == QgsPoint() ); // parallel + inter = QgsPoint(); intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), inter, isIntersect, epsilon ); QVERIFY( !intersection ); QVERIFY( !isIntersect ); @@ -689,6 +700,36 @@ void TestQgsGeometryUtils::testSegmentIntersection() QVERIFY( intersection ); QVERIFY( isIntersect ); QVERIFY( inter == QgsPoint( 0, 5 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon ); + QVERIFY( !intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); + inter = QgsPoint(); + intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 5 ), QgsPoint( 0, 0 ), QgsPoint( 1, 5 ), QgsPoint( 0, 5 ), inter, isIntersect, epsilon, true ); + QVERIFY( intersection ); + QVERIFY( isIntersect ); + QVERIFY( inter == QgsPoint( 0, 5 ) ); // colinear inter = QgsPoint(); intersection = QgsGeometryUtils::segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 0, 6 ), inter, isIntersect, epsilon ); From 89fb854383a18be05d4406b5c233a21084c2eb26 Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Fri, 15 Dec 2017 09:00:56 +0100 Subject: [PATCH 7/9] comment the code instead of apply an useless equality... --- src/core/geometry/qgsgeometryutils.cpp | 27 ++++++++++---------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index c2f7e6583ec..58366882ba1 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -287,24 +287,17 @@ bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint & } double x, y; - if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p1.x(), p1.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) ) + if ( + // intersectionPoint = p1 + qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p1.x(), p1.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) || + // intersectionPoint = p2 + qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p2.x(), p2.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) || + // intersectionPoint = q1 + qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q1.x(), q1.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) || + // intersectionPoint = q2 + qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q2.x(), q2.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) + ) { - intersectionPoint == p1; - return true; - } - else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( p2.x(), p2.y(), q1.x(), q1.y(), q2.x(), q2.y(), x, y, tolerance ), 0.0, tolerance ) ) - { - intersectionPoint == p2; - return true; - } - else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q1.x(), q1.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) ) - { - intersectionPoint == q1; - return true; - } - else if ( qgsDoubleNear( QgsGeometryUtils::sqrDistToLine( q2.x(), q2.y(), p1.x(), p1.y(), p2.x(), p2.y(), x, y, tolerance ), 0.0, tolerance ) ) - { - intersectionPoint == q2; return true; } } From 72f5adf3685be335774d70baadb83eb70bb474b4 Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Fri, 15 Dec 2017 20:36:57 +0100 Subject: [PATCH 8/9] Add default value to epsilon. Change example for python. --- python/core/geometry/qgsgeometryutils.sip | 15 +++++++-------- src/app/qgsmaptoolcircle2tangentspoint.cpp | 12 +++++------- src/core/geometry/qgsgeometryutils.cpp | 2 +- src/core/geometry/qgsgeometryutils.h | 15 +++++++-------- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/python/core/geometry/qgsgeometryutils.sip b/python/core/geometry/qgsgeometryutils.sip index 089b28d1a6b..c45bb9cd8ad 100644 --- a/python/core/geometry/qgsgeometryutils.sip +++ b/python/core/geometry/qgsgeometryutils.sip @@ -98,7 +98,7 @@ class QgsGeometryUtils :rtype: bool %End - static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint /Out/, bool &isIntersection /Out/, double tolerance, bool acceptImproperIntersection = false ); + static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint /Out/, bool &isIntersection /Out/, const double tolerance = 1e-8, bool acceptImproperIntersection = false ); %Docstring Compute the intersection between two segments \param p1 First segment start point @@ -112,24 +112,23 @@ class QgsGeometryUtils :return: Whether the segments intersect * Example: \code{.py} - epsilon = 1e-8 - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), epsilon ) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ) ) ret[0], ret[1].asWkt(), ret[2] # Whether the segments intersect, the intersection point, is intersect # (False, 'Point (0 0)', False) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon ) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ) ) ret[0], ret[1].asWkt(), ret[2] # (False, 'Point (0 5)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon, True ) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) ret[0], ret[1].asWkt(), ret[2] # (True, 'Point (0 5)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon ) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ) ) ret[0], ret[1].asWkt(), ret[2] # (False, 'Point (0 2)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon, True ) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) ret[0], ret[1].asWkt(), ret[2] # (True, 'Point (0 2)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), epsilon ) + ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ) ) ret[0], ret[1].asWkt(), ret[2] # (True, 'Point (0 0)', True) \endcode diff --git a/src/app/qgsmaptoolcircle2tangentspoint.cpp b/src/app/qgsmaptoolcircle2tangentspoint.cpp index d7ef8965cbf..1fb9eaa5389 100644 --- a/src/app/qgsmaptoolcircle2tangentspoint.cpp +++ b/src/app/qgsmaptoolcircle2tangentspoint.cpp @@ -63,10 +63,9 @@ void QgsMapToolCircle2TangentsPoint::cadCanvasReleaseEvent( QgsMapMouseEvent *e if ( mPoints.size() == 4 ) { bool isIntersect = false; - const double epsilon = 1e-8; QgsPoint ptInter; QgsGeometryUtils::segmentIntersection( mPoints.at( 0 ), mPoints.at( 1 ), - mPoints.at( 2 ), mPoints.at( 3 ), ptInter, isIntersect, epsilon ); + mPoints.at( 2 ), mPoints.at( 3 ), ptInter, isIntersect ); if ( !isIntersect ) { QgisApp::instance()->messageBar()->pushMessage( tr( "Error" ), tr( "Segments are parallels" ), @@ -173,19 +172,18 @@ void QgsMapToolCircle2TangentsPoint::getPossibleCenter( ) QgsGeometry line2p = line2.offsetCurve( + mRadius, 8, QgsGeometry::JoinStyleBevel, 5 ); bool isIntersect = false; - const double epsilon = 1e-8; QgsPoint inter; QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ), - QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect ); mCenters.append( QgsPointXY( inter ) ); QgsGeometryUtils::segmentIntersection( QgsPoint( line1m.asPolyline().at( 0 ) ), QgsPoint( line1m.asPolyline().at( 1 ) ), - QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect ); mCenters.append( QgsPointXY( inter ) ); QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ), - QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + QgsPoint( line2m.asPolyline().at( 0 ) ), QgsPoint( line2m.asPolyline().at( 1 ) ), inter, isIntersect ); mCenters.append( QgsPointXY( inter ) ); QgsGeometryUtils::segmentIntersection( QgsPoint( line1p.asPolyline().at( 0 ) ), QgsPoint( line1p.asPolyline().at( 1 ) ), - QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect, epsilon ); + QgsPoint( line2p.asPolyline().at( 0 ) ), QgsPoint( line2p.asPolyline().at( 1 ) ), inter, isIntersect ); mCenters.append( QgsPointXY( inter ) ); } } diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index 58366882ba1..1a1a3899cba 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -251,7 +251,7 @@ bool QgsGeometryUtils::lineIntersection( const QgsPoint &p1, QgsVector v, const return true; } -bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance, bool acceptImproperIntersection ) +bool QgsGeometryUtils::segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, const double tolerance, bool acceptImproperIntersection ) { isIntersection = false; diff --git a/src/core/geometry/qgsgeometryutils.h b/src/core/geometry/qgsgeometryutils.h index e34aa8f9512..c331825826d 100644 --- a/src/core/geometry/qgsgeometryutils.h +++ b/src/core/geometry/qgsgeometryutils.h @@ -113,29 +113,28 @@ class CORE_EXPORT QgsGeometryUtils * \returns Whether the segments intersect * * Example: * \code{.py} - * epsilon = 1e-8 - * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ), epsilon ) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ) ) * ret[0], ret[1].asWkt(), ret[2] * # Whether the segments intersect, the intersection point, is intersect * # (False, 'Point (0 0)', False) - * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon ) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ) ) * ret[0], ret[1].asWkt(), ret[2] * # (False, 'Point (0 5)', True) - * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), epsilon, True ) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) * ret[0], ret[1].asWkt(), ret[2] * # (True, 'Point (0 5)', True) - * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon ) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ) ) * ret[0], ret[1].asWkt(), ret[2] * # (False, 'Point (0 2)', True) - * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), epsilon, True ) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) * ret[0], ret[1].asWkt(), ret[2] * # (True, 'Point (0 2)', True) - * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ), epsilon ) + * ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ) ) * ret[0], ret[1].asWkt(), ret[2] * # (True, 'Point (0 0)', True) * \endcode */ - static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint SIP_OUT, bool &isIntersection SIP_OUT, double tolerance, bool acceptImproperIntersection = false ); + static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint SIP_OUT, bool &isIntersection SIP_OUT, const double tolerance = 1e-8, bool acceptImproperIntersection = false ); /** * \brief Project the point on a segment From 313417ddf109889d564893d794895635de9e49ea Mon Sep 17 00:00:00 2001 From: lbartoletti Date: Sat, 16 Dec 2017 08:48:36 +0100 Subject: [PATCH 9/9] Stop conflicts --- python/core/geometry/qgsgeometryutils.sip | 64 ++++++++++++----------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/python/core/geometry/qgsgeometryutils.sip b/python/core/geometry/qgsgeometryutils.sip index c818192aad1..69dd38ae1e9 100644 --- a/python/core/geometry/qgsgeometryutils.sip +++ b/python/core/geometry/qgsgeometryutils.sip @@ -103,37 +103,39 @@ Returns the squared distance between a point and a line. static bool segmentIntersection( const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint /Out/, bool &isIntersection /Out/, const double tolerance = 1e-8, bool acceptImproperIntersection = false ); %Docstring Compute the intersection between two segments - \param p1 First segment start point - \param p2 First segment end point - \param q1 Second segment start point - \param q2 Second segment end point - \param intersectionPoint Output parameter, the intersection point - \param isIntersection Output parameter, return true if an intersection is found - \param tolerance The tolerance to use - \param acceptImproperIntersection By default, this method returns true only if segments have proper intersection. If set true, returns also true if segments have improper intersection (end of one segment on other segment ; continuous segments). - :return: Whether the segments intersect - * Example: - \code{.py} - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ) ) - ret[0], ret[1].asWkt(), ret[2] - # Whether the segments intersect, the intersection point, is intersect - # (False, 'Point (0 0)', False) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ) ) - ret[0], ret[1].asWkt(), ret[2] - # (False, 'Point (0 5)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) - ret[0], ret[1].asWkt(), ret[2] - # (True, 'Point (0 5)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ) ) - ret[0], ret[1].asWkt(), ret[2] - # (False, 'Point (0 2)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) - ret[0], ret[1].asWkt(), ret[2] - # (True, 'Point (0 2)', True) - ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ) ) - ret[0], ret[1].asWkt(), ret[2] - # (True, 'Point (0 0)', True) - \endcode + +:param p1: First segment start point +:param p2: First segment end point +:param q1: Second segment start point +:param q2: Second segment end point +:param intersectionPoint: Output parameter, the intersection point +:param isIntersection: Output parameter, return true if an intersection is found +:param tolerance: The tolerance to use +:param acceptImproperIntersection: By default, this method returns true only if segments have proper intersection. If set true, returns also true if segments have improper intersection (end of one segment on other segment ; continuous segments). + +:return: Whether the segments intersect +* Example: +\code{.py} +ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 1 ), QgsPoint( 1, 1 ), QgsPoint( 1, 0 ) ) +ret[0], ret[1].asWkt(), ret[2] +# Whether the segments intersect, the intersection point, is intersect +# (False, 'Point (0 0)', False) +ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ) ) +ret[0], ret[1].asWkt(), ret[2] +# (False, 'Point (0 5)', True) +ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 5 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) +ret[0], ret[1].asWkt(), ret[2] +# (True, 'Point (0 5)', True) +ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ) ) +ret[0], ret[1].asWkt(), ret[2] +# (False, 'Point (0 2)', True) +ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, 0 ), QgsPoint( 0, 5 ), QgsPoint( 0, 2 ), QgsPoint( 1, 5 ), acceptImproperIntersection=True ) +ret[0], ret[1].asWkt(), ret[2] +# (True, 'Point (0 2)', True) +ret = QgsGeometryUtils.segmentIntersection( QgsPoint( 0, -5 ), QgsPoint( 0, 5 ), QgsPoint( 2, 0 ), QgsPoint( -1, 0 ) ) +ret[0], ret[1].asWkt(), ret[2] +# (True, 'Point (0 0)', True) +\endcode %End static QgsPoint projPointOnSegment( const QgsPoint &p, const QgsPoint &s1, const QgsPoint &s2 );