Calculating point on line

Monkey Forums/Monkey Programming/Calculating point on line

Shinkiro1(Posted 2011) [#1]


I know the positions of points A, B and C. Know I want to calculate the position of point X (the y coordinate).

I know how to get Distance and Angle between those points but what I need is the specific point X.


Qube(Posted 2011) [#2]
More likely a few ways of doing this. One method would be to use "line intersect" algorithm using points A(xy) to B(xy) and C(xy) to D(xy). D being C with the y flipped.

Line intersect code easily found on the Blitz forums, or to save time here's a link to one GfK wrote : http://www.blitzmax.com/codearcs/codearcs.php?code=2597


Jesse(Posted 2011) [#3]
you can do it with vector math projection. Give me a few and I will post some code for you.


GfK(Posted 2011) [#4]
I have some line intersect code over on bb.com - its blitzmax code, but maths is maths.


Jesse(Posted 2011) [#5]
I hope you understand it:
Strict

Import Mojo

Class Point
	Field x:Float
	Field y:Float
End Class

Class Vector
	Field p1:Point
	Field p2:Point
	Field vx:Float
	Field vy:Float
	Field dx:Float
	Field dy:Float
	Field length:Float
	
	
	Method New()
		p1 = New Point
		p2 = New Point
	End Method
	
	Method display:Void()
		DrawLine p1.x,p1.y,p2.x,p2.y
	End Method
	
End Class

Function Main:Int()
	New game
	Return 0
End Function

Class game Extends App
	Field ac:Vector
	Field ab:Vector
	Field tvx:Float
	Field tvy:Float

	Method OnCreate:Int()
		ac = New Vector
		ac.p1.x = 100
		ac.p1.y = 100
		ac.p2.x = 150
		ac.p2.y = 0
		'calculate vector components
		ac.vx = ac.p2.x - ac.p1.x
		ac.vy = ac.p2.y - ac.p1.y
		'calculate length of vector
		ac.length = Sqrt(ac.vx*ac.vx+ac.vy*ac.vy)
		'calculate normals
		ac.dx = ac.vx/ac.length
		ac.dy = ac.vy/ac.length
		
		
		ab = New Vector
		ab.p1.x = 100
		ab.p1.y = 100
		ab.p2.x = 200
		ab.p2.y = 100
		'calculate vector components
		ab.vx = ab.p2.x - ab.p1.x
		ab.vy = ab.p2.y - ab.p1.y
		'calculate length of vector
		ab.length = Sqrt(ab.vx*ab.vx+ab.vy*ab.vy)
		'calculate normas
		ab.dx = ab.vx/ab.length
		ab.dy = ab.vy/ab.length
		
		'projection of ac onto ab
'*************************************************************
		Local dotproduct:Float = ac.vx*ab.dx+ac.vy*ab.dy
		tvx = dotproduct*ab.dx
		tvy = dotproduct*ab.dy
'**************************************************************
		SetUpdateRate(60)
		Return 0
	End Method
	
	Method OnUpdate:Int()
		Return 0
	End Method
	
	Method OnRender:Int()	
		Cls()
		ac.display()
		ab.display()
		SetColor 255,0,0
		DrawLine ab.p1.x,ab.p1.y,ab.p1.x+tvx,ab.p1.y+tvy
		Return 0
	End Method
	
End Class



tvx and tvy is the point on the line relative to point a.
[edited] corrected an error in the first vector component math


Shinkiro1(Posted 2011) [#6]
@Jesse
Great, only one problem. When the line from a to b is not a straight line the results are not correct (so when ab.p2.y <> ac.p1.y)

What I want to do is to check if the player(Point C) is below A to B (which represents the ground).


Jesse(Posted 2011) [#7]
sorry, small miss calculation in the first vector component math. Corrected post.


Jesse(Posted 2011) [#8]

What I want to do is to check if the player(Point C) is below A to B (which represents the ground).



that is also possible with the dot product of the left normal:
dp = ac.vy*ab.dx- ac.vx*ab.dy

if dp > 0 point b is above the line(on the left hand side of the line)
if dp < 0 point b is below the line ( on the right hand side of the line)
if dp = 0 point b is on the line


Shinkiro1(Posted 2011) [#9]
Thanks a lot, I should definitely learn some vector math.

Here is Jesse's example updated how I intended it (just a few lines)
Strict
'buildopt: run
'buildopt: html5
'buildopt: debug

Import Mojo

Class Point
	Field x:Float
	Field y:Float
End Class

Class Vector
	Field p1:Point
	Field p2:Point
	Field vx:Float
	Field vy:Float
	Field dx:Float
	Field dy:Float
	Field length:Float
	
	
	Method New()
		p1 = New Point
		p2 = New Point
	End Method
	
	Method display:Void()
		DrawLine p1.x,p1.y,p2.x,p2.y
	End Method
	
End Class

Function Main:Int()
	New game
	Return 0
End Function

Class game Extends App
	Field ac:Vector
	Field ab:Vector
	Field tvx:Float
	Field tvy:Float
	
	Field dp:Float 'for checking if point is below line (if dp > 0)
	
	Method OnCreate:Int()
		ac = New Vector
		ac.p1.x = 100
		ac.p1.y = 100
		ac.p2.x = 150
		ac.p2.y = 0
		'calculate vector components
		ac.vx = ac.p2.x - ac.p1.x
		ac.vy = ac.p2.y - ac.p1.y
		'calculate length of vector
		ac.length = Sqrt(ac.vx*ac.vx+ac.vy*ac.vy)
		'calculate normals
		ac.dx = ac.vx/ac.length
		ac.dy = ac.vy/ac.length
		
		ab = New Vector
		ab.p1.x = 100
		ab.p1.y = 100
		ab.p2.x = 200
		ab.p2.y = 120
		'calculate vector components
		ab.vx = ab.p2.x - ab.p1.x
		ab.vy = ab.p2.y - ab.p1.y
		'calculate length of vector
		ab.length = Sqrt(ab.vx*ab.vx+ab.vy*ab.vy)
		'calculate normas
		ab.dx = ab.vx/ab.length
		ab.dy = ab.vy/ab.length
		
		'projection of ac onto ab
'*************************************************************
		Local dotproduct:Float = ac.vx*ab.dx+ac.vy*ab.dy
		tvx = dotproduct*ab.dx
		tvy = dotproduct*ab.dy
'**************************************************************
		SetUpdateRate(60)
		Return 0
	End Method
	
	Method OnUpdate:Int()
		ac.p2.x = MouseX()
		ac.p2.y = MouseY()
		'Updating vector components
		ac.vx = ac.p2.x - ac.p1.x
		ac.vy = ac.p2.y - ac.p1.y
		ac.length = Sqrt(ac.vx*ac.vx+ac.vy*ac.vy)
		ac.dx = ac.vx/ac.length
		ac.dy = ac.vy/ac.length
		'update dp
		dp = ac.vy*ab.dx- ac.vx*ab.dy
		Return 0
	End Method
	
	Method OnRender:Int()	
		Cls()
		Print dp
		If dp > 0
			SetColor 255,0,0
		Else
			SetColor 255, 255, 255
		End
		ac.display()
		ab.display()
		Return 1
	End Method
	
End