예제 #1
0
        /// <summary>
        /// Determines if polygon 1 and polygon 2 at position 1 and position 2, respectively, intersect along axis.
        /// </summary>
        /// <param name="poly1">polygon 1</param>
        /// <param name="poly2">polygon 2</param>
        /// <param name="pos1">Origin of polygon 1</param>
        /// <param name="pos2">Origin of polygon 2</param>
        /// <param name="rot1">Rotation of the first polygon</param>
        /// <param name="rot2">Rotation of the second polygon</param>
        /// <param name="strict">If overlapping is required for intersection</param>
        /// <param name="axis">The axis to check</param>
        /// <returns>If poly1 at pos1 intersects poly2 at pos2 along axis</returns>
        public static bool IntersectsAlongAxis(Polygon2 poly1, Polygon2 poly2, Vector2 pos1, Vector2 pos2, Rotation2 rot1, Rotation2 rot2, bool strict, Vector2 axis)
        {
            var proj1 = ProjectAlongAxis(poly1, pos1, rot1, axis);
            var proj2 = ProjectAlongAxis(poly2, pos2, rot2, axis);

            return(AxisAlignedLine2.Intersects(proj1, proj2, strict));
        }
예제 #2
0
        /// <summary>
        /// Determines if the two polygons intersect using the Separating Axis Theorem.
        /// The performance of this function depends on the number of unique normals
        /// between the two polygons.
        /// </summary>
        /// <param name="poly1">First polygon</param>
        /// <param name="poly2">Second polygon</param>
        /// <param name="pos1">Offset for the vertices of the first polygon</param>
        /// <param name="pos2">Offset for the vertices of the second polygon</param>
        /// <param name="rot1">Rotation of the first polygon</param>
        /// <param name="rot2">Rotation of the second polygon</param>
        /// <param name="strict">
        /// True if the two polygons must overlap a non-zero area for intersection,
        /// false if they must overlap on at least one point for intersection.
        /// </param>
        /// <returns>True if the polygons overlap, false if they do not</returns>
        public static bool IntersectsSat(Polygon2 poly1, Polygon2 poly2, Vector2 pos1, Vector2 pos2, Rotation2 rot1, Rotation2 rot2, bool strict)
        {
            if (rot1 == Rotation2.Zero && rot2 == Rotation2.Zero)
            {
                // This was a serious performance bottleneck so we speed up the fast case
                HashSet <Vector2> seen       = new HashSet <Vector2>();
                Vector2[]         poly1Verts = poly1.Vertices;
                Vector2[]         poly2Verts = poly2.Vertices;
                for (int i = 0, len = poly1.Normals.Count; i < len; i++)
                {
                    var axis  = poly1.Normals[i];
                    var proj1 = ProjectAlongAxis(axis, pos1, poly1Verts);
                    var proj2 = ProjectAlongAxis(axis, pos2, poly2Verts);
                    if (!AxisAlignedLine2.Intersects(proj1, proj2, strict))
                    {
                        return(false);
                    }
                    seen.Add(axis);
                }
                for (int i = 0, len = poly2.Normals.Count; i < len; i++)
                {
                    var axis = poly2.Normals[i];
                    if (seen.Contains(axis))
                    {
                        continue;
                    }

                    var proj1 = ProjectAlongAxis(axis, pos1, poly1Verts);
                    var proj2 = ProjectAlongAxis(axis, pos2, poly2Verts);
                    if (!AxisAlignedLine2.Intersects(proj1, proj2, strict))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            foreach (var norm in poly1.Normals.Select((v) => Tuple.Create(v, rot1)).Union(poly2.Normals.Select((v) => Tuple.Create(v, rot2))))
            {
                var axis = Math2.Rotate(norm.Item1, Vector2.Zero, norm.Item2);
                if (!IntersectsAlongAxis(poly1, poly2, pos1, pos2, rot1, rot2, strict, axis))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #3
0
 /// <summary>
 /// Determines if box1 with origin pos1 intersects box2 with origin pos2.
 /// </summary>
 /// <param name="box1">Box 1</param>
 /// <param name="box2">Box 2</param>
 /// <param name="pos1">Origin of box 1</param>
 /// <param name="pos2">Origin of box 2</param>
 /// <param name="strict">If overlap is required for intersection</param>
 /// <returns>If box1 intersects box2 when box1 is at pos1 and box2 is at pos2</returns>
 public static bool Intersects(Rect2 box1, Rect2 box2, Vector2 pos1, Vector2 pos2, bool strict)
 {
     return(AxisAlignedLine2.Intersects(box1.Min.X + pos1.X, box1.Max.X + pos1.X, box2.Min.X + pos2.X, box2.Max.X + pos2.X, strict, false) &&
            AxisAlignedLine2.Intersects(box1.Min.Y + pos1.Y, box1.Max.Y + pos1.Y, box2.Min.Y + pos2.Y, box2.Max.Y + pos2.Y, strict, false));
 }
예제 #4
0
        /// <summary>
        /// Determines if line1 intersects line2, when line1 is offset by pos1 and line2
        /// is offset by pos2.
        /// </summary>
        /// <param name="line1">Line 1</param>
        /// <param name="line2">Line 2</param>
        /// <param name="pos1">Origin of line 1</param>
        /// <param name="pos2">Origin of line 2</param>
        /// <param name="strict">If overlap is required for intersection</param>
        /// <returns>If line1 intersects line2</returns>
        public static bool Intersects(Line2 line1, Line2 line2, Vector2 pos1, Vector2 pos2, bool strict)
        {
            if (line1.Horizontal && line2.Horizontal)
            {
                return(AxisAlignedLine2.Intersects(line1.MinX + pos1.X, line1.MaxX + pos1.X, line2.MinX + pos2.X, line2.MaxX + pos2.X, strict, false));
            }
            else if (line1.Vertical && line2.Vertical)
            {
                return(AxisAlignedLine2.Intersects(line1.MinY + pos1.Y, line1.MaxY + pos1.Y, line2.MinY + pos2.Y, line2.MaxY + pos2.Y, strict, false));
            }
            else if (line1.Horizontal || line2.Horizontal)
            {
                if (line2.Horizontal)
                {
                    // swap line 1 and 2 to prevent duplicating everything
                    var tmp  = line1;
                    var tmpp = pos1;
                    line1 = line2;
                    pos1  = pos2;
                    line2 = tmp;
                    pos2  = tmpp;
                }

                if (line2.Vertical)
                {
                    return(AxisAlignedLine2.Contains(line1.MinX + pos1.X, line1.MaxX + pos1.X, line2.Start.X + pos2.X, strict, false) &&
                           AxisAlignedLine2.Contains(line2.MinY + pos2.Y, line2.MaxY + pos2.Y, line1.Start.Y + pos1.Y, strict, false));
                }
                else
                {
                    // recalculate line2 y intercept
                    // y = mx + b
                    // b = y - mx
                    var line2YIntInner = line2.Start.Y + pos2.Y - line2.Slope * (line2.Start.X + pos2.X);
                    // check line2.x at line1.y
                    // line2.y = line2.slope * line2.x + line2.yintercept
                    // line1.y = line2.slope * line2.x + line2.yintercept
                    // line1.y - line2.yintercept = line2.slope * line2.x
                    // (line1.y - line2.yintercept) / line2.slope = line2.x
                    var line2XAtLine1Y = (line1.Start.Y + pos1.Y - line2YIntInner) / line2.Slope;
                    return(AxisAlignedLine2.Contains(line1.MinX + pos1.X, line1.MaxX + pos1.X, line2XAtLine1Y, strict, false) &&
                           AxisAlignedLine2.Contains(line2.MinX + pos2.X, line2.MaxX + pos2.X, line2XAtLine1Y, strict, false));
                }
            }
            else if (line1.Vertical)
            {
                // vertical line with regular line
                var line2YIntInner = line2.Start.Y + pos2.Y - line2.Slope * (line2.Start.X + pos2.X);
                var line2YAtLine1X = line2.Slope * (line1.Start.X + pos1.X) + line2YIntInner;
                return(AxisAlignedLine2.Contains(line1.MinY + pos1.Y, line1.MaxY + pos1.Y, line2YAtLine1X, strict, false) &&
                       AxisAlignedLine2.Contains(line2.MinY + pos2.Y, line2.MaxY + pos2.Y, line2YAtLine1X, strict, false));
            }

            // two non-vertical, non-horizontal lines
            var line1YInt = line1.Start.Y + pos1.Y - line1.Slope * (line1.Start.X + pos1.X);
            var line2YInt = line2.Start.Y + pos2.Y - line2.Slope * (line2.Start.X + pos2.X);

            if (Math.Abs(line1.Slope - line2.Slope) <= Math2.DEFAULT_EPSILON)
            {
                // parallel lines
                if (line1YInt != line2YInt)
                {
                    return(false); // infinite lines don't intersect
                }
                // parallel lines with equal y intercept. Intersect if ever at same X coordinate.
                return(AxisAlignedLine2.Intersects(line1.MinX + pos1.X, line1.MaxX + pos1.X, line2.MinX + pos2.X, line2.MaxX + pos2.X, strict, false));
            }
            else
            {
                // two non-parallel lines. Only one possible intersection point

                // y1 = y2
                // line1.Slope * x + line1.YIntercept = line2.Slope * x + line2.YIntercept
                // line1.Slope * x - line2.Slope * x = line2.YIntercept - line1.YIntercept
                // x (line1.Slope - line2.Slope) = line2.YIntercept - line1.YIntercept
                // x = (line2.YIntercept - line1.YIntercept) / (line1.Slope - line2.Slope)
                var x = (line2YInt - line1YInt) / (line1.Slope - line2.Slope);

                return(AxisAlignedLine2.Contains(line1.MinX + pos1.X, line1.MaxX + pos1.X, x, strict, false) &&
                       AxisAlignedLine2.Contains(line2.MinX + pos1.X, line2.MaxX + pos2.X, x, strict, false));
            }
        }