Line intersections

Hello!
Recently i was having some issues with detecting if two line intersect eachother. What i’ve done so far is to give the two lines a formula: ax+b, and defined all the variables exept for x.
So far i’m able to consistantly determine where it crosses, but: the lines are practically infinite, i’ve tried to comapre the Xsize of the UIframe with the magnitude of the subtraction from the absoluteposition where it intersects and the absoluteposition of the UIFrame. but that didn’t yield any satisfactory results ((PosA-PosB).magnitude).

So what other ways do i have in order to check if two lines intersect within their lenght?
I’ve aslo check wikipedia, but that gave me more of a headache than that it helped.

2 Likes

I’m not sure if I inderstood your problem correctly. If you are trying to find out if the intersection is inside the frame, can’t you just check if the intersection point’s x coordinate and y coordinate are both inside it?

local function isPointInFrame(p, frame)
    local absPos, halfAbsSize = frame.AbsolutePosition, frame.AbsoluteSize/2
    local xPos, yPos = absPos.X, absPos.Y
    local hXSize, hYSize = halfSize.X, halfSize.Y
    local px, py = point.X, point.Y
    return px >= xPos-hXSize and px <= xPos+hXSize and py >= yPos-hYSize and py <= yPos+hYSize
end
1 Like

No. that won’t help. In this example, there are 3 linepeices, 2 of wich intersect eachother. what i need to check is if two line intersect eachother within their lenghts.


Because what happens now, is that it would expect all 3 lines to cross eachother, though at different points, despite the green line already having ended well before they could even come close.

2 Likes

Is the anchor point of the frame Vector2.new(0, 0.5)? And are you doing the distance check for both lines involved in the calculation?

1 Like

it’s .5,.5
it’s really weird though, not because it goes slightly out of bounds, but because it straight up goes across the screen.

1 Like

If it’s Vector2.new(.5, .5), then you’ll need to use half of the x Size of the frame in checking whether the point is within the length.

1 Like

here’s the code. RC is a in y=ax+b.
It didn’t work.

function FindIntersections (RC,B)
	for i,LineFolder in pairs(Lines:GetChildren()) do
		for o,LinePeice in pairs(LineFolder:GetChildren()) do
			if LinePeice ~= CurrentLine then
				local LineRC = LinePeice.RCValue.Value
				if LineRC ~= RC then
					local LineB = LinePeice.BValue.Value
					local LinePos = LinePeice.AbsolutePosition
					local XIntersect = (RC-LineRC)/(LineB-B)
					local IntersectPos = Vector2.new(XIntersect,RC*XIntersect+B)
					print(IntersectPos,"//",(IntersectPos-LinePos).Magnitude)
					if (IntersectPos-LinePos).Magnitude < LinePeice.AbsoluteSize.X*.5 then
						print("Intersected at: ",IntersectPos)
						return true
					end
				end
			end
		end
	end
	return false
end
2 Likes

I edited it to do the check for both lines. Does it now work?

function FindIntersections (RC,B)
	for i,LineFolder in pairs(Lines:GetChildren()) do
		for o,LinePeice in pairs(LineFolder:GetChildren()) do
			if LinePeice ~= CurrentLine then
				local LineRC = LinePeice.RCValue.Value
				if LineRC ~= RC then
					local LineB = LinePeice.BValue.Value
					local LinePos = LinePeice.AbsolutePosition
					local XIntersect = (RC-LineRC)/(LineB-B)
					local IntersectPos = Vector2.new(XIntersect,RC*XIntersect+B)
					print(IntersectPos,"//",(IntersectPos-LinePos).Magnitude)
					local mag1 = (IntersectPos-LinePos).Magnitude
					local mag2 = (InterSectPos-CurrentLine.AbsolutePosition).Magnitude
					if mag1 < LinePeice.AbsoluteSize.X*.5 and and mag2 < CurrentLine.AbsoluteSize.X*.5 then
						print("Intersected at: ",IntersectPos)
						return true
					end
				end
			end
		end
	end
	return false
end
1 Like

Sadly, this doesn’t work. I know for sure that a and b in y=ax+b are defined correctly, because whenever the rotation of the line = 0 or 180, a = 0, and b = it’s absoluteposition.Y.
so that con’t be the issue either. i cannot use raycasting either because it’s 2d.

