예제 #1
0
        public static double IntersectBall(Ball ball, Ray ray)
        {
            //Переменные для возврата корней квадратного уравнения
            double root1, root2;
            //Расчет коэффициентов решения системы уравнений сферы и луча
            var a = ray.Direction.MultiplyScalar(ray.Direction);
            //Вспомогательный вектор
            var location = new Point3D(ball.GetAbsoluteLocation().X, ball.GetAbsoluteLocation().Y, ball.GetAbsoluteLocation().Z + ball.Radius);
            var vec      = ray.Origin - location;
            var b        = 2 * ray.Direction.MultiplyScalar(vec);
            var c        = vec.MultiplyScalar(vec) - Math.Pow(ball.Radius, 2);

            //Обработка решения
            if ((QuadEquation.Solution(a, b, c, out root1, out root2)) && ((root1 >= 0) | (root2 >= 0)))
            {
                if (root1 >= 0)
                {
                    return(ray.DistanceTo(root1));
                }
                else
                {
                    return(ray.DistanceTo(root2));
                }
            }
            return(Double.PositiveInfinity);
        }
예제 #2
0
        public static double IntersectCylinder(Cylinder cylinder, Ray ray)
        {
            //Переменные для возврата корней квадратного уравнения
            double root1, root2;
            var    a      = ray.Direction.X * ray.Direction.X + ray.Direction.Y * ray.Direction.Y;
            var    center = cylinder.GetAbsoluteLocation().ToPoint3D();
            var    top    = cylinder.GetAbsoluteLocation().ToPoint3D() + new Point3D(0, 0, cylinder.Height);
            //Вспомогательный вектор
            var vec = ray.Origin - center;
            var b   = 2 * (ray.Direction.X * vec.X + ray.Direction.Y * vec.Y);
            var c   = Math.Pow(ray.Origin.X - center.X, 2) +
                      Math.Pow(ray.Origin.Y - center.Y, 2) -
                      Math.Pow(cylinder.RBottom, 2);

            //Обработка решения
            if ((QuadEquation.Solution(a, b, c, out root1, out root2)) && ((root1 >= 0) | (root2 >= 0)))
            {
                if (root1 >= 0)
                {
                    Point3D point = ray.CalculatePoint(root1); //если координата z лежит на цилиндре, то это нам подходит
                    if ((point.Z >= center.Z) && (point.Z <= center.Z + cylinder.Height))
                    {
                        return(ray.DistanceTo(root1));
                    }
                    //если координата z за пределами, то проверяем пересечения с верхней и нижней гранью
                    else if (IntersectCircle(center, cylinder.RBottom, ray) != null)
                    {
                        return(ray.Origin.Hypot(IntersectCircle(center, cylinder.RBottom, ray).Value));
                    }
                    else if (IntersectCircle(top, cylinder.RBottom, ray) != null)
                    {
                        return(ray.Origin.Hypot(IntersectCircle(top, cylinder.RBottom, ray).Value));
                    }
                    else
                    {
                        return(double.PositiveInfinity);
                    }
                }
                else //все то же самое для другого корня
                {
                    Point3D point = ray.CalculatePoint(root2);
                    if ((point.Z >= center.Z) && (point.Z <= center.Z + cylinder.Height))
                    {
                        return(ray.DistanceTo(root2));
                    }
                    else if (IntersectCircle(center, cylinder.RBottom, ray) != null)
                    {
                        return(ray.Origin.Hypot(IntersectCircle(center, cylinder.RBottom, ray).Value));
                    }
                    else if (IntersectCircle(top, cylinder.RBottom, ray) != null)
                    {
                        return(ray.Origin.Hypot(IntersectCircle(top, cylinder.RBottom, ray).Value));
                    }
                    else
                    {
                        return(double.PositiveInfinity);
                    }
                }
            }
            else
            {
                return(double.PositiveInfinity);
            }
        }