I've got a function to return any points at which a line segment intersects a circle (up to two results, but potentially zero):
bool Math::GetLineCircleIntersections(Point theCenter, float theRadius, Point theLineA, Point theLineB, Array<Point>& theResults)
{
theResults.Reset();
Point aBA=theLineB-theLineA;
Point aCA=theCenter-theLineA;
float aA=aBA.mX*aBA.mX+aBA.mY*aBA.mY;
float aBBy2=aBA.mX*aCA.mX+aBA.mY*aCA.mY;
float aC=aCA.mX*aCA.mX+aCA.mY*aCA.mY-theRadius*theRadius;
float aPBy2=aBBy2/aA;
float aQ=aC/aA;
float aDisc=aPBy2*aPBy2-aQ;
if (aDisc<0) return false;
float aTmpSqrt=(float)sqrt(aDisc);
float aABScalingFactor1=-aPBy2+aTmpSqrt;
float aABScalingFactor2=-aPBy2-aTmpSqrt;
int aRSpot=0;
if (aABScalingFactor1<=0.0f && aABScalingFactor1>=-1.0f) theResults[aRSpot++]=Point(theLineA.mX-aBA.mX*aABScalingFactor1,theLineA.mY-aBA.mY*aABScalingFactor1);
if (aDisc==0) return true;
if (aABScalingFactor2<=0.0f && aABScalingFactor2>=-1.0f) theResults[aRSpot++]=Point(theLineA.mX-aBA.mX*aABScalingFactor2,theLineA.mY-aBA.mY*aABScalingFactor2);
return true;
}
I want to convert this to a 3D line, with an infinite cylinder-- with the added complication that the 3D cylinder has a tilt axis. I understand that what I'm really doing is intersecting with a sphere that is centered on the cylinder center where the plane of the line cuts it... but... how do I do that? How do I choose the best point to center the sphere, and then having done that, what's my change to turn line->circle intersections into line->sphere?
(I have a vector class that is exactly like the point class)
(Edit) I did manage to convert to a sphere function, only to discover that duh, no, a sphere won't work because a line that's tilted will not enter and exit the same way it would enter and exit a cylinder.
So, question is the same-- how can I convert this to collide with an infinite cylinder given an origin and axis for the cylinder?
I do not think sphere is usable for this...
However why not convert your 3D line into 2D by projecting it on to plane paralel with the cylinder base.
So you got 3D line in form of 2 endpoint p0,p1
and cylinder in form any point on its axis p
, its radius r
and axis unit direction vector d
.
You need 2 unit basis vectors u,v
describing cylinder base
so exploit cross product and cylinder axis for example:
// set u as any unit and non paralel vector to d
u = (1,0,0)
if (abs(dot(u,d))>0.75) u=(0,1,0)
// v set as perpendicular to u,d
v = cross(d,u)
// and make u perpendicular to v,d too
u = cross(v,d)
Project the problem into 2D
p0' = vec2( p0*dot(p0,u) , p0*dot(p0,v) )
p1' = vec2( p1*dot(p1,u) , p1*dot(p1,v) )
p' = vec2( p *dot(p ,u) , p *dot(p ,v) )
Solve the problem
now you just use 2D points p0',p1',p'
and solve your problem using function you already have...