С помощью JS вычисляем смещение пересечения линии между двумя прямоугольными узлами - PullRequest
0 голосов
/ 01 сентября 2018

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

Используя Javascript и набор известных прямоугольных узлов с известной шириной и высотой (положения узлов по осям x и y представляют центр каждого узла), я хотел бы рассчитать смещения линий для начальной и конечной точек линии, чтобы линия касается только края узлов.

[_____]---->[_____]

На рисунке ascii выше показаны 2 прямоугольных узла со стрелкой между ними. Стрелка не пересекает узлы ни в начале, ни в конце. Это легко рассчитать, если предположить, что линия всегда будет горизонтальной или вертикальной, однако, если линия находится под углом, я бы все же хотел, чтобы линия касалась только краев.

Предположим, что в приведенной ниже иллюстрации ascii есть стрелка, указывающая на целевой узел (обозначается символом трубы)

[_____]
    \
     \|
   [______]

Известные переменные:

  • Источник (1): {x, y, w, h}
  • Цель (2): {x, y, w, h}
  • Тета линии (Math.atan (y2-y1, x2-x1))

Желаемый вывод:

  • Точка пересечения на исходном узле
  • Точка пересечения на целевом узле
* 1 028 * Пример:
{
    sourceIntersect: {x, y}, 
    targetIntersect: {x, y}
}

1 Ответ

0 голосов
/ 11 сентября 2018

Я обнаружил, что есть инструмент, который может рассчитать пересечение двух линий. Если бы я рассматривал прямоугольник как набор из 4 линий, я мог бы использовать проект npm line-intersect, чтобы получить точку пересечения на одной из этих 4 линий. Решение было найдено в вопросе SO ниже.

расчет точки пересечения двух линий

Это пример моего кода:

// first, get the sizes of the element.
// here we use getBoundingClientRect for an SVG
const clientRect = svgRectElement.getBoundingClientRect();

// extract the width and height
const w = clientRect.width;
const h = clientRect.height;

// trg represents the target point from the element above
// the x and y for trg relate to the center of the element
const top = trg.y - h / 2;
const bottom = trg.y + h / 2;
const left = trg.x - w / 2;
const right = trg.x + w / 2;

// a line extends from src{x,y} to trg{x,y} at the center of both rectangles

// another line extends from left to right at the top of the rectangle   
const topIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, left, top, right, top);

// another line extends from top to bottom at the right of the rectangle
const rightIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, right, top, right, bottom);

// another line extends from left to right at the bottom of the rectangle
const bottomIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, left, bottom, right, bottom);

// another line extends from top to bottom at the left of the rectangle
const leftIntersect = lineIntersect.checkIntersection(src.x, src.y, trg.x, trg.y, left, top, left, bottom);

// only one of the intersect variables above will have a value
if (topIntersect.type !== 'none' && topIntersect.point != null) {
  // topIntersect.point is the x,y of the line intersection with the top of the rectangle
} else if (rightIntersect.type !== 'none' && rightIntersect.point != null) {
  // rightIntersect.point is the x,y of the line intersection with the right of the rectangle
} else if (bottomIntersect.type !== 'none' && bottomIntersect.point != null) {
  // bottomIntersect.point is the x,y of the line intersection with the bottom of the rectangle
} else if (leftIntersect.type !== 'none' && leftIntersect.point != null) {
  // leftIntersect.point is the x,y of the line intersection with the left of the rectangle
}

Чтобы получить пересечение исходного узла, я передал бы это как параметр trg моей функции, а целевой узел представлял бы параметр src, по сути, заставляя систему думать, что линия проведена в обратном направлении. Это обеспечит пересечение исходного узла, который представлен в переменной trg выше.

...