如何计算从一个点到矩形的最近点的距离?

时间:2018-08-24 12:12:18

标签: algorithm math vector geometry trigonometry

我在2d坐标系中有一个与轴对齐的矩形,该矩形由左下角的点和右上角的点以及可能在矩形内部或外部的点表示。我想找到该点到矩形最近点的距离,而不管它是否在矩形内。当然,我可以编写一个具有9种不同结果的切换案例,但我希望有一个更优雅的解决方案。
另外,我已经找到了解决此问题的多种解决方案(例如this one),但是如果该点位于框内,所有这些方法都将距离计算为0,这是我不希望的。

3 个答案:

答案 0 :(得分:3)

我的答案比其他答案略长,但这是从不同的角度来看的。

如果您位于 rectangle 之内,则不是关键点,但是如果您位于通过矩形的边并无限延伸(定义一个无限的加号)而定义的走廊中的任何位置,以矩形为中心。

如果它在那些走廊之内,则最近的距离与边之一正交。

如果在外面,则最近的距离是到最近的角的距离。

您的代码可能如下所示:

nearest_distance(rectangle, point):
    d_top = abs(rectangle.top - point.y)
    d_bottom = abs(rectangle.bottom - point.y)
    corner_y = d_top < d_bottom ? rectangle.top : rectangle.bottom

    d_left = abs(rectangle.left - point.x)
    d_right = abs(rectangle.right - point.x)
    corner_x = d_left < d_right ? rectangle.left : rectangle.right

    d_cx = corner_x - point.x
    d_cy = corner_y - point.y
    d_corner = sqrt(d_cx*d_cx + d_cy*d_cy)

    return min(d_top, d_bottom, d_left, d_right, d_corner)

如果您想保存一个sqrt,可以检查您是否在走廊之内或之外。在这种情况下,您可以按以下方式重新排列:

nearest_distance(rectangle, point):
    d_top = abs(rectangle.top - point.y)
    d_bottom = abs(rectangle.bottom - point.y)
    d_left = abs(rectangle.left - point.x)
    d_right = abs(rectangle.right - point.x)

    r = rectangle # just to make the next line neater
    if r.left <= point.x <= r.right or r.bottom <= point.y <= r.top:
        return min(d_top, d_bottom, d_left, d_right)
    else:
        corner_y = d_top < d_bottom ? rectangle.top : rectangle.bottom
        corner_x = d_left < d_right ? rectangle.left : rectangle.right

        d_cx = corner_x - point.x
        d_cy = corner_y - point.y
        d_corner = sqrt(d_cx*d_cx + d_cy*d_cy)
        return d_corner

答案 1 :(得分:1)

您可以扩展MultiRRomero的链接解,并对矩形内的点进行一些附加计算。

对于这些点,矩形边界上最接近的点与该点具有相同的xy坐标。因此,计算到直线的距离是直截了当的,最小的将是所需的距离。

function distance(rect, p) {
  var dx = Math.max(rect.min.x - p.x, 0, p.x - rect.max.x);
  var dy = Math.max(rect.min.y - p.y, 0, p.y - rect.max.y);
  var distance = Math.sqrt(dx*dx + dy*dy)
  if (distance == 0) {
    distance = Math.min(p.x - rect.min.x, rect.max.x - p.x, p.y - rect.min.y, rect.max.y - p.y)
  }
  return distance
}

编辑:错别字固定

答案 2 :(得分:0)

这样的事情怎么样? (第一部分从MultiRRomeros answer“被盗”)

function distance(rect, p) {
  // outside
  var dxo = Math.max(rect.min.x - p.x, 0, p.x - rect.max.x);
  var dyo = Math.max(rect.min.y - p.y, 0, p.y - rect.max.y);
  var hypothenuse = Math.sqrt(dxo*dxo + dyo*dyo);

  // inside
  var dxi = Math.min(rect.max.x - p.x, p.x - rect.min.x);
  var dyi = Math.min(rect.max.y - p.y, p.y - rect.min.y);

  return hypothenuse > 0 ? hypothenuse : Math.min(dxi, dyi);
}