有没有人在java中有一个函数来查找点和线段/边之间的最短距离?我发现的每个例子都是另一种语言并使用了一堆子函数。它不能基于它们是垂直的假设。
更新
我将一个python函数移植到java。如果有人擅长数学并且可以验证我会很感激。 x和y是点,其他参数用于线段。
public float pDistance(float x, float y, float x1, float y1, float x2, float y2) {
float A = x - x1;
float B = y - y1;
float C = x2 - x1;
float D = y2 - y1;
float dot = A * C + B * D;
float len_sq = C * C + D * D;
float param = -1;
if (len_sq != 0) //in case of 0 length line
param = dot / len_sq;
float xx, yy;
if (param < 0) {
xx = x1;
yy = y1;
}
else if (param > 1) {
xx = x2;
yy = y2;
}
else {
xx = x1 + param * C;
yy = y1 + param * D;
}
float dx = x - xx;
float dy = y - yy;
return (float) Math.sqrt(dx * dx + dy * dy);
}
答案 0 :(得分:2)
来自http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
从点到线的距离(或垂直距离)是 欧氏几何中从点到线的最短距离。它是 将点连接到线的线段的长度 垂直于直线。
你说&#34;它不能基于它们是垂直的假设。&#34;,但是点和线段之间的最短距离代表另一条垂直于该线的线。原始线。因此,它是由A B和C形成的三角形的高度,其中A - 点,B和C是线段的终点。
我们知道所有三个点的坐标,因此我们可以获得三角形的边长。使用Heron的公式:https://www.mathsisfun.com/geometry/herons-formula.html我们可以从https://www.mathsisfun.com/algebra/trig-area-triangle-without-right-angle.html获得等于0.5 * b * h的面积
private static float distBetweenPointAndLine(float x, float y, float x1, float y1, float x2, float y2) {
// A - the standalone point (x, y)
// B - start point of the line segment (x1, y1)
// C - end point of the line segment (x2, y2)
// D - the crossing point between line from A to BC
float AB = distBetween(x, y, x1, y1);
float BC = distBetween(x1, y1, x2, y2);
float AC = distBetween(x, y, x2, y2);
// Heron's formula
float s = (AB + BC + AC) / 2;
float area = (float) Math.sqrt(s * (s - AB) * (s - BC) * (s - AC));
// but also area == (BC * AD) / 2
// BC * AD == 2 * area
// AD == (2 * area) / BC
// TODO: check if BC == 0
float AD = (2 * area) / BC;
return AD;
}
private static float distBetween(float x, float y, float x1, float y1) {
float xx = x1 - x;
float yy = y1 - y;
return (float) Math.sqrt(xx * xx + yy * yy);
}
我不知道它是多么正确,希望真正的数学家可以纠正或备份这个解决方案
答案 1 :(得分:2)
我们可以简化一些事情。你不需要计算参数。您可以做的是找到与该线成直角的矢量 v 。取矢量(A,B)的点积。在2D中,它很容易找到与(C,D)正交的向量,它只是(-D,C)。
acc
如果您担心性能可以更容易使用平方距离,那么最后一行将是
public float pDistance(float x, float y, float x1, float y1, float x2, float y2) {
float A = x - x1; // position of point rel one end of line
float B = y - y1;
float C = x2 - x1; // vector along line
float D = y2 - y1;
float E = -D; // orthogonal vector
float F = C;
float dot = A * E + B * F;
float len_sq = E * E + F * F;
return (float) Math.abs(dot) / Math.sqrt(len_sq);
}
这节省了必须计算平方根。因此,如果要计算最近的边,请找到每条边的平方距离并选择最小的边。
此函数查找到无限线而不是线段的距离。这可能不是你想要的。如果该点超出线段的两端,则问题中的解决方案会有所不同。在那里找到距离最近终点的距离。
答案 2 :(得分:2)
如果您不想自己实施所有这些,我建议您使用JTS。使用LineSegment(对于行)或Coordinate(对于点)的距离方法。给定您的Line的p1和p2点以及Point p3(您想要计算距离),代码看起来像这样:
// create Line
LineSegment ls = new LineSegment(p1.getX(), p1.getY(), p2.getX(), p2.getY());
//calculate distance between Line and Point
double distanceLinePoint = ls.distance(new Coordinate(p3.getX(), p3.getY()));
// calculate distance between Points (p1 - p3)
double distanceBetweenPoints = new Coordinate(p1.getX(), p1.getY()).distance(new Coordinate(p3.getX(), p3.getY()));
答案 3 :(得分:1)
如果你的线经过两个点,你可以准确地确定线的方程式。
如果您的行为ax + by + c = 0
且您的观点为(x0, y0)
,则距离为:
这给出了任何直线和点之间的最短距离。 (a,b,c是实常数)
修改:为了从该行的两个点找到确切的等式,步骤如下:
`y − y1 = m(x − x1)` where m is the slope of the line.
从中简化a = -m
,b = 1
和c = m*x1 - y1