Как продолжить линию и получить координаты ее окончания?

В наличии имеется координатная система по осям 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 шт):

Автор решения: MBo

Если вы уверены, что прямая попадёт в вертикальные края, то достаточно записать из подобия треугольников

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 };
}
→ Ссылка