穿过两点的“无限”线

时间:2018-10-22 20:22:59

标签: javascript canvas geometry line

在以下设置中,如何绘制一条穿过两点的“无限”线?

var context = document.getElementById("canvas").getContext("2d");

var point1 = {
    x : 120,
    y : 100,
};

var point2 = {
    x : 250,
    y : 300,
};

// mark points in the canvas
context.fillStyle = "red";
context.beginPath();
context.arc(point1.x + 0.5, point1.y + 0.5, 2, 0, 2 * Math.PI);
context.fill();
context.beginPath();
context.arc(point2.x + 0.5, point2.y + 0.5, 2, 0, 2 * Math.PI);
context.fill();

// draw a line between two points
context.beginPath();
context.moveTo(point1.x, point1.y);
context.lineTo(point2.x, point2.y);
context.stroke();

// draw an "infinite" line that passes through two points
// ??
body {
    font-family: sans-serif;
    box-sizing: border-box;
    background-color: hsl(0, 0%, 90%);
}
canvas {
    display: block;
    margin: 20px;
    background: white;
    box-shadow: 0 0 1px rgba(0,0,0,.2),
                0 0 3px rgba(0,0,0,.15),
                0 1px 2px rgba(0,0,0,.15);
}
<canvas id="canvas" width="400" height="400"></canvas>

我知道我需要计算在同一路径上但不在视图(画布)之外的新坐标,并在它们之间绘制一条线以伪造无限线。

这些新坐标不一定必须位于画布的边缘。我认为这需要额外的计算。所以我在想类似的东西

current position ± canvas diagonal (max distance in canvas)

只是为了确保新坐标始终在画布之外,并跳过多余的计算。

如何计算这些新坐标?

2 个答案:

答案 0 :(得分:4)

回溯到代数课,您可以计算出坡度并进行截距,然后使用其在画布边缘上绘制点。如果它们超出了画布的边界,它将创建一条超出边缘的线。

但是请注意,这将不支持水平或垂直线,您必须添加额外的检查以覆盖这些实例。本质上,如果斜率为0,则在两点的y值处从0到canvas.width绘制一条线,如果未定义,则在{{1 }}两点的值。

x
var context = document.getElementById("canvas").getContext("2d");

var point1 = {
    x : 120,
    y : 100,
};

var point2 = {
    x : 250,
    y : 300,
};

var slope = (point2.y - point1.y)/(point2.x - point1.x)
//y = mx + b | b = y - mx
var intercept = point2.y - (slope * point2.x)

function getY(x){ return (slope * x) + intercept; }
function getX(y) { return (y - intercept)/slope; }

// mark points in the canvas
context.fillStyle = "red";
context.beginPath();
context.arc(point1.x + 0.5, point1.y + 0.5, 2, 0, 2 * Math.PI);
context.fill();
context.beginPath();
context.arc(point2.x + 0.5, point2.y + 0.5, 2, 0, 2 * Math.PI);
context.fill();

// draw a line between two points
context.beginPath();
context.moveTo(getX(0), 0);
context.lineTo(point1.x, point1.y);
context.lineTo(point2.x, point2.y);
context.lineTo(getX(context.canvas.height), context.canvas.height);
context.stroke();

// draw an "infinite" line that passes through two points
// ??
body {
    font-family: sans-serif;
    box-sizing: border-box;
    background-color: hsl(0, 0%, 90%);
}
canvas {
    display: block;
    margin: 20px;
    background: white;
    box-shadow: 0 0 1px rgba(0,0,0,.2),
                0 0 3px rgba(0,0,0,.15),
                0 1px 2px rgba(0,0,0,.15);
}

答案 1 :(得分:0)

您需要找到直线与画布边缘相交的两个点:

var context = document.getElementById("canvas").getContext("2d");

var point1 = {
    x : 120,
    y : 100,
};

var point2 = {
    x : 250,
    y : 300,
};

var a = (point2.y - point1.y) / (point2.x - point1.x);
var b = (point1.y * point2.x - point2.y * point1.x) / (point2.x - point1.x);

// mark points in the canvas
context.fillStyle = "red";
context.beginPath();
context.arc(point1.x + 0.5, point1.y + 0.5, 2, 0, 2 * Math.PI);
context.fill();
context.beginPath();
context.arc(point2.x + 0.5, point2.y + 0.5, 2, 0, 2 * Math.PI);
context.fill();

// draw a line between two points
//context.beginPath();
//context.moveTo(point1.x, point1.y);
//context.lineTo(point2.x, point2.y);
//context.stroke();

// draw an "infinite" line that passes through two points
// ??

var canvasWidth = context.canvas.width;
var canvasHeight = context.canvas.height;

var leftSideY = b;
var rightSideY = (canvasWidth * a) + b;
var topSideX = (-b) / a;
var bottomSideX = (canvasHeight - b) / a;

// vertical line
if ([Infinity, -Infinity].includes(a)) {
  topSideX = bottomSideX = point1.x; 
}
// same points
if (a !== a) {
  throw new Error("point1 and point2 are the same") 
}

const edgePoints = [
  {x: 0, y: leftSideY},
  {x: canvasWidth, y: rightSideY},
  {x: topSideX, y: 0},
  {x: bottomSideX, y: canvasHeight}
  ].filter(({x, y}) => x >= 0 && x <= canvasWidth && y >= 0 && y <= canvasHeight);

context.beginPath();

context.moveTo(edgePoints[0].x , edgePoints[0].y || 0);
context.lineTo(edgePoints[1].x || point2.x, edgePoints[1].y || canvasHeight);
context.stroke();
body {
    font-family: sans-serif;
    box-sizing: border-box;
    background-color: hsl(0, 0%, 90%);
}
canvas {
    display: block;
    margin: 20px;
    background: white;
    box-shadow: 0 0 1px rgba(0,0,0,.2),
                0 0 3px rgba(0,0,0,.15),
                0 1px 2px rgba(0,0,0,.15);
}
<canvas id="canvas" width="400" height="400"></canvas>