测试一个点是否大约在由另外两个点形成的线段上

时间:2015-07-10 17:29:28

标签: javascript linear-algebra algebra

我想确定是否在点之间进行了点击,并且大致是在连接这两点的线段上进行了点击。

我的问题类似于How can you determine a point is between two other points on a line segment?,但它推迟了两点:

  1. 我在javascript工作,坐标是整数(像素)
  2. 该点不必完全在线段上。需要宽容。
  3. 以下代码改编自this answer,但我不知道如何在线段周围插入公差

    iOS 7a是线段的终点,b是点击的点。我想检查cc之间是否a以及ba

    之间的链接
    b

3 个答案:

答案 0 :(得分:6)

enter image description here

可能是你想要的公式。

以下是此公式的维基百科页面的link

这个来源非常彻底,但可能不是最容易阅读的。您可以阅读维基上的解释,但我将在这里以另一种方式解释它,希望我可以帮助您和其他读者想象它。

x0和y0是点击点的坐标。 x1和y1是第一个线端点的坐标。 x2和y2是同一行上第二个端点的坐标。

这个公式将三个坐标作为三个坐标作为参数 前两组坐标构成了这条线 第三个参数是您的点击点。 它返回一个距离。

好的,现在让我们试着想象一下这个公式在做什么。 所以你取点击点和线的两个端点,你想象一个三角形。我们有三点,这就是我们制作三角形所需的全部内容。

所以,为了找到三角形的高度,你有一个公式,这是熟悉的A =(1/2)bh

的重新排列

enter image description here

因此,当您找到三角形的高度时,您将找到点击点与线条之间的距离。 (这是点击点和线之间的最短距离)

上面更大的距离公式基本上就是这样做的。这里的差异,以及它看起来更复杂的原因是,计算A的部分是明确显示的。

关于您提到的容差,只需设置容差变量,并将距离与该容差进行比较。如果你想要对线附近的点击容忍度更加“模糊”,你需要做更多的数学运算,但我假设你只想知道点击是否距离线一定距离。

当你写这个函数时,请确保你做好记账并在正确的位置设置正确的坐标,否则你会回到距离但不是你想要的距离。 既然你提到你使用的是整数,你可能无法从距离公式得到一个完美的int,我的意思是,看看那个平方根,所以如果你没有得到一个完美的int回来,不用担心,只是向上或向下,

答案 1 :(得分:2)

您可以在两个点之间叠加div,根据需要旋转,并根据需要加厚。附加hover CSS或点击事件到div。

使用距离公式确定div的宽度:

enter image description here

使用此公式确定以度为单位的旋转角度:

Math.atan2((y1-y2),(x1-x2))*(180/Math.PI)

为简单起见,我在我的代码片段中使用了jQuery,但我可以在vanilla JavaScript中快速重写:



var x1= 10+Math.random()*500/4,
    y1= 10+Math.random()*300/4,
    x2= Math.random()*500/2 + 500/4,
    y2= Math.random()*300/2 + 300/4,
    pt= $('.a').width()/2,
    dx= (x2-x1),
    dy= (y2-y1),
    angle= Math.atan2((y1-y2),(x1-x2))*(180/Math.PI),
    tolerance= 30;

$('.a').css({left: x1, top : y1});
$('.b').css({left: x2, top : y2});

$('div.c').css({
  width: Math.sqrt(dx*dx + dy*dy),
  height: tolerance,
  left: x2+pt,
  top: y2+pt,
  transformOrigin: '0px '+tolerance/4+'px',
  transform: 'rotate('+angle+'deg)'
});

$('div.c')
  .click(function() {
    alert('clicked!');
  });

body {
  margin: 0;
  padding: 0;
}

div.a, div.b, div.c {
  position: absolute;
  border-radius: 50%;
  height: 1.2em;
  width: 1.2em;
  text-align: center;
  background: orange;
}

div.c {
  border: 1px solid #eee;
  background: transparent;
  border-radius: 0;
}

div.c:hover ~ div.a, div.c:hover ~ div.b {
  background: lightgreen;
}

div.c hr {
  position: relative;
  top: 50%;
  transform: translateY(-50%);
  height: 1.2em;
  border: none;
  border-top: 1px solid orange;
}

div.c:hover hr {
  border-top: 1px solid green;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="c"><hr></div>
<div class="a">A</div>
<div class="b">B</div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

这是我现在使用的最终javascript函数。

第一部分是使用Ashley Tharp's answer中所述的距离公式,我们首先测试c是否在经过{{tolerance的预定距离(a)内1}}和b

第二部分取自Cyrille Ka' answer from a similar question

  

然后,要知道ca之间是否b,您还需要检查   (b-a)(c-a)的点积为正且较小   而不是ab之间距离的平方。

// a and b are vertices of the segment AB and c is the tested point (here from a mouseclick event (e))
var a={}, b={}, c={};
a.x = 100;
a.y = 100;
b.x = 200;
b.y = 200;
c.x = e.screenX
c.y = e.screeny

console.log(isBetween(a, b, c, 5));

function isBetween(a, b, c, tolerance) {

    //test if the point c is inside a pre-defined distance (tolerance) from the line
    var distance = Math.abs((c.y - b.y)*a.x - (c.x - b.x)*a.y + c.x*b.y - c.y*b.x) / Math.sqrt(Math.pow((c.y-b.y),2) + Math.pow((c.x-b.x),2));
    if (distance > tolerance) { return false; }

    //test if the point c is between a and b
    var dotproduct = (c.x - a.x) * (b.x - a.x) + (c.y - a.y)*(b.y - a.y);
    if (dotproduct < 0) { return false; }

    var squaredlengthba = (b.x - a.x)*(b.x - a.x) + (b.y - a.y)*(b.y - a.y);
    if (dotproduct > squaredlengthba) { return false; }

    return true;
};