Reputation: 453
I want to create a function wich knows if a line hits a point. Is there any function like that? I also want to set the size of my 3D-points in centimetre and dont know how to do that.
I appreciate your help.
For example:
Assuming that the points have an radius and the lines wouldnt hit the point exact in the middle, is the a function that shows me if a line hit the point?
Upvotes: 1
Views: 1370
Reputation: 11
What you are looking for is an algorithm to find intersections between a line and a sphere. This is a problem commonly found in graphics programming, and there are a lot of articles that probably explain it a lot better than I could. There is one at http://www.lighthouse3d.com/tutorials/maths/ray-sphere-intersection/
The basic idea is that you project the sphere onto the line, and then solve the resulting right triangle , formed by the point of intersection, the sphere's center, and the projected point, using the Pythagorean theorem.
Here is the code I used in my pathtracing renderer:
hitdata intersectwith(Sphere sphere)
{
d3Vector projected;
float t = V.dot(sphere.pos.subtract(O));
projected = V.normalize().scalarmultiply(t); //the projected vector
float distnce = (projected.subtract(sphere.pos.subtract(O))).magnitude();
//the length between the center of your sphere and the projected point
hitdata outdata; // a class containing the results of the intersection
outdata.hit = false;
outdata.t = 110;
if(t<=0)
{
return outdata;
}
if(distnce<sphere.r)
{// the line is less distant from the center of the sphere than the surface
outdata.hit = true;
float deltaT = sqrtf((sphere.r*sphere.r)-(distnce*distnce));//Pythagorean theorem
outdata.coord = O.add(V.scalarmultiply(t-deltaT));
//calculating intersection coordinates
outdata.normal = outdata.coord.subtract(sphere.pos);
outdata.normal = outdata.normal.normalize();//calculating surface normals
outdata.material = sphere.material;
outdata.t = t-deltaT;
}
return outdata;
}
Upvotes: 0
Reputation: 5887
Ok, I have classical solution that work in any dimensions.
First of all, you got sphere and a line, and you need to have good model of them.
Sphere is easy you just have a Vector .center
and .diameter
.
class Sphere:
def __init__( sphere, center, diameter ):
sphere.center=Vector(center)
sphere.diameter=float(diameter)
Line could be more problematic for beginners because it could be defined in many ways.
The most useful comes from parametric equation, you have a direction in Vector .direction
and some staring point .center
. We assume that .direction
is unit length, and .center
is the nearest point on line from (0,0). In most cases we need to create a line, having to points Vectors:
def line_on_two_points( A, B ):
return Line( direction= Vector(B)-A, center=A )
So we have to fix the direction
and center
in the constructor. .direction
is easy to fix wee need just to make it unit length. To find .center
, we need scalar projection. Here is as vector to D:
Having .direction
as unit length A to B and center
as from C to A, we could init our line as:
class Line:
def __init__( line, direction, center ):
line.direction= Vector(direction) / length(direction)
line.center= center - line.direction*dot(center,line.direction)
If we don't have a line, just two points we could just do:
#class Sphere:
def colide_line_on_two_points( sphere, A, B ):
line=line_on_two_points( A-sphere.center, B-sphere.center)
return length(line.center) < sphere.diameter
But when we have a line we try to optimize it as:
#class Sphere:
def colide_line( sphere, line ):
return line.distance_to(sphere.center) < sphere.diameter
The .distance_to()
function is a bit tricky:
#class Line:
def vector_to( line, P ):
return line.center + line.direction * dot(line.direction,P) - P
def distance_to( line, P ):
return length( line.center + line.direction * dot(line.direction,P) - P )
def move_to( line, P ):
line.center += line.direction * dot(line.direction,P) - P
The last but not least is the Vector
type, I try numpy, but it's rather slow for 2D,3D:
from numpy import array as Vector
from numpy import dot
from numpy.linalg import norm as length
Upvotes: 2