/// <summary> /// Returns true if a rectangle centered at the given point, at the /// given angle and dimensions, will fit in the polygon. /// </summary> private bool WillRectangleFit(Edge[] edges, Vector2 center, float angleRad, float width, float height) { float halfWidth = width / 2; float halfHeight = height / 2; var topLeft = new Vector2(center.x - halfWidth, center.y + halfHeight); var topRight = new Vector2(center.x + halfWidth, center.y + halfHeight); var bottomLeft = new Vector2(center.x - halfWidth, center.y - halfHeight); var bottomRight = new Vector2(center.x + halfWidth, center.y - halfHeight); topLeft = RotatePoint(center, angleRad, topLeft); topRight = RotatePoint(center, angleRad, topRight); bottomLeft = RotatePoint(center, angleRad, bottomLeft); bottomRight = RotatePoint(center, angleRad, bottomRight); var top = new Edge(topLeft, topRight); var right = new Edge(topRight, bottomRight); var bottom = new Edge(bottomLeft, bottomRight); var left = new Edge(topLeft, bottomLeft); // If any edges of the polygon intersect with any of our edges, it won't fit foreach (var edge in edges) { if (EdgeHelpers.IsValidPoint(EdgeHelpers.GetIntersection(edge, top)) || EdgeHelpers.IsValidPoint(EdgeHelpers.GetIntersection(edge, right)) || EdgeHelpers.IsValidPoint(EdgeHelpers.GetIntersection(edge, bottom)) || EdgeHelpers.IsValidPoint(EdgeHelpers.GetIntersection(edge, left))) { return(false); } } return(true); }
/// <summary> /// Given a point inside of the boundary, finds the points on the /// boundary directly above, below, left and right of the point, /// with respect to the given angle. /// </summary> private bool FindSurroundingCollisionPoints( Edge[] edges, Vector2 point, float angleRad, out Vector2 topCollisionPoint, out Vector2 bottomCollisionPoint, out Vector2 leftCollisionPoint, out Vector2 rightCollisionPoint) { topCollisionPoint = EdgeHelpers.InvalidPoint; bottomCollisionPoint = EdgeHelpers.InvalidPoint; leftCollisionPoint = EdgeHelpers.InvalidPoint; rightCollisionPoint = EdgeHelpers.InvalidPoint; bool isInside = EdgeHelpers.IsInside(edges, point); if (!isInside) { return(false); } // Find the top and bottom collision points by creating a large line segment that goes through the point to MAX and MIN values on Y var topEndpoint = new Vector2(point.x, largeValue); var bottomEndpoint = new Vector2(point.x, smallValue); topEndpoint = RotatePoint(point, angleRad, topEndpoint); bottomEndpoint = RotatePoint(point, angleRad, bottomEndpoint); var verticalLine = new Edge(topEndpoint, bottomEndpoint); // Find the left and right collision points by creating a large line segment that goes through the point to MAX and Min values on X var rightEndpoint = new Vector2(largeValue, point.y); var leftEndpoint = new Vector2(smallValue, point.y); rightEndpoint = RotatePoint(point, angleRad, rightEndpoint); leftEndpoint = RotatePoint(point, angleRad, leftEndpoint); var horizontalLine = new Edge(rightEndpoint, leftEndpoint); // Loop the edges and find the nearest intersection point foreach (var edge in edges) { Vector2 verticalIntersection = EdgeHelpers.GetIntersection(edge, verticalLine); if (EdgeHelpers.IsValidPoint(verticalIntersection)) { // Is this intersection above or below the point? bool isAbove = RotatePoint(point, -angleRad, verticalIntersection).y > point.y; if (isAbove) { // If this collision point is closer than the previous one if (!EdgeHelpers.IsValidPoint(topCollisionPoint) || Vector2.SqrMagnitude(point - verticalIntersection) < Vector2.SqrMagnitude(point - topCollisionPoint)) { topCollisionPoint = verticalIntersection; } } else { if (!EdgeHelpers.IsValidPoint(bottomCollisionPoint) || Vector2.SqrMagnitude(point - verticalIntersection) < Vector2.SqrMagnitude(point - bottomCollisionPoint)) { bottomCollisionPoint = verticalIntersection; } } } // If vertical intersection found Vector2 horizontalIntersection = EdgeHelpers.GetIntersection(edge, horizontalLine); if (EdgeHelpers.IsValidPoint(horizontalIntersection)) { // Is this intersection left or right of the point? bool isLeft = RotatePoint(point, -angleRad, horizontalIntersection).x < point.x; if (isLeft) { // Is it closer than the previous intersection? if (!EdgeHelpers.IsValidPoint(leftCollisionPoint) || Vector2.SqrMagnitude(point - horizontalIntersection) < Vector2.SqrMagnitude(point - leftCollisionPoint)) { leftCollisionPoint = horizontalIntersection; } } else { // Is it closer than the previous intersection? if (!EdgeHelpers.IsValidPoint(rightCollisionPoint) || Vector2.SqrMagnitude(point - horizontalIntersection) < Vector2.SqrMagnitude(point - rightCollisionPoint)) { rightCollisionPoint = horizontalIntersection; } } } } // Assert that any point inside should have intersection points on all sides with the polygon if (!EdgeHelpers.IsValidPoint(topCollisionPoint) || !EdgeHelpers.IsValidPoint(bottomCollisionPoint) || !EdgeHelpers.IsValidPoint(leftCollisionPoint) || !EdgeHelpers.IsValidPoint(rightCollisionPoint)) { return(false); } return(true); }