How to go about projecting a point onto a line using a direction!

Godot Version

4.2.stable.mono.official

Question

How to go about projecting a point onto a line using a direction!
line-projection-question

Effectively I have this function that takes in a point in 3D space, a line start and end (both in 3D space) and then gives out the closest point on that line.

func project_point_on_line(P : Vector3, A : Vector3, B : Vector3) -> Vector3:
	
	var line_direction = B - A
	var line_length = line_direction.length()
	line_direction = line_direction.normalized()
	
	var change = P-A
	
	var project_length : float = clampf(
		change.dot(line_direction), 0, line_length)
	
	return A + line_direction*project_length # this all works as expected!

And that function above works as expected! But I want instead a function that takes in all that plus a general direction and then gives us the closest point on the line in that general direction rather than the exact closest point.

func project_point_on_line_within_direction(P : Vector3, A : Vector3, B : Vector3, Project_Dir : Vector3) -> Vector3:
	# code that does all that somehow.

But I am not very good at this sort of thing, so I ask you! If you could help with this issue, please do!
Any help would be very appreciated!

The term you want to search for is “line intersection” - you have two lines, the one defined by A and B, and the one defined by P and Project_Dir, although the latter doesn’t have an end point. So what you’re looking for isn’t projection, but finding the intersection.

1 Like

For the implementation I need, the P and Project_Dir aren’t going to be always able to intersect with the line.
line-projection-question-2
But there might be some sort of way to adjust Project_Dir so it does intersect every time so projecting wouldn’t be necessary but I wouldn’t know of one.

not a math wiz this is what i would do. it took several 25 oz rolling rocks before i told myself i knew what you were asking

1 Like

Thats a good way to find the closest point on the line! But I already got the function that gets that done already

func project_point_on_line(P : Vector3, A : Vector3, B : Vector3) -> Vector3:
	
	var line_direction = B - A
	var line_length = line_direction.length()
	line_direction = line_direction.normalized()
	
	var change = P-A
	
	var project_length : float = clampf(
		change.dot(line_direction), 0, line_length)
	
	return A + line_direction*project_length # this all works as expected

I’m asking for a function that like gets our point and smacks it onto the line in the given general direction
line-projection-question-3

Assume the line starts with A and ends with B, your general direction starts with P and ends with Q, then your target closest point should be:

var line_direction = (B - A).normalized()
var projected_p = (P - A).dot(line_direction)
var projected_q = (Q - P).dot(line_direction)
var closest = A + (projected_p + projected_q) * line_direction

To check if the closest point is on the line, just check if (project_p + project_q) is between 0 and 1.
I don’t know if I comprehend your requirements.

1 Like

Ah, sorry, you should check if (project_p + project_q) is between 0 and (B - A).length()

1 Like

It worked! heres the code, after some tinkering!

func project_point_on_line_within_direction(P : Vector3, A : Vector3, B : Vector3, Project_Dir : Vector3) -> Vector3:
	var Q = P + Project_Dir.normalized()
	
	var line_direction = B - A
	var line_length = line_direction.length()
	line_direction = line_direction.normalized()
	
	var projected_p = (P - A).dot(line_direction)
	var projected_q = (Q - P).dot(line_direction)
	var closest = A + (clampf(
		(projected_p + projected_q),
		0, line_length)+clampf(
		projected_p, # it takes both solutions and takes the middle of them!
		0, line_length))/2 * line_direction 
	
	return closest

It still isn’t exact but it works and it does well!
So thank you a lot math wizard man!
( and everyone else who helped too :) )

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.