📜  使用向量从点到线段的最小距离

📅  最后修改于: 2021-04-27 20:17:50             🧑  作者: Mango

给定线段的两个端点A(x1,y1)B(x2,y2)的坐标和点E(x,y)的坐标;任务是找到从点到以给定坐标形成的线段的最小距离。
注意,一条线的两端都可以无穷大,即一条线没有终点。另一方面,由于线段的长度是固定的,因此线段具有起点和终点。
例子:

方法:想法是使用向量的概念来解决问题,因为最近的点始终位于线段上。假设矢量AB的方向是从A到B,则出现三种情况:

1.如果向量AB(A到B)和向量BE(B到E)的点积为正,则线段AB上距E点最近的点就是B点本身,其中E是给定点。自AB以来。 BE> 0时,给定点的方向与向量AB的方向相同,并且最接近的点必须为B本身,因为最接近的点位于线段上。

2.如果向量AB(A到B)和向量BE(B到E)的点积为负,则线段AB上距点E最近的点就是点A本身,其中E是给定点。自AB以来。 BE <0时,给定点位于线段AB的相反方向上,并且最近点必须为A本身,因为最近点位于线段上。

3.如果点积为0,则点E垂直于线段AB,并且距线段AB到给定点E的垂直距离是最短距离。如果某个任意点F是线段上与E垂直的点,则垂直距离可以计算为| EF |。 = |(AB X AE)/ | AB ||

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
 
// To store the point
#define Point pair
#define F first
#define S second
using namespace std;
 
// Function to return the minimum distance
// between a line segment AB and a point E
double minDistance(Point A, Point B, Point E)
{
 
    // vector AB
    pair AB;
    AB.F = B.F - A.F;
    AB.S = B.S - A.S;
 
    // vector BP
    pair BE;
    BE.F = E.F - B.F;
    BE.S = E.S - B.S;
 
    // vector AP
    pair AE;
    AE.F = E.F - A.F,
    AE.S = E.S - A.S;
 
    // Variables to store dot product
    double AB_BE, AB_AE;
 
    // Calculating the dot product
    AB_BE = (AB.F * BE.F + AB.S * BE.S);
    AB_AE = (AB.F * AE.F + AB.S * AE.S);
 
    // Minimum distance from
    // point E to the line segment
    double reqAns = 0;
 
    // Case 1
    if (AB_BE > 0) {
 
        // Finding the magnitude
        double y = E.S - B.S;
        double x = E.F - B.F;
        reqAns = sqrt(x * x + y * y);
    }
 
    // Case 2
    else if (AB_AE < 0) {
        double y = E.S - A.S;
        double x = E.F - A.F;
        reqAns = sqrt(x * x + y * y);
    }
 
    // Case 3
    else {
 
        // Finding the perpendicular distance
        double x1 = AB.F;
        double y1 = AB.S;
        double x2 = AE.F;
        double y2 = AE.S;
        double mod = sqrt(x1 * x1 + y1 * y1);
        reqAns = abs(x1 * y2 - y1 * x2) / mod;
    }
    return reqAns;
}
 
// Driver code
int main()
{
    Point A = make_pair(0, 0);
    Point B = make_pair(2, 0);
    Point E = make_pair(1, 1);
 
    cout << minDistance(A, B, E);
 
    return 0;
}


