/// <summary> /// Method that gets overlap of two projections /// </summary> /// <param name="first"></param> /// <param name="second"></param> /// <returns></returns> public static double GetOverlap(Projection first, Projection second) { double o_min, o_max; if (first.Max >= second.Max) { o_max = second.Max; } else { o_max = first.Max; } if (first.Min <= second.Min) { o_min = second.Min; } else { o_min = first.Min; } return o_max - o_min; }
/// <summary> /// Method that check overlap of two projections /// </summary> /// <param name="first"></param> /// <param name="second"></param> /// <returns></returns> public static bool IsOverlap(Projection first, Projection second) { if (first.Max <= second.Min || first.Min >= second.Max) { return false; } else { return true; } }
/// <summary> /// /// </summary> /// <param name="circleCenter"></param> /// <param name="circleRadius"></param> /// <param name="rectCenter"></param> /// <param name="rectSize"></param> /// <param name="rectAngle"></param> /// <returns></returns> public static MTV CollisionCircleRectangle(Vector circleCenter, double circleRadius, Vector rectCenter, Vector rectSize, Double rectAngle) { double smallestOverlap = 100000; //Устанавливаем значение малейшего пересечения как можно больше. Vector smallestAxis = new Vector(0, 0); //Ось выхода из столкновения. Vector[] rectCorners = GetRectangleVertices(rectCenter, rectSize, rectAngle); Vector[] rectAxes = GetRectangleAxes(rectCorners); //Получить оси первой и второй фигур. for (int i = 0; i < 2; i++) //Перебор осей первой фигуры { Vector axis = rectAxes[i]; Projection rectProj = Projection.GetProjection(rectCorners, axis); //Проецируем первую фигуру на данную ось Double circleCenterProj = Vector.Multiply(axis, circleCenter); Projection circProj = new Projection(circleCenterProj - circleRadius, circleCenterProj + circleRadius); if (!Projection.IsOverlap(rectProj, circProj)) //Проверяем проекции на пересечение { return null; } else { double overlap = Projection.GetOverlap(rectProj, circProj); //Если пересекаются, ищем модуль пересечения if (overlap < smallestOverlap) //Установления оси минимального пересечения { smallestOverlap = overlap; smallestAxis = axis; } } } Vector minDistVector = rectCorners[0]; double minSDistValue = (rectCorners[0] - circleCenter).LengthSquared; for (int i = 1; i < 4; i++) { double sDistValue = (rectCorners[i] - circleCenter).LengthSquared; if (sDistValue < minSDistValue) { minDistVector = rectCorners[i]; minSDistValue = sDistValue; } } if (minSDistValue < smallestOverlap) { smallestAxis = minDistVector; smallestOverlap = minSDistValue; } Vector distantion_vector = (circleCenter - rectCenter); if (smallestAxis * distantion_vector < 0) { smallestAxis *= -1; } return new MTV(smallestAxis, smallestOverlap); }