【问题标题】:straight line between two points两点之间的直线
【发布时间】:2011-05-06 23:24:20
【问题描述】:

在 HTML 画布上,我有多个从 1 到 N 的点,这基本上是一个连接点应用程序,并在 touchstart 时激活。

有验证,因此他们只能连接从 1 到 2 的点 (.. n)。问题是现在没有验证这条线是一条直线,我正在寻找一种算法来做到这一点,这是我到目前为止的想法

  1. 对于 2 个点 (x1,y1) 到 (x2,y2),通过找到斜率并使用公式 y = mx + b 获取所有坐标
  2. 在 touchmove 上获取 x,y 坐标并确保它是前面步骤中的点之一并画一条线,否则不要画线。

有没有更好的方法来做到这一点,或者我可以采取什么不同的方法?

【问题讨论】:

  • 澄清一下:您是要自己连接点,还是要确保用户已正确连接点?
  • @Tikhon Jelvis 我想确保用户已经连接了这些点
  • 好吧,要做到这一点,您可以使用我的答案,查看所有用户的坐标并在它们上调用isValid。您可能希望给用户一点回旋余地,因为绘制 100% 的直线很困难。

标签: javascript algorithm geometry


【解决方案1】:

编辑:似乎我最初误解了这个问题。

就验证路径而言:我认为拥有一个确定一个点是否有效的函数比预先计算所有值更容易。比如:

function getValidatorForPoints(x1, y1, x2, y2) {
    var slope = (y2 - y1) / (x2 - x1);
    return function (x, y) {
        return (y - y1) == slope * (x - x1);
    }
}

那么,鉴于两点,你可以这样做:

var isValid = getValidatorForPoints(x1, y1, x2, y2);
var x = getX(), y = getY();// getX and getY get the user's new point.
if (isValid(x, y)) {
    // Draw
}

这种方法还为您提供了一些灵活性——您可以随时修改函数以降低精确度,以适应那些不太画直线但可以容忍接近的人。

精度: 正如我在评论中提到的,您可以更改函数的行为方式以使其不那么严格。我认为这样做的一个好方法如下:

现在,我们使用公式(y - y1) == slope * (x - x1)。这与(slope * (x - x1)) - (y - y1) == 0 相同。我们可以将零更改为某个正数,以使其接受“靠近”有效线的点,如下所示:

Math.abs((slope * (x - x1)) - (y - y1)) <= n

此处n 更改了点与线的距离才能进行计数。

我很确定这会像宣传的那样有效,有助于解释人们画线有点歪,但有人应该仔细检查我的数学。

【讨论】:

  • 我很确定这与问题无关。
  • @tbridge:我想我可能误解了这个问题。哎呀。
  • 我现在已经对其进行了编辑,假设提问者现在想要检查给定点是否在两点之间的直线上。希望这次我正确理解了这个问题。
  • @Tikhon Jelvis 感谢您的解决方案,它非常优雅,我该如何使其不那么精确?任何指针。
  • 如果 x1 == x2,您在计算斜率时不会除以零吗?
【解决方案2】:
function drawGraphLine(x1, y1, x2, y2, color) {

    var dist = Math.ceil(Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
    var angle = Math.atan2(y2-y1, x2-x1)*180/Math.PI;
    var xshift = dist - Math.abs(x2-x1);
    var yshift = Math.abs(y1-y2)/2;

    var div = document.createElement('div');
    div.style.backgroundColor = color;
    div.style.position = 'absolute';
    div.style.left = (x1 - xshift/2) + 'px';
    div.style.top = (Math.min(y1,y2) + yshift) + 'px';
    div.style.width = dist+'px';
    div.style.height = '3px';
    div.style.WebkitTransform = 'rotate('+angle+'deg)';
    div.style.MozTransform = 'rotate('+angle+'deg)';

}

// 作者:Tomer Almog

【讨论】:

  • 你应该为你的函数添加一个解释
  • 这不回答原问题,也不需要解释。他说的是“使用 html 而不是画布来创建一条线”