private bool GetCylinderRayIntersection(Point3D p1, Point3D p2, double radius, int xProj, int yProj, double eyeXPos, out double x, out double z)
{
x = z = 0;
Point3D proj = new Point3D { X = xProj * PixelWidthInternal, Y = yProj * PixelHeight, Z = 0 };
Point3D eye = new Point3D { X = eyeXPos, Y = eyeYPos, Z = -DistanceToEyes };
Vector3D v1 = (proj - eye).Normalize(), v2 = (p2 - p1).Normalize();
double i = Vector3D.ScalarProduct(v1, v2), j = Vector3D.ScalarProduct(eye - p1, v2);
Vector3D vAux1 = v1 - v2 * i, vAux2 = eye - p1 - v2 * j;
double a = vAux1.Abs2(), b = 2 * Vector3D.ScalarProduct(vAux1, vAux2), c = vAux2.Abs2() - radius * radius;
double discr = b * b - 4 * a * c;
if (discr < 0 || a < 1e-8)
return false;
double x1 = Math.Min(p1.X, p2.X) - 1e-8, x2 = Math.Max(p1.X, p2.X) + 1e-8;
double y1 = Math.Min(p1.Y, p2.Y) - 1e-8, y2 = Math.Max(p1.Y, p2.Y) + 1e-8;
double z1 = Math.Min(p1.Z, p2.Z) - 1e-8, z2 = Math.Max(p1.Z, p2.Z) + 1e-8;
for (int r = 0; r <= 1; r++)
{
double t = (-b + (r == 0 ? -Math.Sqrt(discr) : Math.Sqrt(discr))) / 2 / a;
Point3D pAxis = p1 + v2 * (i * t + j);
if (pAxis.X >= x1 && pAxis.X <= x2 && pAxis.Y >= y1 && pAxis.Y <= y2 && pAxis.Z >= z1 && pAxis.Z <= z2)
{
x = eyeXPos + v1.X * t;
z = -DistanceToEyes + v1.Z * t;
return true;
}
}
return false;
}