1 Like

Distance checking doesn’t seem like the most effective solution as you’d have to account for the rotation of the line too, but a better method is using some vector maths:

Say you have your four points for two lines in the screen space. You can get the lines as vectors by subtracting the lines’ points

image

We know that:

b = a + r;
d = c + s;

If we consider two different, randoms scalars, t and u and multiply them to our r and s line, eventually, we might reach an equality:

a + tr = c + us

The lines are intersecting if both conditions are met:

  • 0 <= t <= 1;
  • 0 <= u <= 1;

t and u can be calculated by getting rid of one of them in the equality. Crossing a vector by itself will return a vector with magnitude 0 and u is the scalar coefficient of vector s. Crossing s by itself will get rid of us on the right side and we’re left with:

(a + tr) x s = (c + us) x s
a x s + t(r x s) = c x s

Solving for t:

t(r x s) = (c - a) x s
t = ((c - a) x s) / (r x s)

Solving for u (Alternatively, you can plug in t into any of the equations above to solve for t):

a + tr = c + us
(a + tr) x r = (c + us) x r
a x r = c x r + u(s x r)
(a - c) x r = u(s x r)
u = (a - c) x r / (s x r)

You have both unknowns now. Now, to check if they’re intersecting:

if (t >= 0 and t <= 1) or (u >= 0 and u <= 1) then
    -- intersecting
end

For the code part now:

local function intersecting(a, b, c, d)
    local u = ((a - c):Cross(r)) / s:Cross(r)
    local r = ((c - a):Cross(s)) / r:Cross(s)

    if (t >= 0 and t <= 1) or (u >= 0 and u <= 1) then
        return true
    end

    return false
end
2 Likes

After having done some editing to the function so it can be integrated into my script, i ended up with a few questions and errors. First: r was defined as a vector, but u wasn’t.
t wasn’t defined, but it was a scalar, so i hoped to be able to replace t with r, but i don’t know if that would work.
Vector3:Cross() returns a vector3 that in this case NANed out. so i used a vector2 instead. can’t wait until roblox makes vector2values a thing.

local function FindIntersections(a, b)
	for i,Folder in pairs(Lines:GetChildren()) do
		for o,LinePeice in pairs(Folder:GetChildren()) do
			if LinePeice ~= CurrentLine then
				local c = Vector3.new(LinePeice.StartPos.Value.X,LinePeice.StartPos.Value.Y)
				local d = Vector3.new(LinePeice.EndPos.Value.X,LinePeice.EndPos.Value.Y)
				local r = b-a
				local s = d-c
				local u = ((a - c):Cross(r)) / s:Cross(r)
				local t = ((c - a):Cross(s)) / r:Cross(s)
				if (t >= 0 and t <= 1) or (u >= 0 and u <= 1) then
					return true
				end
			end
		end
	end
	return false
end

Anyways, here’s the entire place. i haven’t focussed on optimizing yet.mathstoobigformybrain.rbxl (29.6 KB)

I didn’t really read through the script when I was writing, leading to errors. So, here’s the fixed intersection function:

local function intersecting(a, b, c, d)
	local r, s = b - a, d - c
	local u = ((a - c):Cross(r)) / s:Cross(r)
	local t = ((c - a):Cross(s)) / r:Cross(s)

	if (t >= 0 and t <= 1) and (u >= 0 and u <= 1) then
		return true
	end

	return false
end

I tested it this time, and it works. Place file: Line Intersections.rbxl (25.6 KB)

I made it so when the two lines are intersecting, a textlabel in the bottom-left corner will appear and say “intersecting”, else it’ll disappear:

https://gyazo.com/b7fdbb09337c1d2feb162788d9f6447d

It was really supposed to be a Vector2, not a Vector3. In my opinion, Vector3Value and all of the other values are quite niche

2 Likes

Thanks for the help. it seems like i have to edit my script quite a bit in order to get it working the way i needed it to, but it detects intersecting lines, and that’s a good place to start from!
Also thanks for teaching me this stuff. i would’ve never known what the cross product could possibly be before our maths class will eventually feature it without it.