//SAT for two rotated rectangles // 1st rectangle is weaker so is moved out by return vector2 public static Vector2 intersectRectangles(RectangleShape a, RectangleShape b) { RectangleShape ar = new RectangleShape(new Rectangle((int)(a.getRectangle().X - a.getRotatePoint().X), (int)(a.getRectangle().Y - a.getRotatePoint().Y), a.getRectangle().Width, a.getRectangle().Height), a.getRotatePoint(), a.getRotation(), 0); //Rotated Vector points of Rectangle A Vector2 aUL = UpperLeftCorner(ar); Vector2 aUR = UpperRightCorner(ar); Vector2 aLL = LowerLeftCorner(ar); Vector2 aLR = LowerRightCorner(ar); Vector2[] aPoints = new Vector2[] { aUL, aUR, aLL, aLR }; int aLeft = (int)Math.Min(Math.Min(aUL.X, aUR.X), Math.Min(aLL.X, aLR.X)); int aTop = (int)Math.Min(Math.Min(aUL.Y, aUR.Y), Math.Min(aLL.Y, aLR.Y)); int aRight = (int)Math.Max(Math.Max(aUL.X, aUR.X), Math.Max(aLL.X, aLR.X)); int aBottom = (int)Math.Max(Math.Max(aUL.Y, aUR.Y), Math.Max(aLL.Y, aLR.Y)); Rectangle aNoRotate = new Rectangle(aLeft, aTop, aRight - aLeft, aBottom - aTop); RectangleShape br = new RectangleShape(new Rectangle((int)(b.getRectangle().X - b.getRotatePoint().X), (int)(b.getRectangle().Y - b.getRotatePoint().Y), b.getRectangle().Width, b.getRectangle().Height), b.getRotatePoint(), b.getRotation(), 0); //Rotated Vector points of Rectangle B Vector2 bUL = UpperLeftCorner(br); Vector2 bUR = UpperRightCorner(br); Vector2 bLL = LowerLeftCorner(br); Vector2 bLR = LowerRightCorner(br); Vector2[] bPoints = new Vector2[] { bUL, bUR, bLL, bLR }; int bLeft = (int)Math.Min(Math.Min(bUL.X, bUR.X), Math.Min(bLL.X, bLR.X)); int bTop = (int)Math.Min(Math.Min(bUL.Y, bUR.Y), Math.Min(bLL.Y, bLR.Y)); int bRight = (int)Math.Max(Math.Max(bUL.X, bUR.X), Math.Max(bLL.X, bLR.X)); int bBottom = (int)Math.Max(Math.Max(bUL.Y, bUR.Y), Math.Max(bLL.Y, bLR.Y)); Rectangle bNoRotate = new Rectangle(bLeft, bTop, bRight - bLeft, bBottom - bTop); //Checks initially for the bounding rectangles non rotated. if (!intersectRectanglesNoRotate(aNoRotate, bNoRotate)) { return Vector2.Zero; } List<Vector2> aRectangleAxis = new List<Vector2>(); aRectangleAxis.Add(aUR - aUL); aRectangleAxis.Add(aUR - aLR); aRectangleAxis.Add(bUL - bLL); aRectangleAxis.Add(bUL - bUR); //Cycle through all of the Axis we need to check. If a collision does not occur //on ALL of the Axis, then a collision is NOT occurring. We can then exit out //immediately and notify the calling function that no collision was detected. If //a collision DOES occur on ALL of the Axis, then there is a collision occurring //between the rotated rectangles. We know this to be true by the Seperating Axis Theorem Vector2 smallest = new Vector2(10000, 10000); foreach (Vector2 aAxis in aRectangleAxis) { Vector2 res = IsAxisCollision(aPoints, bPoints, aAxis); if (res == Vector2.Zero) { return Vector2.Zero; } else { if (Math.Pow(res.X, 2) + Math.Pow(res.Y, 2) < Math.Pow(smallest.X, 2) + Math.Pow(smallest.Y, 2)) { smallest = res; } } } return smallest; }
private static Vector2 intersectCircleRectangle(Circle circle, RectangleShape rectangle) { RectangleShape rectangle2 = new RectangleShape(new Rectangle((int)(rectangle.getRectangle().X - rectangle.getRotatePoint().X), (int)(rectangle.getRectangle().Y - rectangle.getRotatePoint().Y), rectangle.getRectangle().Width, rectangle.getRectangle().Height), rectangle.getRotatePoint(), rectangle.getRotation(), 0); //Rotated Vector points of Rectangle Vector2 rUL = UpperLeftCorner(rectangle2); Vector2 rUR = UpperRightCorner(rectangle2); Vector2 rLL = LowerLeftCorner(rectangle2); Vector2 rLR = LowerRightCorner(rectangle2); Vector2[] bPoints = new Vector2[] { rUL, rUR, rLL, rLR }; int bLeft = (int)Math.Min(Math.Min(rUL.X, rUR.X), Math.Min(rLL.X, rLR.X)); int bTop = (int)Math.Min(Math.Min(rUL.Y, rUR.Y), Math.Min(rLL.Y, rLR.Y)); int bRight = (int)Math.Max(Math.Max(rUL.X, rUR.X), Math.Max(rLL.X, rLR.X)); int bBottom = (int)Math.Max(Math.Max(rUL.Y, rUR.Y), Math.Max(rLL.Y, rLR.Y)); Vector2 Normalisedvec; //Now we normalise the rectangle and circle by rotating the two objects by the rectangles rotation Vector2 rNUL = GeometryHelper.rotatePoint(rUL, new Vector2(rectangle2.getRectangle().X, rectangle2.getRectangle().Y), -rectangle2.getRotation()); Vector2 rNUR = GeometryHelper.rotatePoint(rUR, new Vector2(rectangle2.getRectangle().X, rectangle2.getRectangle().Y), -rectangle2.getRotation()); Vector2 rNLL = GeometryHelper.rotatePoint(rLL, new Vector2(rectangle2.getRectangle().X, rectangle2.getRectangle().Y), -rectangle2.getRotation()); Vector2 rNLR = GeometryHelper.rotatePoint(rLR, new Vector2(rectangle2.getRectangle().X, rectangle2.getRectangle().Y), -rectangle2.getRotation()); Rectangle recNormal = new Rectangle((int)rNUL.X, (int)rNUL.Y, (int)(rNUR.X - rNUL.X), (int)(rNLL.Y - rNUL.Y)); Vector2 circleLoc = GeometryHelper.rotatePoint(circle.getLocation(), new Vector2(rectangle2.getRectangle().X, rectangle2.getRectangle().Y), -rectangle2.getRotation()); //Now we check for voronoi regions on the rectangle bool voronoid = false; Vector2 vertexVoronoi; //See if cirlce point fits in any voronoi region if (circleLoc.X < recNormal.Left && circleLoc.Y < recNormal.Top) { vertexVoronoi = rNUL; voronoid = true; } if (circleLoc.X > recNormal.Right && circleLoc.Y < recNormal.Top) { vertexVoronoi = rNUR; voronoid = true; } if (circleLoc.X < recNormal.Left && circleLoc.Y > recNormal.Bottom) { vertexVoronoi = rNLL; voronoid = true; } if (circleLoc.X > recNormal.Right && circleLoc.Y > recNormal.Bottom) { vertexVoronoi = rNLR; voronoid = true; } if (!voronoid) { circle.setRotation(0.0f); Rectangle circleRec = new Rectangle((int)(circleLoc.X - circle.getRadius()), (int)(circleLoc.Y - circle.getRadius()), (int)circle.getRadius() * 2, (int)circle.getRadius() * 2); Normalisedvec = intersectRectangles(new RectangleShape(circleRec, Vector2.Zero, 0, 0), new RectangleShape(recNormal, Vector2.Zero, 0, 0)); } else { circle.setRotation((float)Math.PI / 4); Rectangle circleRec = new Rectangle((int)(circleLoc.X), (int)(circleLoc.Y), (int)circle.getRadius() * 2, (int)circle.getRadius() * 2); Normalisedvec = intersectRectangles(new RectangleShape(circleRec, new Vector2(circle.getRadius(), circle.getRadius()), (float)Math.PI / 4, 0), new RectangleShape(recNormal, Vector2.Zero, 0, 0)); } return GeometryHelper.rotatePoint(Normalisedvec, Vector2.Zero, rectangle.getRotation()); }
public static Vector2 UpperRightCorner(RectangleShape a) { Vector2 aUpperRight = new Vector2(a.getRectangle().Right, a.getRectangle().Top); aUpperRight = RotatePoint(aUpperRight, aUpperRight + new Vector2(-(a.getRectangle().Width - a.getRotatePoint().X), a.getRotatePoint().Y), a.getRotation()); return aUpperRight; }
public static Vector2 UpperLeftCorner(RectangleShape a) { Vector2 aUpperLeft = new Vector2(a.getRectangle().Left, a.getRectangle().Top); aUpperLeft = RotatePoint(aUpperLeft, aUpperLeft + a.getRotatePoint(), a.getRotation()); return aUpperLeft; }
public static Vector2 LowerRightCorner(RectangleShape a) { Vector2 aLowerRight = new Vector2(a.getRectangle().Right, a.getRectangle().Bottom); aLowerRight = RotatePoint(aLowerRight, aLowerRight + new Vector2(-(a.getRectangle().Width - a.getRotatePoint().X), -(a.getRectangle().Height - a.getRotatePoint().Y)), a.getRotation()); return aLowerRight; }
public static Vector2 LowerLeftCorner(RectangleShape a) { Vector2 aLowerLeft = new Vector2(a.getRectangle().Left, a.getRectangle().Bottom); aLowerLeft = RotatePoint(aLowerLeft, aLowerLeft + new Vector2(a.getRotatePoint().X, -(a.getRectangle().Height - a.getRotatePoint().Y)), a.getRotation()); return aLowerLeft; }