Finding intersection of a line and block.

BlitzMax Forums/BlitzMax Beginners Area/Finding intersection of a line and block.

Ryan Burnside(Posted 2009) [#1]
Currently I have a problem. I'm working on a project in which there are particles and blocks. I can easly do a collision check to find if a particle is inside a block. I'm keeping track of the movement of the particles by saving the former position. Every time the particle moves I store the old position using last_x and last_y. Then I update the x and y. Now if a particle hits a rectangle (solid block) I need to know the x and y values of where it hit. I then move the particle to the intersection before drawing. The last x and y will always be inside the block so there will never be 2 intersection points.

"http://img7.imageshack.us/my.php?image=19824179.png"


Jesse(Posted 2009) [#2]
pick your choice:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1855
http://www.blitzbasic.com/codearcs/codearcs.php?code=2131

you should look in the code archives now and then they are verry usefull.
I read some posts in which some members trash the code archs But it has been bery usefull to me. Must be the smart ones with genuinely selfish know it all talent.:)


Warpy(Posted 2009) [#3]
You don't even need to do anything that complicated, as the lines of the block are exactly horizontal and vertical.

Assuming the box's top-left corner is at (bx1,by1) and bottom-right corner is at (bx2,by2) ....

Function boxintersect(last_x#, last_y#, x#, y#, bx1#, by1#, bx2#, by2#, ix# Var, iy# Var)
	'finds point of intersection of line from (last_x,last_y) to (x,y)
	'with the box (bx1,by1,bx2,by2). the ix and iy parameters are var pointers, which means
	'the function fills in the values of the point of intersection in the variables that you give.
	
	If last_x < bx1 And x >= bx1 		'does it cross left edge?
		iy# = last_y + (y - last_y) * (bx1-last_x)/(x-last_x)
		If iy>=by1 And iy<=by2			'is intersection point on left edge?
			ix# = bx1
			Return
		EndIf
	ElseIf last_x > bx2 And x <= bx2	'does it cross right edge?
		iy# = last_y + (y - last_y) * (bx2 - last_x)/(x - last_x)
		If iy>=by1 And iy<=by2			'is intersection point on right edge?
			ix# = bx2
			Return
		EndIf
	EndIf
	
	If last_y < by1 And y >= by1 		'does it cross top edge?
		ix# = last_x + (x - last_x) * (by1 - last_y)/(y - last_y)
		If ix>=bx1 And ix<=bx2			'is intersection point on top edge?
			iy# = by1
			Return
		EndIf
	ElseIf last_y > by2 And y <= by2	'does it cross bottom edge?
		ix# = last_x + (x - last_x) * (by2 - last_y)/(y - last_y)
		If ix>=bx1 And ix<=bx2			'is intersection point on bottom edge?
			iy# = by2
			Return
		EndIf
	EndIf
End Function





'example
Graphics 800,600,0

Global box1#,boy1#,box2#,boy2#
Global ox#,oy#,nx#,ny#

Function maketest()
	box1=Rnd(200,300)
	boy1=Rnd(100,200)
	box2=Rnd(500,600)
	boy2=Rnd(400,500)
	
	nx=Rnd(box1,box2)
	ny=Rnd(boy1,boy2)
	an#=Rnd(360)
	ox=300*Cos(an)+400
	oy=300*Sin(an)+300
	
End Function

maketest

While Not (KeyHit(KEY_ESCAPE) Or AppTerminate())

	If KeyHit(KEY_SPACE)
		'make a new box and line
		maketest
	EndIf
	
	DrawLine box1,boy1,box2,boy1
	DrawLine box1,boy1,box1,boy2
	DrawLine box1,boy2,box2,boy2
	DrawLine box2,boy1,box2,boy2
	
	DrawLine ox,oy,nx,ny
	
	Local ix#,iy#	'variables to store point of intersection in
	boxintersect( ox,oy,nx,ny, box1,boy1,box2,boy2, ix,iy )
	
	DrawOval ix-3,iy-3,6,6
	

	Flip
	Cls
Wend



The way it works is to notice that one line crosses another if it starts on one side of the crossed line, and ends on the other. That's what the first check is about, checking the infinite line which the side of the box is part of. The second check finds the intersection point and checks if it is actually within the line segment which makes up the box.


ImaginaryHuman(Posted 2009) [#4]
Nice code Warpy, useful. Reminds me of `clipping` code that used to be more relevant with direct rendering to a backbuffer with the cpu.


Jesse(Posted 2009) [#5]
Warpy, Added one more to my library. thanks.


Ryan Burnside(Posted 2009) [#6]
Awesome work! Thanks so much!