用于查找点到多边形的最小距离(由html区域定义)的Javascript代码

用于查找点到多边形的最小距离(由html区域定义)的Javascript代码,javascript,html,distance,imagemap,Javascript,Html,Distance,Imagemap,我有一个定义了多个区域的图像地图,都是多边形 我想计算从图像上的一个点(通常由用户点击图像给出)到给定区域外边缘上的闭合点的距离 在我的例子中,可以假设多边形的所有边都不相交,从而使任务更容易一些 检测点是否在区域/多边形的内部、内部或外部也很有趣,例如,如果点位于多边形内部,则距离为负;如果点位于边上,则距离为0 但这对我来说并不是那么重要,因为如果用户点击图像给出了点,就很容易检测到这一点 这个问题的通用解决方案已经给出了,但我想知道是否有人已经有了javascript的实现来解决这个问题

我有一个定义了多个区域的图像地图,都是多边形

我想计算从图像上的一个点(通常由用户点击图像给出)到给定区域外边缘上的闭合点的距离

在我的例子中,可以假设多边形的所有边都不相交,从而使任务更容易一些

检测点是否在区域/多边形的内部、内部或外部也很有趣,例如,如果点位于多边形内部,则距离为负;如果点位于边上,则距离为0

但这对我来说并不是那么重要,因为如果用户点击图像给出了点,就很容易检测到这一点


这个问题的通用解决方案已经给出了,但我想知道是否有人已经有了javascript的实现来解决这个问题

我想做一些类似的事情:

var distance = calculateDistancePointToArea( xCoord, yCoord, areaId );

如果这适用于一个区域的所有可能形状:矩形、圆形和多边形,这将是一个额外的好处。下面是javascript中计算两个坐标之间距离的函数

function(calculateDistancePointToArea(x2, y2, areaId))
{
    var el1 = document.getElementById(areaId);
    var off1 = getOffset(el1);
    // center
    var x1 = off1.left;
    var y1 = off1.top;
    // distance
    var length = Math.sqrt(((x2-x1) * (x2-x1)) + ((y2-y1) * (y2-y1)));       
}

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    var _w = el.offsetWidth|0;
    var _h = el.offsetHeight|0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return {
        top: _y,
        left: _x,
        width: _w,
        height: _h
    };
}

希望它能给你一个想法和帮助。

我为通用坐标编写了一个函数,如果你需要,你可以将它转换为HTML多边形

一个非常简单的解决方案:为每对多边形顶点解一个等式

具有点a和点b的一段多边形(图中为灰色)的算法:

  • 向量A就是点A的坐标
  • 向量S(egment)=b-a
  • 向量N垂直于S(-ys,xs)
  • 向量P是点的坐标
要检查点到线段之间法线的长度,并确保目标点位于线段内部

下面是您要求解的等式:

在解决方案中,i必须介于0和1之间。如果是,则距离为| iN |,点为P+iN,否则它是顶点之间最接近的点(a和b)。然后,您可以在每条边的边中找到最近的点

下面是搜索最近距离的Javascript代码,但修改最近点应该很容易:

function vlen(vector) {
  return Math.sqrt(vector[0]*vector[0] + vector[1] * vector[1]);
}

function vsub(v1, v2) {
  return [v1[0] - v2[0], v1[1] - v2[1]];
}

function vscale(vector, factor) {
  return [vector[0] * factor, vector[1] * factor];
}

function vnorm(v) {
  return [-v[1], v[0]];
}

function distance_to_poly(point, poly) {
  var dists = $.map(poly, function(p1, i) {
    var prev = (i == 0 ? poly.length : i) - 1,
        p2 = poly[prev],
        line = vsub(p2, p1);

    if (vlen(line) == 0)
      return vlen(vsub(point, p1));

    var norm = vnorm(line),
        x1 = point[0],
        x2 = norm[0],
        x3 = p1[0],
        x4 = line[0],
        y1 = point[1],
        y2 = norm[1],
        y3 = p1[1],
        y4 = line[1],

        j = (x3 - x1 - x2 * y3 / y2 + x2 * y1 / y2) / (x2 * y4 / y2 - x4),
        i;

      if (j < 0 || j > 1)
        return Math.min(
          vlen(vsub(point, p1)),
          vlen(vsub(point, p2)));

      i = (y3 + j * y4 - y1) / y2;

      return vlen(vscale(norm, i));
  });

  return Math.min.apply(null, dists);
}
函数vlen(向量){
返回Math.sqrt(向量[0]*向量[0]+向量[1]*向量[1]);
}
函数vsub(v1,v2){
返回[v1[0]-v2[0],v1[1]-v2[1]];
}
函数vscale(向量、因子){
返回[向量[0]*因子,向量[1]*因子];
}
函数vnorm(v){
返回[-v[1],v[0]];
}
函数距离_到_多边形(点,多边形){
var dists=$.map(多边形,函数(p1,i){
var prev=(i==0?多边形长度:i)-1,
p2=多边形[prev],
line=vsub(p2,p1);
如果(vlen(线)==0)
返回vlen(vsub(点,p1));
var范数=vnorm(直线),
x1=点[0],
x2=范数[0],
x3=p1[0],
x4=第[0]行,
y1=点[1],
y2=标准值[1],
y3=p1[1],
y4=第[1]行,
j=(x3-x1-x2*y3/y2+x2*y1/y2)/(x2*y4/y2-x4),
我
如果(j<0 | | j>1)
返回Math.min(
vlen(vsub(点,p1)),
vlen(vsub(point,p2));
i=(y3+j*y4-y1)/y2;
返回vlen(vscale(norm,i));
});
返回Math.min.apply(null,dists);
}