/// <summary> /// Given a force and a distance to cover given by two vectors, this /// method calculates how long it will take the ball to travel between /// the two points /// /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <param name="force"></param> /// <returns></returns> public double CalucateTimeToCoverDistance(Vector2D A, Vector2D B, double force) { //this will be the velocity of the ball in the next time step *if* //the player was to make the pass. double speed = force / Mass; //calculate the velocity at B using the equation // // v^2 = u^2 + 2as // //first calculate s (the distance between the two positions) double DistanceToCover = Vector2D.Vec2DDistance(A, B); double term = speed * speed + 2.0 * DistanceToCover * ParameterManager.Instance.Friction; //if (u^2 + 2as) is negative it means the ball cannot reach point B. if (term <= 0.0) { return(-1.0); } double v = Math.Sqrt(term); //it IS possible for the ball to reach B and we know its speed when it //gets there, so now it's easy to calculate the time using the equation // // t = v-u // --- // a // return((v - speed) / ParameterManager.Instance.Friction); }
/// <summary> /// Given a line segment AB and a point P, this function calculates the /// perpendicular distance between them /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <param name="P"></param> /// <returns></returns> public static double DistToLineSegment(Vector2D A, Vector2D B, Vector2D P) { //if the angle is obtuse between PA and AB is obtuse then the closest //vertex must be A double dotA = (P.X - A.X) * (B.X - A.X) + (P.Y - A.Y) * (B.Y - A.Y); if (dotA <= 0) { return(Vector2D.Vec2DDistance(A, P)); } //if the angle is obtuse between PB and AB is obtuse then the closest //vertex must be B double dotB = (P.X - B.X) * (A.X - B.X) + (P.Y - B.Y) * (A.Y - B.Y); if (dotB <= 0) { return(Vector2D.Vec2DDistance(B, P)); } //calculate the point along AB that is the closest to P Vector2D Point = A + ((B - A) * dotA) / (dotA + dotB); //calculate the distance P-Point return(Vector2D.Vec2DDistance(P, Point)); }
/// <summary> /// Given 2 lines in 2D space AB, CD this returns true if an /// intersection occurs and sets dist to the distance the intersection /// occurs along AB. Also sets the 2d vector point to the point of /// intersection /// /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <param name="C"></param> /// <param name="D"></param> /// <param name="dist"></param> /// <param name="point"></param> /// <returns></returns> public static bool LineIntersection2D(Vector2D A, Vector2D B, Vector2D C, Vector2D D, ref double dist, ref Vector2D point) { double rTop = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y); double rBot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); double sTop = (A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y); double sBot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); if ((rBot == 0) || (sBot == 0)) { //lines are parallel return(false); } double r = rTop / rBot; double s = sTop / sBot; if ((r > 0) && (r < 1) && (s > 0) && (s < 1)) { dist = Vector2D.Vec2DDistance(A, B) * r; point = A + r * (B - A); return(true); } else { dist = 0; return(false); } }
/// <summary> /// Given 2 lines in 2D space AB, CD this returns true if an /// intersection occurs and sets dist to the distance the intersection /// occurs along AB /// /// </summary> /// <param name="A"></param> /// <param name="B"></param> /// <param name="C"></param> /// <param name="D"></param> /// <param name="dist"></param> /// <returns></returns> public static bool LineIntersection2D(Vector2D A, Vector2D B, Vector2D C, Vector2D D, ref double dist) { double rTop = (A.Y - C.Y) * (D.X - C.X) - (A.X - C.X) * (D.Y - C.Y); double sTop = (A.Y - C.Y) * (B.X - A.X) - (A.X - C.X) * (B.Y - A.Y); double Bot = (B.X - A.X) * (D.Y - C.Y) - (B.Y - A.Y) * (D.X - C.X); if (Bot == 0)//parallel { if (Math.Abs(rTop) > Geometry.MinPrecision && Math.Abs(sTop) > Geometry.MinPrecision) { return(true); } return(false); } double r = rTop / Bot; double s = sTop / Bot; if ((r > 0) && (r < 1) && (s > 0) && (s < 1)) { dist = Vector2D.Vec2DDistance(A, B) * r; return(true); } else { dist = 0; return(false); } }
public Vector2D DetermineBestSupportingPosition() { //only update the spots every few frames if (!_regulator.IsReady /* && _bestSupportingSpot != null */) { return(_bestSupportingSpot.m_vPos); } //reset the best supporting spot _bestSupportingSpot = null; double BestScoreSoFar = 0.0; for (int spotIndex = 0; spotIndex < _supportSpots.Count; spotIndex++) { //first remove any previous score. (the score is set to one so that //the viewer can see the positions of all the spots if he has the //aids turned on) _supportSpots[spotIndex].m_dScore = 1.0; //Test 1. is it possible to make a safe pass from the ball's position //to this position? if (_team.IsPassSafeFromAllOpponents(_team.ControllingPlayer.Position, _supportSpots[spotIndex].m_vPos, null, ParameterManager.Instance.MaxPassingForce)) { _supportSpots[spotIndex].m_dScore += ParameterManager.Instance.SpotPassSafeScore; } Vector2D shotTarget = new Vector2D(); //Test 2. Determine if a goal can be scored from this position. if (_team.CanShoot(_supportSpots[spotIndex].m_vPos, ParameterManager.Instance.MaxShootingForce, ref shotTarget)) { _supportSpots[spotIndex].m_dScore += ParameterManager.Instance.SpotCanScoreFromPositionScore; } //Test 3. calculate how far this spot is away from the controlling //player. The further away, the higher the score. Any distances further //away than OptimalDistance pixels do not receive a score. if (_team.SupportingPlayer != null) { const double OptimalDistance = 200.0; double dist = Vector2D.Vec2DDistance(_team.ControllingPlayer.Position, _supportSpots[spotIndex].m_vPos); double temp = Math.Abs(OptimalDistance - dist); if (temp < OptimalDistance) { //normalize the distance and add it to the score _supportSpots[spotIndex].m_dScore += ParameterManager.Instance.SpotDistFromControllingPlayerScore * (OptimalDistance - temp) / OptimalDistance; } } //check to see if this spot has the highest score so far if (_supportSpots[spotIndex].m_dScore > BestScoreSoFar) { BestScoreSoFar = _supportSpots[spotIndex].m_dScore; _bestSupportingSpot = _supportSpots[spotIndex]; } } return(_bestSupportingSpot.m_vPos); }