/// <summary> /// Returns whether a line intersects a circle and the points at which it intersects /// </summary> LineIntersectCircleResult TestLineIntersectsCircle(Vector2 lineStart, Vector2 lineEnd, Vector2 circleCenter, float circleRadius) { LineIntersectCircleResult ret = new LineIntersectCircleResult(); float x1 = lineStart.X - circleCenter.X; float x2 = lineEnd.X - circleCenter.X; float y1 = lineStart.Y - circleCenter.Y; float y2 = lineEnd.Y - circleCenter.Y; float a = (float)Math.Pow(y2 - y1, 2) + (float)Math.Pow(x2 - x1, 2); float b = 2 * (x1 * (x2 - x1) + y1 * (y2 - y1)); float c = x1 * x1 + y1 * y1 - circleRadius * circleRadius; //t = (-b +- Sqrt(b^2 - 4ac)) / (2a) float D = b * b - 4 * a * c; if (D < 0) { return(ret); //no intersect } float sqD = (float)Math.Sqrt(D); ret.T1 = (-b + sqD) / (2 * a); ret.T2 = (-b - sqD) / (2 * a); ret.Intersect1 = lineStart + (lineEnd - lineStart) * ret.T1; ret.Intersect2 = lineStart + (lineEnd - lineStart) * ret.T2; ret.Intersects = true; return(ret); }
/// <summary> /// Tests whether any of the vertices of this polygon collide with a specified line segment when this polygon /// is rotated /// </summary> /// <param name="moveBy"></param> /// <param name="lineStart"></param> /// <param name="lineEnd"></param> /// <returns></returns> CollisionInfo TestCollisionWithLineSegment(float rotateBy, Vector2 lineStart, Vector2 lineEnd) { CollisionInfo ret = new CollisionInfo(); ret.Fraction = 1; for (int i = 0; i < _points.Length; i++) { Vector2 p = _points[i]; float length = (p - _centerOfMass).Length(); LineIntersectCircleResult info = TestLineIntersectsCircle(lineStart, lineEnd, CenterOfMass, length); //Game.ArrowCollection.AddArrow("test4" + i, Vector2.Zero, Vector2.Zero, Color.Orange); if (info.Intersects) { //Game.ArrowCollection.AddArrow("test" + i, info.Intersect1, info.Intersect1, Color.Green); //Game.ArrowCollection.AddArrow("test2" + i, info.Intersect2, info.Intersect2, Color.Green); for (int a = 0; a < 2; a++) { float t; Vector2 intersection; if (a == 0) { t = info.T1; intersection = info.Intersect1; } else { t = info.T2; intersection = info.Intersect2; } if (t >= 0 && t < 1) { Vector2 v = ToWorld(p) - ToWorld(Vector2.Zero); //Game.ArrowCollection.AddArrow("sadad", ToWorld(Vector2.Zero), ToWorld(p), Color.RoyalBlue); //Game.ArrowCollection.AddArrow("sadad2", ToWorld(Vector2.Zero), intersection, Color.GreenYellow); float angleToIntersect = Util.AngleBetween(CenterOfMass, intersection); float angleToPoint = Util.AngleBetween(CenterOfMass, ToWorld(p)); float angleBeforeHit = Util.AngleBetween(angleToPoint, angleToIntersect); float fractionIntersect = angleBeforeHit / rotateBy; if (fractionIntersect > 0f && fractionIntersect < 1f && fractionIntersect < ret.Fraction) { ret.IsCollision = true; ret.Fraction = fractionIntersect; ret.IndexOfStriking = i; ret.Impact = intersection; ret.Type = CollisionType.VertexStrikesEdge; } } } } } return(ret); }