用于在java中查找点和边之间距离的函数

时间:2015-05-31 16:32:16

标签: java math

有没有人在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);
        }

4 个答案:

答案 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),则距离为:

enter image description here

这给出了任何直线和点之间的最短距离。 (a,b,c是实常数)

修改:为了从该行的两个点找到确切的等式,步骤如下:

`y − y1 = m(x − x1)` where m is the slope of the line.

从中简化a = -mb = 1c = m*x1 - y1