public static Point3D? IntersectPlane(Plane plane, Ray ray) { var a = plane.Normal.X; var b = plane.Normal.Y; var c = plane.Normal.Z; var d = -a*plane.Center.X - b*plane.Center.Y - c*plane.Center.Z; //Console.WriteLine("{0} x , {1} y , {2} z , {3} ", a,b,c,d); if (Math.Abs(ray.Direction.MultiplyScalar(plane.Normal)) < Double.Epsilon) //Если N || лучу, то нет пересечения { return null; } else { double t = -(d + ray.Origin.MultiplyScalar(plane.Normal))/(ray.Direction.MultiplyScalar(plane.Normal)); if (t < 0) //Проверка на то, что точка пересечения лежит с нужной стороны от начала луча { return null; } else { return ray.CalculatePoint(t); } } }
public void RayTest(Ray ray, Point3D point, double distance) { { Assert.AreEqual(ray.Origin, new Point3D(0, 0, 0)); Assert.AreEqual(ray.Direction, point); // Console.WriteLine("Ray: " + ray); } }
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; } }
/// <summary> /// Возвращает точку пересечения луча и круга параллельного плоскости z = 0 /// </summary> /// <param name="center">Вершина</param> /// <param name="radius">Радиус</param> /// <param name="ray">Луч</param> /// <returns></returns> public static Point3D? IntersectCircle(Point3D center, double radius, Ray ray) { var p1 = new Point3D(center.X - radius, center.Y, center.Z); var p2 = new Point3D(center.X, center.Y - radius, center.Z); var plane = new ePlane(center, p1, p2); Point3D? point1 = IntersectPlane(plane, ray); if ((point1 != null) && (center.Hypot(point1.Value) <= radius)) { return point1; } else { return null; } }
/// <summary> /// Возвращает точку пересечения луча и треугольника p0p1p2 /// </summary> /// <param name="p0">Вершина</param> /// <param name="p1">Вершина</param> /// <param name="p2">Вершина</param> /// <param name="ray">Луч</param> /// <returns></returns> public static Point3D? IntersectTriangle(Point3D p0, Point3D p1, Point3D p2, Ray ray) { var plane = new ePlane(p0, p1, p2); //Плоскость содержащая треугольник Point3D? point1 = IntersectPlane(plane, ray); if (point1 == null) { return null; } else { int i = ProjectPlane(plane); //Определяем куда проецировать треугольник Point2D point = ProjectPoint(i, point1.Value); Point2D v0 = ProjectPoint(i, p0); Point2D v1 = ProjectPoint(i, p1); Point2D v2 = ProjectPoint(i, p2); Point2D[] regionPoints = new Point2D[] {v0, v2, v1}; return Geometry.IsFromRegion(point, regionPoints) ? point1 : null; } }
public static double IntersectBox(Box box, Ray ray) { Ball ball = GetExternalSphere(box); if (double.IsPositiveInfinity(IntersectBall(ball, ray))) return double.PositiveInfinity; else { var points = new List<Point3D>(); var vertex = GetVertex(box); int[][] order = new int[12][]; order[0] = new[] {0, 2, 1}; order[1] = new[] {1, 2, 4}; order[2] = new[] {0, 5, 2}; order[3] = new[] {0, 3, 5}; order[4] = new[] {0, 3, 1}; order[5] = new[] {1, 3, 6}; order[6] = new[] {3, 5, 6}; order[7] = new[] {6, 5, 7}; order[8] = new[] {1, 6, 7}; order[9] = new[] {1, 7, 4}; order[10] = new[] {2, 5, 7}; order[11] = new[] {2, 7, 4}; for (int i = 0; i < 12; i++) { Point3D? point = TriangleIntersection.IntersectTriangle(vertex[order[i][0]], vertex[order[i][1]], vertex[order[i][2]], ray); if (point != null) points.Add(point.Value); else { point = TriangleIntersection.IntersectTriangle(vertex[order[i][0]], vertex[order[i][2]], vertex[order[i][1]], ray); if (point != null) points.Add(point.Value); } } if (points.Capacity == 0) { return double.PositiveInfinity; } return points.Min(a => ray.Origin.Hypot(a)); } }
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; }
public static double Intersect(Body body, Ray ray) { if (body is Box) return IntersectBox(body as Box, ray); if (body is Ball) return IntersectBall(body as Ball, ray); if (body is Cylinder) return IntersectCylinder(body as Cylinder, ray); return double.PositiveInfinity; //throw new Exception("Unknown body"); }
public void RayTest(Point3D v0, Point3D v1, Point3D v2, Ray ray, Point3D? point) { var computedPoint = Intersector.TriangleIntersection.IntersectTriangle(v0, v1, v2, ray); Assert.AreEqual(point, computedPoint); // Console.WriteLine("Expected: {0}. But was: {1}", point, computedPoint); }
public void RayTest(Ray ray, Point3D center, double radius, Point3D? point) { Point3D? computedPoint = Intersector.IntersectCircle(center, radius, ray); Assert.AreEqual(point, computedPoint); { //Console.WriteLine("Point: {0}. Expected: {1}", computedPoint, point); } }
public void RayTest(Ray ray, Cylinder cylinder, double distance) { var computedDistance = Intersector.IntersectCylinder(cylinder, ray); Assert.AreEqual(distance, computedDistance); // Console.WriteLine("Expected: {0}. But was: {1}", distance, computedDistance); }
public void RayTest(Ray ray, Box box, double distance) { var computedDistance = Intersector.IntersectBox(box, ray); Assert.AreEqual(distance, computedDistance); { Console.WriteLine("Distance: {0}. expected: {1}", computedDistance, distance); } }
public void RayTest(Ray ray, Plane plane, Point3D? point) { Point3D? computedPoint = Intersector.IntersectPlane(plane, ray); Assert.AreEqual(point, computedPoint); { // Console.WriteLine("Point: {0}. Expected: {1}", computedPoint, point); } }
public void RayTest(Ray ray, Ball ball, double distance) { var computedDistance = Intersector.IntersectBall(ball, ray); Assert.AreEqual(distance, computedDistance); { //Console.WriteLine("Distance: {0}. Expected: {1}", computedDistance, distance); } }