here are one solution in 2D
it returns 1 or 2 points of intersection (if any)
Joshy
Code: Select all
type VECTOR2D
as single x,y
end type
const epsilon = 0.0001
function RayCircleIntersection(RayOrigin as Vector2D, _
RayDir as Vector2D, _
CirclePos as Vector2D, _
Radius as single, _
HPoints() as Vector2D) as integer
dim as VECTOR2D diff
dim as single r2,dot,dir2,d,ds,l
diff.x = RayOrigin.x - CirclePos.x
diff.y = RayOrigin.y - CirclePos.y
r2 = Radius * Radius
' ray origin inside circle?
If (diff.x * diff.x + diff.y * diff.y) <= r2 then
' normalize direction
l=RayDir.x*RayDir.x + RayDir.y*RayDir.y
if l<>0.0 then
l=1.0/sqr(l)
RayDir.x*=l
RayDir.y*=l
end if
HPoints(0).x = CirclePos.x+Radius*RayDir.x
HPoints(0).y = CirclePos.y+Radius*RayDir.y
Return 1
EndIf
dot = RayDir.x * diff.x + RayDir.y * diff.y
dir2 = RayDir.x * RayDir.x + RayDir.y * RayDir.y
d = dot * dot - Dir2 * (diff.x * diff.x + diff.y * diff.y - R2)
If (d < 0.0) then
return 0
ElseIf d < epsilon then
' one point of intersection
l = -dot / Dir2
If (l < 0.0) Or (l > 1.0) then
Return 0
Else
HPoints(0).x = RayOrigin.x + l * RayDir.x
HPoints(0).y = RayOrigin.y + l * RayDir.y
Return 1
EndIf
Else
' two points of intersection
ds=sqr(d)
' first hit point (nearest)
l = (-dot - ds) / Dir2
dim as integer ret=0
If (l >=0.0) and (l <= 1.0) then
HPoints(ret).x = RayOrigin.x + l * RayDir.x
HPoints(ret).y = RayOrigin.y + l * RayDir.y
ret+=1
end if
' second hit point
l = (-dot + ds) / Dir2
If (l >=0.0) and (l <= 1.0) then
HPoints(ret).x = RayOrigin.x + l * RayDir.x
HPoints(ret).y = RayOrigin.y + l * RayDir.y
ret+=1
end if
return ret
EndIf
End function
const scr_w=640
const scr_h=480
screenres scr_w,scr_h
dim as VECTOR2d RayOrigin,RayDir,SphereCenter,HitPoints(1)
dim as single r
dim as integer nHits
while inkey=""
with RayOrigin :.x=rnd*scr_w:.y=rnd*scr_h:end with
with RayDir :.x=rnd*scr_w- RayOrigin.x:.y=rnd*scr_h - RayOrigin.y:end with
with SphereCenter:.x=rnd*scr_w:.y=rnd*scr_h:end with
R=20
nHits = RayCircleIntersection(RayOrigin,RayDir,SphereCenter,R,HitPoints(0))
if nHits>0 then
cls
line (RayOrigin.x,RayOrigin.y)-step(RayDir.x,RayDir.y),1
circle (SphereCenter.x,SphereCenter.y),r,2
for i as integer=0 to nHits-1
circle (HitPoints(i).x,HitPoints(i).y),2,3+i
next
sleep 1000
end if
wend