public abstract bool IntersectsWith(CircleBoundsAspect circle);
public override bool IntersectsWith(CircleBoundsAspect circle) { // сначала грубая проверка, аппроксимация окружностью float distanceBetweenCenters = (position - circle.Position).LengthFast; if (distanceBetweenCenters > longestRadius + circle.Radius) return false; // Для произвольных выпуклых объектов используем Gilbert–Johnson–Keerthi distance algorithm // тут мы используем теорему о разделяющей оси http://www.gamedev.ru/code/terms/SAT // небольшие пояснения тут http://www.ryandudley.com/docs/spheretri.pdf // сначала проверяем 3 прямые, образованные сторонами треугольника for (int i = 0; i < 3; i++) { Vector2 start = vertices[i].Position; Vector2 end = vertices[(i + 1) % 3].Position; if (!TestSegmentIntersection(circle, ref start, ref end)) return false; } // теперь проверяем 3 прямые, проходящие через центр круга и каждую из вершин треугольника for (int i = 0; i < 3; i++) { Vector2 start = vertices[i].Position; Vector2 end = circle.Position; if (!TestSegmentIntersection(circle, ref start, ref end)) return false; } return true; }
private bool TestSegmentIntersection(CircleBoundsAspect circle, ref Vector2 start, ref Vector2 end) { // проецируем каждую вершину треугольника на прямую float triangleProjection; float triangleMinProjection = float.MaxValue; float triangleMaxProjection = float.MinValue; for (int j = 0; j < 3; j++) { triangleProjection = Misc.GetProjection(vertices[j].Position, start, end); if (triangleMinProjection > triangleProjection) triangleMinProjection = triangleProjection; if (triangleMaxProjection < triangleProjection) triangleMaxProjection = triangleProjection; } // получили 2 точки - проекция треугольника на одну из прямых // проецируем центр круга и прибавляем к нему по радиусу с каждой стороны // так как GetProjection возвращает координату, зависящую от длины отрезка, // нужно выразить радиус круга в длине отрезка float circleCenterProjection = Misc.GetProjection(circle.Position, start, end); float radiusLength = circle.Radius / (start - end).LengthFast; float circleMinProjection = circleCenterProjection - radiusLength; float circleMaxProjection = circleCenterProjection + radiusLength; // сравниваем, что cMin < tMax или cMax > tMin // если это не так, то круг и треугольник не пересекаются и дальше можно не проверять if (circleMinProjection > triangleMaxProjection || circleMaxProjection < triangleMinProjection) return false; else return true; }
public override bool IntersectsWith(CircleBoundsAspect circle) { throw new NotImplementedException(); }