【问题标题】:Extend Line based on slope to the end of canvas/drawing area根据坡度将线延伸到画布/绘图区域的末端
【发布时间】:2017-07-12 08:26:06
【问题描述】:

我正在尝试将一条线(从到点(X,Y))延伸到绘图区域的末端。 到目前为止,我找到了一些关于如何计算扩展端点的说明。

但是我并没有真正完成它,它朝一个方向工作,一旦你到达中间点就会中断。

见附件代码示例(我正在开发的真正产品是 swift,但由于它不是编程语言相关的问题,我将其移植到 javascript)

右边好像行得通,黑线是用户选择的,红线是画布边缘的延伸,到左边会产生垃圾。

var canvas = document.getElementById("myCanvas");
var endPoint = {
  x: 200,
  y: 200
};

function draw() {
  //Demo only in final product user also can select the startpoint
  startPoint = {
    x: 150,
    y: 150
  }
  screenMax = {
    x: canvas.height,
    y: canvas.width
  }

  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.beginPath();
  ctx.moveTo(startPoint.x, startPoint.y);
  ctx.lineTo(endPoint.x, endPoint.y);
  ctx.strokeStyle = "#000000";
  ctx.stroke();

  //Extend line to end of canvas according to slope
  var slope = 1.0
  var extendedPoint = {
    x: 0,
    y: 0
  }
  if (endPoint.x != startPoint.x) {
    slope = (endPoint.y - startPoint.y) / (endPoint.x - startPoint.x);
    extendedPoint = {
      x: screenMax.x,
      y: slope * (screenMax.x - endPoint.x) + endPoint.y
    }

  } else {
    slope = 0
    extendedPoint.x = endPoint.x;
    extendedPoint.y = screenMax.y;
  }
  console.log(endPoint);

  //Draw the Extension
  ctx.beginPath();
  ctx.moveTo(endPoint.x, endPoint.y);
  ctx.lineTo(extendedPoint.x, extendedPoint.y);
  ctx.strokeStyle = "#FF0000";
  ctx.stroke();




}
//initial draw
draw();

//handle Mouse dOwn
canvas.onmousedown = function(e) {
  handleMouseDown(e);
}



// handle the mousedown event
//Set new endpoint
function handleMouseDown(e) {
  mouseX = parseInt(e.clientX);
  mouseY = parseInt(e.clientY);
  endPoint = {
    x: mouseX,
    y: mouseY
  }
  draw();
}
<!DOCTYPE html>
<html>

<body>

  <canvas id="myCanvas" width="300" height="300" style="border:1px solid #d3d3d3;">
      Your browser does not support the HTML5 canvas tag.</canvas>


</body>

</html>

【问题讨论】:

    标签: javascript math canvas geometry


    【解决方案1】:

    此函数可能会有所帮助,将行 x1,y1x2,y2 并将其扩展到由 left,top,right,bottom 定义的边界,返回截点为 {x:?,y:?}

    function toBorder(x1, y1, x2, y2, left, top, right, bottom){
        var dx, dy, py, vx, vy;
        vx = x2 - x1;
        vy = y2 - y1;
        dx = vx < 0 ? left : right;
        dy = py = vy < 0 ? top : bottom;
        if(vx === 0){
            dx = x1;
        }else if(vy === 0){
            dy = y1;
        }else{
            dy = y1 + (vy / vx) * (dx - x1);
            if(dy < top || dy > bottom){
                dx = x1 + (vx / vy) * (py - y1);
                dy = py;
            }
        }
        return {x : dx, y : dy}
    }
    

    【讨论】:

    • 太棒了! ? 就像一个魅力!很多谢谢,这里的参考是你的函数的更新小提琴(只是改变了输入参数)jsfiddle.net/tp9e2vaw/3
    • 好哥们,这很完美。我不明白代码是如何工作的,但它可以工作 xD。谢谢。
    【解决方案2】:

    坡度法并不通用 - 它不能用于垂直线 (x0=x1)。

    我会使用射线(线)的参数表示

     x0 = startPoint.x 
     x1 = endPoint.x
     y0 = startPoint.y 
     y1 = endPoint.y
    
    dx = x1 - x0
    dy = y1 - y0
    x = x0 + dx * t
    y = y0 + dy * t
    

    现在检查哪个边界将首先相交(t 值较小)

    //prerequisites: potential border positions
    if dx > 0 then
       bx = width
    else
       bx = 0
    
    if dy > 0 then
       by = height
    else
       bx = 0
    
    //first check for horizontal/vertical lines 
    if dx = 0 then
        return ix = x0,  iy = by
    
    if dy = 0 then
        return iy = y0,  ix = bx
    
    
    //in general case find parameters of intersection with horizontal and vertical edge
    tx = (bx - x0) / dx
    ty = (by - y0) / dy
    
    //and get intersection for smaller parameter value
    if tx <= ty then
       ix = bx
       iy = y0 + tx * dy
    else
       iy = by
       ix = x0 + ty * dx
    
    return ix, iy
    

    【讨论】:

    • 非常感谢您的回答,我的心都碎了。 t 是什么?你能不能把你的变量改成更具可读性,因为我似乎很愚蠢地理解它并采用我上面的示例:(
    • t 是沿线段起点从 0 到 1 变化的参数(以及在它之外更大的值)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 2018-03-20
    • 2014-06-02
    相关资源
    最近更新 更多