Line Intersect Circle

BlitzMax Forums/BlitzMax Beginners Area/Line Intersect Circle

GregBUG(Posted 2007) [#1]
hi!
someone can help me to find a function to
detect if a line collide with a circle ? (and determine intersection points?)

please helpme !!!

I have tried various methods but they are slow...

help!


TaskMaster(Posted 2007) [#2]
To find if the line intersects the circle, just take the point at the center of the circle, use the point distance to line formula and then check if that distance is less than the radius of the circle.


Grey Alien(Posted 2007) [#3]
Pretty sure I posted some code for this in the main BMax forum. Check back a page or two.


SebHoll(Posted 2007) [#4]
Thought I'd have a go at the challenge, so after thinking through the algebra on a piece of paper, how about something like this:

Basically you pass any two points on the line, the center of the circle, and the radius to GetIntersectionLineCircle() and the function will return the points of intersection (if there are any).



I've added a timer, so you can see how fast it is... On my Intel Core 2 Duo 2.00Ghz, it takes approx 0.002ms to find the two points of intersection!

Who say's high school maths doesn't come in handy?


GregBUG(Posted 2007) [#5]
thanks guys!

@SebHoll wow!


SebHoll(Posted 2007) [#6]
I've added this to the code archives in case anybody else needs to use it.


GregBUG(Posted 2007) [#7]
@SebHoll

I have tried the code, but I think there is something that doesn't work with the recognition of the collision...
try this code...

thanks

SuperStrict

Local tmpIntersectLineCircle#[][]

Graphics 640, 480, 0

Local mx:Float, my: Float
While Not KeyHit(key_escape)
	Cls
		SetColor(50, 200, 100)
		DrawCircle(320, 240, 40)
		mx = MouseX()
		my = MouseY()
		SetColor(50, 70, 222)
		DrawLine(0,0, mx, my)
		tmpIntersectLineCircle = GetIntersectionLineCircle( [0.0,0.0], [mx, my], [320.0, 240.0], 40.0 )
		If tmpIntersectLineCircle.length = 1			
			SetColor(255, 0,0)
			DrawCircle(tmpIntersectLineCircle[0][0], tmpIntersectLineCircle[0][1], 4)
		EndIf
		If tmpIntersectLineCircle.length = 2			
			SetColor(255,50,30)
			DrawText "COLLISION", 290, 20
			SetColor(255, 0,0)
			DrawCircle(tmpIntersectLineCircle[1][0], tmpIntersectLineCircle[1][1], 4)
			DrawCircle(tmpIntersectLineCircle[0][0], tmpIntersectLineCircle[0][1], 4)
		EndIf
	
	Flip 0
Wend

Function DrawCircle(xCentre:Float, yCentre:Float, Radius:Float) 
	DrawOval(xCentre - (Radius), yCentre - (Radius), Radius * 2, Radius * 2) 
End Function

Function GetIntersectionLineCircle#[][]( pLineStart#[], pLineEnd#[], pCircleCenter#[], pCircleRadius# )

	Local tmpIntersections#[][]
	
	Local p# = pCircleCenter[0], q# = pCircleCenter[1]
	Local m# = (pLineEnd[1]-pLineStart[1])/(pLineEnd[0]-pLineStart[0])
	Local r# = pCircleRadius
	Local t# = pLineEnd[1]- (m*pLineEnd[0])
	Local s# = t-q
	
	Local a# = m*m + 1, b# = (2*m*s) - (2*p), c# = s^2 + p^2 - (r^2)
	
	Local bsqminfourac# = b*b-4*a*c
	
	If bsqminfourac > 0 Then
		
		bsqminfourac = Sqr(bsqminfourac)
		
		Local x1# = ((-b)+bsqminfourac)/(2*a)
		Local x2# = ((-b)-bsqminfourac)/(2*a)
		
		tmpIntersections = [[x1,(m*x1)+t],[x2,(m*x2)+t]]
		
	ElseIf bsqminfourac = 0 Then
		
		tmpIntersections = [[(-b)/(2*a),(-b*m)/(2*a)+t]]
		
	EndIf
	
	Return tmpIntersections

EndFunction




Poit(Posted 2012) [#8]
has anyone gotten this detection working with vertical or near vertical lines? this returns more inaccurate the closer the line is to vertical and nothing at all for a vertical line.


col(Posted 2012) [#9]
Hiya,

I tried the code and it does suffer from bad vertical intersections. I didn't bother to try fix it as I had this on my h/drive which gives much more information...

If you can't understand how to use it then let me know and I'll help you out.

Move the line with W,S,A,D and the mouse.



Last edited 2012


Poit(Posted 2012) [#10]
Hey!

Thanks so much for this, seems to work awesomely!

the command Var makes those input values update globaly? never knew that... o.0

should be simple enough to incorporate. :D


col(Posted 2012) [#11]

the command Var makes those input values update globaly? never knew that... o.0



Using Var will pass the variable by pointer, or by reference - whatever people choose to call it these days. So altering the value of the variable in the 'called function' will also alter the same variable in the 'calling function'. This can help reduce the use of real Global variables. I dont think you actually need it in this example, as you are passing objects in such as a type or an array as these are passed to a function by reference anyway, but it's there for completeness and understanding when you read the code 6 months later :P

A good use is when you want to return more than one value from the function : bit of a pain as a function can only return one value. Say you have 2 or 3 Local variables in one function that you want altered by another function. Instead of making them Globals, put those variable into the parameters of the function using Var on the end, alter them in the 'called function' and they are also altered in the 'calling code' too.


Poit(Posted 2012) [#12]
yeah, stuff I should have known for years lol.

thanks again.