根据斜率将线延伸到画布/绘图区域

时间:2017-07-12 08:26:06

标签: javascript math canvas geometry

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

然而,我并没有真正做到这一点它在一个方向上起作用,一旦你到达中间点就会中断。

请参阅随附的代码示例(我正在处理的真实产品是快速的,但由于它不是与编程语言相关的问题,我将其移植到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>

2 个答案:

答案 0 :(得分:1)

斜率方法不是通用的 - 它不适用于垂直线(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

答案 1 :(得分:1)

此功能可能有所帮助,将x1,y1行转移到x2,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}
}