寻找点和线段之间的最短距离
Finding shortest distance between a point and a line segment
我需要找到点和线段之间的最短距离(点定义为 x y,线使用端点 ax ay 和 bx by 定义)。
我写了一些代码,但它似乎对某些参数不起作用。我不确定是否只是某处有一些小错误,或者(更有可能)它的工作方式根本上是错误的。
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;
}
}
无效时的示例:
x=0, y=30
ax=-30,ay=0
bx=30, by=0
预期结果是30。我的程序改为returns42.4264。
你在角度部分有一些错误,所以结果是计算其中一端 (30*sqrt(2))。 (请注意,您为距离计算了 atan,但参数应该是两个距离的比率。此外,这种方法存在 atan 范围等问题)。
但你不需要进行三角函数计算。只需找到 ba 和 bp 向量的标量积以及 ab 和 的标量积ap 个向量。
如果第一个是负数(角度abp是钝角),得到到b端点的距离。如果第二个为负数,则获取到 a 端的距离。
如果都是负数,则使用叉积计算的距离(你已经知道了)。请注意,最后的距离可能会在所有比较之后计算。
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
我需要找到点和线段之间的最短距离(点定义为 x y,线使用端点 ax ay 和 bx by 定义)。
我写了一些代码,但它似乎对某些参数不起作用。我不确定是否只是某处有一些小错误,或者(更有可能)它的工作方式根本上是错误的。
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;
}
}
无效时的示例:
x=0, y=30
ax=-30,ay=0
bx=30, by=0
预期结果是30。我的程序改为returns42.4264。
你在角度部分有一些错误,所以结果是计算其中一端 (30*sqrt(2))。 (请注意,您为距离计算了 atan,但参数应该是两个距离的比率。此外,这种方法存在 atan 范围等问题)。
但你不需要进行三角函数计算。只需找到 ba 和 bp 向量的标量积以及 ab 和 的标量积ap 个向量。
如果第一个是负数(角度abp是钝角),得到到b端点的距离。如果第二个为负数,则获取到 a 端的距离。
如果都是负数,则使用叉积计算的距离(你已经知道了)。请注意,最后的距离可能会在所有比较之后计算。
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