bool QgsTransectSample::closestSegmentPoints( const QgsGeometry& g1, const QgsGeometry& g2, double& dist, QgsPoint& pt1, QgsPoint& pt2 ) { QgsWkbTypes::Type t1 = g1.wkbType(); if ( t1 != QgsWkbTypes::LineString && t1 != QgsWkbTypes::LineString25D ) { return false; } QgsWkbTypes::Type t2 = g2.wkbType(); if ( t2 != QgsWkbTypes::LineString && t2 != QgsWkbTypes::LineString25D ) { return false; } QgsPolyline pl1 = g1.asPolyline(); QgsPolyline pl2 = g2.asPolyline(); if ( pl1.size() < 2 || pl2.size() < 2 ) { return false; } QgsPoint p11 = pl1.at( 0 ); QgsPoint p12 = pl1.at( 1 ); QgsPoint p21 = pl2.at( 0 ); QgsPoint p22 = pl2.at( 1 ); double p1x = p11.x(); double p1y = p11.y(); double v1x = p12.x() - p11.x(); double v1y = p12.y() - p11.y(); double p2x = p21.x(); double p2y = p21.y(); double v2x = p22.x() - p21.x(); double v2y = p22.y() - p21.y(); double denominatorU = v2x * v1y - v2y * v1x; double denominatorT = v1x * v2y - v1y * v2x; if ( qgsDoubleNear( denominatorU, 0 ) || qgsDoubleNear( denominatorT, 0 ) ) { //lines are parallel //project all points on the other segment and take the one with the smallest distance QgsPoint minDistPoint1; double d1 = p11.sqrDistToSegment( p21.x(), p21.y(), p22.x(), p22.y(), minDistPoint1 ); QgsPoint minDistPoint2; double d2 = p12.sqrDistToSegment( p21.x(), p21.y(), p22.x(), p22.y(), minDistPoint2 ); QgsPoint minDistPoint3; double d3 = p21.sqrDistToSegment( p11.x(), p11.y(), p12.x(), p12.y(), minDistPoint3 ); QgsPoint minDistPoint4; double d4 = p22.sqrDistToSegment( p11.x(), p11.y(), p12.x(), p12.y(), minDistPoint4 ); if ( d1 <= d2 && d1 <= d3 && d1 <= d4 ) { dist = sqrt( d1 ); pt1 = p11; pt2 = minDistPoint1; return true; } else if ( d2 <= d1 && d2 <= d3 && d2 <= d4 ) { dist = sqrt( d2 ); pt1 = p12; pt2 = minDistPoint2; return true; } else if ( d3 <= d1 && d3 <= d2 && d3 <= d4 ) { dist = sqrt( d3 ); pt1 = p21; pt2 = minDistPoint3; return true; } else { dist = sqrt( d4 ); pt1 = p21; pt2 = minDistPoint4; return true; } } double u = ( p1x * v1y - p1y * v1x - p2x * v1y + p2y * v1x ) / denominatorU; double t = ( p2x * v2y - p2y * v2x - p1x * v2y + p1y * v2x ) / denominatorT; if ( u >= 0 && u <= 1.0 && t >= 0 && t <= 1.0 ) { dist = 0; pt1.setX( p2x + u * v2x ); pt1.setY( p2y + u * v2y ); pt2 = pt1; dist = 0; return true; } if ( t > 1.0 ) { pt1.setX( p12.x() ); pt1.setY( p12.y() ); } else if ( t < 0.0 ) { pt1.setX( p11.x() ); pt1.setY( p11.y() ); } if ( u > 1.0 ) { pt2.setX( p22.x() ); pt2.setY( p22.y() ); } if ( u < 0.0 ) { pt2.setX( p21.x() ); pt2.setY( p21.y() ); } if ( t >= 0.0 && t <= 1.0 ) { //project pt2 onto g1 pt2.sqrDistToSegment( p11.x(), p11.y(), p12.x(), p12.y(), pt1 ); } if ( u >= 0.0 && u <= 1.0 ) { //project pt1 onto g2 pt1.sqrDistToSegment( p21.x(), p21.y(), p22.x(), p22.y(), pt2 ); } dist = sqrt( pt1.sqrDist( pt2 ) ); return true; }