简体   繁体   中英

Using JS calculate the line intersection offset between two rectangular nodes

I hate to ask other people on questions like this, but I'm not a trig expert and I need a little help with calculating some positions for line intersects.

Using Javascript and a set of known rectangular nodes with some known width and height (x and y positions of nodes represent the center of each node), I would like to calculate the line offsets for the line's start and end points such that the line only touches the edge of the nodes.

[_____]---->[_____]

The ascii art above shows 2 rectangular nodes with an arrow between. The arrow doesn't intersect the nodes at either the start or the end. This is easy to calculate assuming the line will always be horizontal or vertical, however if the line is at an angle then I'd still like the line to only touch the edges.

Assume the ascii art below has an arrow pointed at the target node (denoted by the pipe symbol)

[_____]
    \
     \|
   [______]

Known variables:

  • Source (1): {x, y, w, h}
  • Target (2): {x, y, w, h}
  • Theta of line (Math.atan(y2-y1, x2-x1))

Desired output:

  • Point of intersection on source node
  • Point of intersection on target node

Example:

{
    sourceIntersect: {x, y}, 
    targetIntersect: {x, y}
}

I found that there's a tool that can calculate the intersection of two lines. If I treated the rectangle as a set of 4 lines I can use the line-intersect npm project to get the point of intersection on one of those 4 lines. The solution was found in the SO question below.

calculating the point of intersection of two lines

This is an example of my code:

// 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
}

To get the intersection of the source node I would pass that as the trg parameter to my function and the target node would represent the src parameter, essentially tricking the system into thinking the line is drawn backwards. This would provide the intersection of the source node, which is represented in the variable trg above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM