Как продолжить линию и получить координаты ее окончания?
В наличии имеется координатная система по осям X и Y.
Для примера возьмем ширину холста 493 по ширине и 94 по высоте.
Есть прочерченная прямая на основе следующих координат 2-х точек:
x1 y1 x2 y2:
84 90 389 75
Угол данной прямой будет составлять -16.015905961155084
Вопрос:
Как продлить эту линию до конца холста с учетом текущего угла линии?
И как прорисовать линию от начала холста и до начала данной линии под текущим углом?
Затем необхолимо получить 2 точки где первая будет самым началом этой уже новой большой линии а последняя будет ее концом.
Сам холст на SVG.
Нашел отдаленный пример как это можно сделать на Canvas но без получения конечных координат итоговой линии:
https://codepen.io/yazmeyaa/pen/mdvPwYj
Для лучшего понимания задачи приложу пару скринов с проблематикой того зачем это необходимо:
Есть белая линия которую необходимо дорисовать на чарте с соотвествующим углом до его конца вправо и влево соотвественно. И дорисовать это по следующему принципу:
Ответы (1 шт):
Если вы уверены, что прямая попадёт в вертикальные края, то достаточно записать из подобия треугольников
y_left = y1 + (y2-y1)*(-x1)/(x2-x1)
y_right = y1 + (y2-y1)*(width-x1)/(x2-x1)
В общем случае можно записать прямую в параметрическом виде, и найти решение - ниже для конца луча в сторону второй точки (второе пересечение подобным же образом)
//параметрические уравнения прямой для справки
//x = x1 + dx * t
//y = y1 + dy * t
dx = x2 - x1
dy = y2 - y1
//возможные границы
if dx > 0 then
bx = width
else
bx = 0
if dy > 0 then
by = height
else
by = 0
//проверим на вертикаль/горизонталь
if dx = 0 then
return ix = x1, iy = by
if dy = 0 then
return iy = y1, ix = bx
//в общем случае считаем параметры, при которых будет пересечение с гор/верт ребром
tx = (bx - x1) / dx
ty = (by - y1) / dy
//и выбираем меньший параметр
if tx <= ty then
ix = bx
iy = y1 + tx * dy
else
iy = by
ix = x1 + ty * dx
return ix, iy
Добавлено: код автора вопроса, обрабатывающий продление линии в обе стороны
function drawLineToEdges(x1, y1, x2, y2, width, height) {
let dx = x2 - x1;
let dy = y2 - y1;
let bxRight, bxLeft;
let byTop, byBottom;
let ixRight, iyRight;
let txRight, tyRight;
let ixLeft, iyLeft;
let txLeft, tyLeft;
if (dx > 0) {
bxRight = width;
bxLeft = 0;
} else {
bxRight = 0;
bxLeft = width;
}
if (dy > 0) {
byTop = height;
byBottom = 0;
} else {
byTop = 0;
byBottom = height;
}
if (dx === 0) {
ixRight = x1;
iyRight = Math.min(byTop, height);
ixLeft = x1;
iyLeft = Math.max(byBottom, height);
} else if (dy === 0) {
iyRight = y1;
ixRight = Math.min(bxRight, width);
iyLeft = y1;
ixLeft = Math.max(bxLeft, 0);
} else {
txRight = (bxRight - x1) / dx;
tyRight = (byTop - y1) / dy;
txLeft = (bxLeft - x1) / dx;
tyLeft = (byBottom - y1) / dy;
if (txRight <= tyRight) {
ixRight = bxRight;
iyRight = y1 + txRight * dy;
} else {
iyRight = byTop;
ixRight = x1 + tyRight * dx;
}
if (txLeft <= tyLeft) {
ixLeft = bxLeft;
iyLeft = y1 + txLeft * dy;
} else {
iyLeft = byBottom;
ixLeft = x1 + tyLeft * dx;
}
}
return { x1: ixLeft, y1: iyLeft, x2: ixRight, y2: iyRight };
}

