«Бесконечная» линия, проходящая через две точки - PullRequest
0 голосов
/ 22 октября 2018

В следующей настройке, как я могу нарисовать "бесконечную" линию, которая проходит через две точки?

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 голосов
/ 23 октября 2018

Вам нужно найти две точки, в которых линия пересекается с краями холста:

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>
0 голосов
/ 23 октября 2018

Возвращаясь к классу алгебры, вы можете отработать свой уклон, перехватить и использовать его для построения точек на краю холста.Если они выходят за границы холста, это создаст линию, которая выходит за края.

ОДНАКО, пожалуйста, обратите внимание, что это не будет поддерживать горизонтальные или вертикальные линии, вам придется добавить дополнительные проверкичтобы покрыть эти случаи.По сути, если наклон равен 0, просто нарисуйте линию от 0 до canvas.width при значении y двух точек, а если он не определен, нарисуйте линию от 0 до canvas.height при значении 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);
}
<canvas id="canvas" width="400" height="400"></canvas>
...