Math 给定两点,我如何通过它们画一条线?

Math 给定两点,我如何通过它们画一条线?,math,canvas,vector,line,Math,Canvas,Vector,Line,假设我有{x:10,y:20}和{x:100,y:40},如果我想画一条从10,20开始到100,40结束的线,我会: context.beginPath(); context.moveTo(10, 20); context.lineTo(100, 40); context.stroke(); 但是如果我想划一条线穿过它们,我该怎么办呢?也就是说,这条线比点之间的空间长,但它跨越了两个点?使用以下几种备选方案之一绘制一条更长的线: 将线与画布的边界相交以获得端点 将线与“更正交”画布边

假设我有{x:10,y:20}和{x:100,y:40},如果我想画一条从10,20开始到100,40结束的线,我会:

 context.beginPath();
 context.moveTo(10, 20);
 context.lineTo(100, 40);
 context.stroke();

但是如果我想划一条线穿过它们,我该怎么办呢?也就是说,这条线比点之间的空间长,但它跨越了两个点?

使用以下几种备选方案之一绘制一条更长的线:

  • 将线与画布的边界相交以获得端点
  • 将线与“更正交”画布边界相交,即如果x差的绝对值小于y差的绝对值,则与底部和顶部边界相交,否则与垂直边界线相交
  • 将直线延长一个固定且足够大的差分向量倍数
  • 通过差分向量的倍数延伸直线,使该延伸具有固定且已知的大小
  • 以下哪项最合适取决于您的应用程序。您可以依赖最大画布大小或最小点距离吗?如果不是,则交叉点备选方案更稳健,第二个备选方案的工作量更小。

    您可以使用“反向”插值-我的意思是,您可以使用负值或值>1来获得“线外”插值,而不是使用分数为[0.0,1.0]的插值线:

    代码很简单,使用x和y集,并用一个delta对它们进行插值,这里是一个介于0和1之间的分数值,其中1是其中一个点外的两倍长度:

    function extLine(x1, y1, x2, y2, delta) {
    
        var ox1 = x1 + (x2 - x1) * -delta,
            ox2 = x1 + (x2 - x1) * (1 + delta),
            oy1 = y1 + (y2 - y1) * -delta,
            oy2 = y1 + (y2 - y1) * (1 + delta);
    
        ctx.beginPath();
        ctx.moveTo(ox1, oy1);
        ctx.lineTo(ox2, oy2);
    
        /// for the demo a couple of markers for the original points        
        ctx.rect(x1 - 2, y1 - 2, 5, 5);
        ctx.rect(x2 - 2, y2 - 2, 5, 5);
    
        ctx.stroke();
    }
    
    你可以计算线的长度,然后从结果中得到一个分数,这样你就可以用像素数来扩展线

    以下是一个版本,您可以指定像素数:

    function extLine2(x1, y1, x2, y2, pixels) {
    
        /// calc fraction based on line length and added pixels        
        var xd = x2 - x1,
            yd = y2 - y1,
            len = Math.sqrt(xd * xd + yd * yd),
            delta = pixels / len,
    
            /// as before
            ox1 = x1 + (x2 - x1) * -delta,
            ox2 = x1 + (x2 - x1) * (1 + delta),
            oy1 = y1 + (y2 - y1) * -delta,
            oy2 = y1 + (y2 - y1) * (1 + delta);
    
        ctx.beginPath();
        ctx.moveTo(ox1, oy1);
        ctx.lineTo(ox2, oy2);
    
        ctx.rect(x1 - 2, y1 - 2, 5, 5);
        ctx.rect(x2 - 2, y2 - 2, 5, 5);
    
        ctx.stroke();
    }