Java
// Java implementation of the approach
class GFG
{
 
static class pair
{
    double F, S;
    public pair(double F, double S)
    {
        this.F = F;
        this.S = S;
    }
    public pair() {
    }
}
 
// Function to return the minimum distance
// between a line segment AB and a point E
static double minDistance(pair A, pair B, pair E)
{
 
    // vector AB
    pair AB = new pair();
    AB.F = B.F - A.F;
    AB.S = B.S - A.S;
 
    // vector BP
    pair BE = new pair();
    BE.F = E.F - B.F;
    BE.S = E.S - B.S;
 
    // vector AP
    pair AE = new pair();
    AE.F = E.F - A.F;
    AE.S = E.S - A.S;
 
    // Variables to store dot product
    double AB_BE, AB_AE;
 
    // Calculating the dot product
    AB_BE = (AB.F * BE.F + AB.S * BE.S);
    AB_AE = (AB.F * AE.F + AB.S * AE.S);
 
    // Minimum distance from
    // point E to the line segment
    double reqAns = 0;
 
    // Case 1
    if (AB_BE > 0)
    {
 
        // Finding the magnitude
        double y = E.S - B.S;
        double x = E.F - B.F;
        reqAns = Math.sqrt(x * x + y * y);
    }
 
    // Case 2
    else if (AB_AE < 0)
    {
        double y = E.S - A.S;
        double x = E.F - A.F;
        reqAns = Math.sqrt(x * x + y * y);
    }
 
    // Case 3
    else
    {
 
        // Finding the perpendicular distance
        double x1 = AB.F;
        double y1 = AB.S;
        double x2 = AE.F;
        double y2 = AE.S;
        double mod = Math.sqrt(x1 * x1 + y1 * y1);
        reqAns = Math.abs(x1 * y2 - y1 * x2) / mod;
    }
    return reqAns;
}
 
// Driver code
public static void main(String[] args)
{
    pair A = new pair(0, 0);
    pair B = new pair(2, 0);
    pair E = new pair(1, 1);
 
    System.out.print((int)minDistance(A, B, E));
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 implementation of the approach
from math import sqrt
 
# Function to return the minimum distance
# between a line segment AB and a point E
def minDistance(A, B, E) :
 
    # vector AB
    AB = [None, None];
    AB[0] = B[0] - A[0];
    AB[1] = B[1] - A[1];
 
    # vector BP
    BE = [None, None];
    BE[0] = E[0] - B[0];
    BE[1] = E[1] - B[1];
 
    # vector AP
    AE = [None, None];
    AE[0] = E[0] - A[0];
    AE[1] = E[1] - A[1];
 
    # Variables to store dot product
 
    # Calculating the dot product
    AB_BE = AB[0] * BE[0] + AB[1] * BE[1];
    AB_AE = AB[0] * AE[0] + AB[1] * AE[1];
 
    # Minimum distance from
    # point E to the line segment
    reqAns = 0;
 
    # Case 1
    if (AB_BE > 0) :
 
        # Finding the magnitude
        y = E[1] - B[1];
        x = E[0] - B[0];
        reqAns = sqrt(x * x + y * y);
 
    # Case 2
    elif (AB_AE < 0) :
        y = E[1] - A[1];
        x = E[0] - A[0];
        reqAns = sqrt(x * x + y * y);
 
    # Case 3
    else:
 
        # Finding the perpendicular distance
        x1 = AB[0];
        y1 = AB[1];
        x2 = AE[0];
        y2 = AE[1];
        mod = sqrt(x1 * x1 + y1 * y1);
        reqAns = abs(x1 * y2 - y1 * x2) / mod;
     
    return reqAns;
 
# Driver code
if __name__ == "__main__" :
 
    A = [0, 0];
    B = [2, 0];
    E = [1, 1];
 
    print(minDistance(A, B, E));
 
# This code is contributed by AnkitRai01


C#
// C# implementation of the approach
using System;
 
class GFG
{
 
class pair
{
    public double F, S;
    public pair(double F, double S)
    {
        this.F = F;
        this.S = S;
    }
    public pair() {
    }
}
 
// Function to return the minimum distance
// between a line segment AB and a point E
static double minDistance(pair A, pair B, pair E)
{
 
    // vector AB
    pair AB = new pair();
    AB.F = B.F - A.F;
    AB.S = B.S - A.S;
 
    // vector BP
    pair BE = new pair();
    BE.F = E.F - B.F;
    BE.S = E.S - B.S;
 
    // vector AP
    pair AE = new pair();
    AE.F = E.F - A.F;
    AE.S = E.S - A.S;
 
    // Variables to store dot product
    double AB_BE, AB_AE;
 
    // Calculating the dot product
    AB_BE = (AB.F * BE.F + AB.S * BE.S);
    AB_AE = (AB.F * AE.F + AB.S * AE.S);
 
    // Minimum distance from
    // point E to the line segment
    double reqAns = 0;
 
    // Case 1
    if (AB_BE > 0)
    {
 
        // Finding the magnitude
        double y = E.S - B.S;
        double x = E.F - B.F;
        reqAns = Math.Sqrt(x * x + y * y);
    }
 
    // Case 2
    else if (AB_AE < 0)
    {
        double y = E.S - A.S;
        double x = E.F - A.F;
        reqAns = Math.Sqrt(x * x + y * y);
    }
 
    // Case 3
    else
    {
 
        // Finding the perpendicular distance
        double x1 = AB.F;
        double y1 = AB.S;
        double x2 = AE.F;
        double y2 = AE.S;
        double mod = Math.Sqrt(x1 * x1 + y1 * y1);
        reqAns = Math.Abs(x1 * y2 - y1 * x2) / mod;
    }
    return reqAns;
}
 
// Driver code
public static void Main(String[] args)
{
    pair A = new pair(0, 0);
    pair B = new pair(2, 0);
    pair E = new pair(1, 1);
 
    Console.Write((int)minDistance(A, B, E));
}
}
 
// This code is contributed by 29AjayKumar


输出:
1

时间复杂度: O(1)

辅助空间: O(1)