AutoStereogramDemo.AutoStereogramBuilder.GetCylinderRayIntersection C# (CSharp) Method

GetCylinderRayIntersection() private method

private GetCylinderRayIntersection ( Point3D p1, Point3D p2, double radius, int xProj, int yProj, double eyeXPos, double &x, double &z ) : bool
p1 Point3D
p2 Point3D
radius double
xProj int
yProj int
eyeXPos double
x double
z double
return bool
        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;
        }