internal Obstacle FindFirstIntersection(Segment segment)
 {
     if (_box.CannotIntersectWithExcluding(segment))
     {
         return(null);
     }
     for (var i = 0; i < _obstacles.Count; i++)
     {
         var obstacle = _obstacles[i];
         if (obstacle.Inersects(segment))
         {
             return(obstacle);
         }
     }
     for (var i = 0; i < _children.Count; i++)
     {
         var obstacle = _children[i].FindFirstIntersection(segment);
         if (obstacle != null)
         {
             return(obstacle);
         }
     }
     return(null);
 }
Beispiel #2
0
        public bool Inersects(Segment segment)
        {
            //коробка
            if (_box.CannotIntersectWithExcluding(segment))
            {
                return(false);
            }

            //весь обставкл вне линии (TODO: удалить, перенести внутрь сегмента)
            if (OutOfLine(segment))
            {
                return(false);
            }

#if true
            //узнаем, являются ли начало и конец сегмента вершинами обстакла
            int startVerticeIndex = -1;
            int endVerticeIndex   = -1;
            for (var i = 0; i < _vertices.Length; i++)
            {
                if (_vertices[i] == segment.Start)
                {
                    startVerticeIndex = i;
                }
                if (_vertices[i] == segment.End)
                {
                    endVerticeIndex = i;
                }
            }

            //если мы две соседние вершины - можно попытаться выйти раньше
            if (startVerticeIndex != -1 && endVerticeIndex != -1)
            {
                int delta = startVerticeIndex - endVerticeIndex;
                delta = delta < 0 ? -delta : delta;
                if (delta >= _vertices.Length)
                {
                    delta -= _vertices.Length;
                }
                if (delta == 1)
                {
                    return(false);
                }
            }

            var segmentTransposed = segment.TransposeToZero();
            //var segmentPerpendicular = Vector2.Perpendicular(segmentTransposed);

            //по каждой из вершин, совпадающих с началом или концом сегмента:
            //идём от первой к старту, дальше если сегмент больше по правую руку, чем следующий поворот - проткнули
            if (startVerticeIndex != -1)
            {
                var first  = _vertices[startVerticeIndex] - _vertices[startVerticeIndex <= 0 ? _vertices.Length - 1 : startVerticeIndex - 1];
                var second = _vertices[startVerticeIndex >= _vertices.Length - 1 ? 0 : startVerticeIndex + 1] - _vertices[startVerticeIndex];
                if (AngleBetween(first, segmentTransposed) < AngleBetween(first, second))
                {
                    return(true);
                }
            }

            if (endVerticeIndex != -1)
            {
                var first  = _vertices[endVerticeIndex] - _vertices[endVerticeIndex <= 0 ? _vertices.Length - 1 : endVerticeIndex - 1];
                var second = _vertices[endVerticeIndex >= _vertices.Length - 1 ? 0 : endVerticeIndex + 1] - _vertices[endVerticeIndex];
                if (AngleBetween(first, segmentTransposed) < AngleBetween(first, second))
                {
                    return(true);
                }
            }


            //гоним все грани
            //если пересекаем хотя бы одну - пересеклись с обстаклом.
            //если сегмент пересекает вершину грани (смотрим только правую) и обе соседние вершины
            //по разные стороны от сегмента - пересеклись с обстаклом

            //TODO: вот тут не дописано как раз про пересечение с вершиной.

            for (var i = 0; i < _vertices.Length; i++)
            {
                var     secondVertice     = i == _vertices.Length - 1 ? 0 : i + 1;
                Vector2 intersectionPoint = Vector2.zero;
                if (Vector2.SegmentToSegmentIntersection(segment.Start, segment.End, _vertices[i], _vertices[secondVertice], ref intersectionPoint))
                {
                    return(true);
                }
            }

            //иначе - не пересеклись
            return(false);
#else //intersectionDetails.SquaredDistanceFromStart = 0;
            int firstVerticeIndex  = -1;
            int secondVerticeIndex = -1;
            for (var i = 0; i < _vertices.Length; i++)
            {
                if (_vertices[i].Equals(segment.Start))
                {
                    firstVerticeIndex = i;
                }
                if (_vertices[i].Equals(segment.End))
                {
                    secondVerticeIndex = i;
                }
            }
            if (firstVerticeIndex != -1 && secondVerticeIndex != -1)
            {
                int delta = Math.Abs(firstVerticeIndex - secondVerticeIndex);
                if (delta >= _vertices.Length)
                {
                    delta -= _vertices.Length;
                }
                if (delta == 1)
                {
                    return(false);
                }
            }

            for (var i = 0; i < _vertices.Length; i++)
            {
                var     secondVertice     = i == _vertices.Length - 1 ? 0 : i + 1;
                Vector2 intersectionPoint = Vector2.zero;
                if (Vector2.SegmentToSegmentIntersection(segment.Start, segment.End, _vertices[i], _vertices[secondVertice], ref intersectionPoint))
                {
                    return(true);
                }
            }

            if (_vertices.Any(vector2 => vector2.Equals(segment.Start)) && _vertices.Any(vector2 => vector2.Equals(segment.End)))
            {
                //TODO: всё это говнохак, направленный на то, чтобы определить, что мы проходим внутри обстакла, когда наши точки находятся на вершинах обстакла
                //это должно быть удалено
                for (var i = 0; i < _vertices.Length; i++)
                {
                    for (var j = i + 1; j < _vertices.Length; j++)
                    {
                        var innerSegment = Segment.Create(_vertices[i], _vertices[j]);
                        innerSegment = Segment.Extend(innerSegment);
                        Vector2 temp = Vector2.down;
                        if (Vector2.SegmentToSegmentIntersection(segment.Start, segment.End, innerSegment.Start, innerSegment.End, ref temp))
                        {
                            return(true);
                        }
                    }
                }

                var shrinkedSegment = Segment.Shrink(segment);
                if (Contains(shrinkedSegment.Start) || Contains(shrinkedSegment.End))
                {
                    return(true);
                }
            }

            return(false);
#endif
        }