1
votes

I need to find the shortest distance between a point and a line segment (point defined as x y, line defined using endpoints ax ay and bx by).

I have written some code but it doesn't seem to work for some of the parameters. I'm not sure if there's just some small mistake somewhere or (more likely) the way it works is fundamentally wrong.

public static double GetDist(double ax, double ay, double bx, double by, double x, double y)
{
    double Perpendicular = Math.Abs((by - ay) * x - (bx - ax) * y + bx * ay - by * ax) /
                           Math.Sqrt((ay - by) * (ay - by) + (ax - bx) * (ax - bx));
    double to_axay = Math.Sqrt((x - ax) * (x - ax) + (y - ay) * (y - ay));
    double to_bxby = Math.Sqrt((x - bx) * (x - bx) + (y - by) * (y - by));

    double dist1 = Math.Sqrt((x - ax) * (x - ax) + (y - ay) * (y - ay));
    double dist2 = Math.Sqrt((bx - ax) * (bx - ax) + (by - ay) * (by - ay));

    double theta1 = Math.Atan(dist1);
    double theta2 = Math.Atan(dist2);

    double angle = Math.Abs(theta2 - theta1);

    if (angle > Math.PI)
        angle = 2 * Math.PI - angle;

    if (angle <= (1 / 2 * Math.PI))
        return Perpendicular;
    else
    {
        if (to_axay >= to_bxby)
            return to_bxby;
        else
            return to_axay;
    }
}

Example when it doesn't work:

x=0, y=30

ax=-30, ay=0

bx=30, by=0

The expected result is 30. My program instead returns 42.4264.

1
If x=0, y=30 and bx=0, by=30, why is the expected result 30? It seems like the point is on the line (it's the same as the endpoint of the line at b) so the result should be 0. Or maybe I'm misunderstanding somethingRufus L
@RufusL Sorry, made a mistake when writing the sample inputs. Fixed them now.386blastprocessing

1 Answers

2
votes

You have some mistake in angle part, so result is calculated for one of the ends (30*sqrt(2)). (Note thet you calculate atan for distance, but argument should be ratio of two distances. Moreover, such approach suffers from issues with atan range and so on).

But you don't need to make trigonometric calculations. Just find scalar product of ba and bp vectors and scalar product of ab and ap vectors.

If the first one is negative (angle abp is obtuse), get distance to b end. If the second one is negative, get distance to a end.

If both are negative, use distance calculated through cross product (you already have got it). Note that the last distance might be calculated after all comparisons.

Checked code:

public static double GetDist(double ax, double ay, double bx, 
                             double by, double x, double y)  {
   if ((ax-bx)*(x-bx)+(ay-by)*(y-by) <= 0)
      return Math.Sqrt((x - bx) * (x - bx) + (y - by) * (y - by));

   if ((bx-ax)*(x-ax)+(by-ay)*(y-ay) <= 0)
      return Math.Sqrt((x - ax) * (x - ax) + (y - ay) * (y - ay));

 return Math.Abs((by - ay)*x - (bx - ax)*y + bx*ay - by*ax) /
     Math.Sqrt((ay - by) * (ay - by) + (ax - bx) * (ax - bx));
}

    public static void Main()
    {
        Console.WriteLine(GetDist(0, 2, 2, 0, 0, 0));
        Console.WriteLine(GetDist(0, 2, 2, 0, 0, 3));
    }



1.41421356237309
1