Legacy GM Find intersection in rectangle

example.png
Heya, I've run into a problem and I'm having trouble coming up with a solution.
I have a box with varying width and height. I have a center point (x1, y1) that is always directly in the center of said box. And lastly: I have a final point (x2, y2) that exists somewhere outside the box.
If a line were to exist between these two points, how would I find the (x, y) coordinate of the point where this line intersects the border of this box (the point seen in red above).
Any assistance or advice would be greatly appreciated. Thank you.
 

jo-thijs

Member
View attachment 9810
Heya, I've run into a problem and I'm having trouble coming up with a solution.
I have a box with varying width and height. I have a center point (x1, y1) that is always directly in the center of said box. And lastly: I have a final point (x2, y2) that exists somewhere outside the box.
If a line were to exist between these two points, how would I find the (x, y) coordinate of the point where this line intersects the border of this box (the point seen in red above).
Any assistance or advice would be greatly appreciated. Thank you.
Suppose the center of your box as coordinates (mx, my) and the box has width w and height h.
Suppose the second point has coordinates (px, py).
You could then use this code, with the coordinates (rx, ry) as result:
Code:
var rx = undefined;
var ry = undefined;

var dx = px - mx;
var dy = py - my;

if dx * 2 >= w || dy * 2 >= h {
    if abs(dx) * h < abs(dy) * w {
        rx = mx + sign(dx) * w * 0.5;
        ry = (rx - mx) * dy / dx + my;
    } else {
        ry = my + sign(dy) * h * 0.5;
        rx = (ry - my) * dx / dy + mx;
    }
}
If there's no intersection, the variables rx and ry will be the value undefined.
 
K

Koohyar

Guest
From a mathematical point of view the solution to this isn't that hard. What I write here is NOT GML. It's mathematical explanation of how that point is going to be calculated (for people who are interested):

m = (y2 - y1)/(x2-x1) // The slope of the line
y = mx + b // The line equation

Any point on a line fits its equation. So the collision point (which IS on the line) is going to fit as well.

Case 1:
Now we know that the x coordinates of the collision point (if it is on the right or left) is going to be the same as the x of the center point of the rectangle + (or minus) the width/2.

Case 2: The same is true for the y coordinates of the collision point if it is on top or down side of the rectangle. If that's the case then the y of the center point of the rectangle + (or minus) the height/2 is going to be the y.

For the case 1 we can use the ordinary equation (y=mx+b). In this case there is no "b" because the line is always on the center point where b=0. Here is the solution for case 1:

y = (y2 - y1)/(x2 - x1) * (x1 + width/2) // for the right side
y = (y2 - y1)/(x2 - x1) * (x1 - width/2) // for the left side

For the case 2 we need to alter the ordinary equation:

y = mx + b ===> x = y/m - b

Here we have the y and want to calculate the x (and still there is no "b"):

x = (y1 - height/2) / (y2 - y1)/(x2 - x1) // for the up side
x = (y1 + height/2) / (y2 - y1)/(x2 - x1) // for the down side

I'm not sure how to do this in GMS1.4 (or GMS2) because the latest version I used was 7. Although the programming solution to this is already provided, I thought it might be cool if I provide a mathematical explanation for you. :)
 

Roderick

Member
To expand on @Koohyar's math, that point will always be on one or more of bbox_left, bbox_right, bbox_top and bbox_bottom. So solve for y if x = bbox_right and bbox_left; if either of those are equal to or between bbox_top and bbox_bottom, you have your intersection. If not, find x for y = bbox_top and bbox_bottom.
 

jo-thijs

Member
From a mathematical point of view the solution to this isn't that hard. What I write here is NOT GML. It's mathematical explanation of how that point is going to be calculated (for people who are interested):

m = (y2 - y1)/(x2-x1) // The slope of the line
y = mx + b // The line equation

Any point on a line fits its equation. So the collision point (which IS on the line) is going to fit as well.

Case 1:
Now we know that the x coordinates of the collision point (if it is on the right or left) is going to be the same as the x of the center point of the rectangle + (or minus) the width/2.

Case 2: The same is true for the y coordinates of the collision point if it is on top or down side of the rectangle. If that's the case then the y of the center point of the rectangle + (or minus) the height/2 is going to be the y.

For the case 1 we can use the ordinary equation (y=mx+b). In this case there is no "b" because the line is always on the center point where b=0. Here is the solution for case 1:

y = (y2 - y1)/(x2 - x1) * (x1 + width/2) // for the right side
y = (y2 - y1)/(x2 - x1) * (x1 - width/2) // for the left side

For the case 2 we need to alter the ordinary equation:

y = mx + b ===> x = y/m - b

Here we have the y and want to calculate the x (and still there is no "b"):

x = (y1 - height/2) / (y2 - y1)/(x2 - x1) // for the up side
x = (y1 + height/2) / (y2 - y1)/(x2 - x1) // for the down side

I'm not sure how to do this in GMS1.4 (or GMS2) because the latest version I used was 7. Although the programming solution to this is already provided, I thought it might be cool if I provide a mathematical explanation for you. :)
It's exactly the same on GM7 with the exceptions of the value undefined not being part of GM7 (which is not a problem)
and the fact that GM7 requires local/temporary variable decleration to be separated from the assignment of a value to that variable (which is even less of a problem).

To expand on @Koohyar's math, that point will always be on one or more of bbox_left, bbox_right, bbox_top and bbox_bottom. So solve for y if x = bbox_right and bbox_left; if either of those are equal to or between bbox_top and bbox_bottom, you have your intersection. If not, find x for y = bbox_top and bbox_bottom.
That's not true actually.
First of all, you don't know if Freddie The Potato is using bounding boxes,
secondly if he would be using them, it'd be bbox_left, bbox_right + 1, bbox_top and bbox_bottom + 1.
 
Top