Beispiel #1
0
 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();
 }