Vec2DDistanceSq() публичный статический Метод

public static Vec2DDistanceSq ( Vector2D v1, Vector2D v2 ) : double
v1 Vector2D
v2 Vector2D
Результат double
Пример #1
0
        /// <summary>
        /// As above, but avoiding sqrt
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="P"></param>
        /// <returns></returns>
        public static double DistToLineSegmentSq(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.Vec2DDistanceSq(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.Vec2DDistanceSq(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.Vec2DDistanceSq(P, Point));
        }
Пример #2
0
        /// <summary>
        /// calculate the closest player to the SupportSpot
        ///
        /// </summary>
        /// <returns></returns>
        public PlayerBase DetermineBestSupportingAttacker()
        {
            double ClosestSoFar = double.MaxValue;

            PlayerBase BestPlayer = null;


            for (int playerIndex = 0; playerIndex < _players.Count; playerIndex++)
            {
                //only attackers utilize the BestSupportingSpot
                if ((_players[playerIndex].PlayerRole == PlayerBase.PlayerRoles.Attacker) && (_players[playerIndex] != _controllingPlayer))
                {
                    //calculate the dist. Use the squared value to avoid sqrt
                    double dist = Vector2D.Vec2DDistanceSq(_players[playerIndex].Position, _supportSpotCalculator.GetBestSupportingSpot());

                    //if the distance is the closest so far and the player is not a
                    //goalkeeper and the player is not the one currently controlling
                    //the ball, keep a record of this player
                    if ((dist < ClosestSoFar))
                    {
                        ClosestSoFar = dist;

                        BestPlayer = _players[playerIndex];
                    }
                }
            }

            return(BestPlayer);
        }
Пример #3
0
 /// <summary>
 ///  returns true if an opposing player is within the radius of the position
 ///  given as a parameter
 ///
 /// </summary>
 /// <param name="pos"></param>
 /// <param name="rad"></param>
 /// <returns></returns>
 public bool IsOpponentWithinRadius(Vector2D pos, double rad)
 {
     foreach (PlayerBase opponent in OpposingTeam.Players)
     {
         if (Vector2D.Vec2DDistanceSq(pos, opponent.Position) < rad * rad)
         {
             return(true);
         }
     }
     return(false);
 }
Пример #4
0
        /// <summary>
        ///  The best pass is considered to be the pass that cannot be intercepted
        ///  by an opponent and that is as far forward of the receiver as possible
        ///
        /// </summary>
        /// <param name="passer"></param>
        /// <param name="receiver"></param>
        /// <param name="PassTarget"></param>
        /// <param name="power"></param>
        /// <param name="MinPassingDistance"></param>
        /// <returns></returns>
        public bool FindPass(PlayerBase passer,
                             out PlayerBase receiver,
                             out Vector2D PassTarget,
                             double power,
                             double MinPassingDistance)
        {
            receiver   = null;
            PassTarget = null;

            double   ClosestToGoalSoFar = double.MaxValue;
            Vector2D Target             = new Vector2D();

            //iterate through all this player's team members and calculate which
            //one is in a position to be passed the ball
            foreach (PlayerBase currentPlayer in _players)
            {
                //make sure the potential receiver being examined is not this player
                //and that it is further away than the minimum pass distance
                if ((currentPlayer != passer) &&
                    (Vector2D.Vec2DDistanceSq(passer.Position, currentPlayer.Position) >
                     MinPassingDistance * MinPassingDistance))
                {
                    if (GetBestPassToReceiver(passer, currentPlayer, ref Target, power))
                    {
                        //if the pass target is the closest to the opponent's goal line found
                        // so far, keep a record of it
                        double Dist2Goal = Math.Abs(Target.X - OpponentsGoal.GoalLineCenter.X);

                        if (Dist2Goal < ClosestToGoalSoFar)
                        {
                            ClosestToGoalSoFar = Dist2Goal;

                            //keep a record of this player
                            receiver = currentPlayer;

                            //and the target
                            PassTarget = Target;
                        }
                    }
                }
            }//next team member

            if (receiver != null)
            {
                return(true);
            }

            else
            {
                return(false);
            }
        }
Пример #5
0
        //------------------------- IsThreatened ---------------------------------
        //
        //  returns true if there is an opponent within this player's
        //  comfort zone
        //------------------------------------------------------------------------
        public bool IsThreatened()
        {
            for (int opponentIndex = 0; opponentIndex < Team.OpposingTeam.Players.Count; opponentIndex++)
            {
                //calculate distance to the player. if dist is less than our
                //comfort zone, and the opponent is infront of the player, return true
                if (IsPositionInFrontOfPlayer(Team.OpposingTeam.Players[opponentIndex].Position) &&
                    (Vector2D.Vec2DDistanceSq(Position, Team.OpposingTeam.Players[opponentIndex].Position) < ParameterManager.Instance.PlayerComfortZoneSq))
                {
                    return(true);
                }
            }// next opp

            return(false);
        }
Пример #6
0
        /// <summary>
        ///  given a line segment AB and a circle position and radius, this function
        ///  determines if there is an intersection and stores the position of the
        ///  closest intersection in the reference IntersectionPoint
        ///
        ///  returns false if no intersection point is found
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <param name="pos"></param>
        /// <param name="radius"></param>
        /// <param name="IntersectionPoint"></param>
        /// <returns></returns>
        public static bool GetLineSegmentCircleClosestIntersectionPoint(Vector2D A,
                                                                        Vector2D B,
                                                                        Vector2D pos,
                                                                        double radius,
                                                                        ref Vector2D IntersectionPoint)
        {
            Vector2D toBNorm = Vector2D.Vec2DNormalize(B - A);

            //move the circle into the local space defined by the vector B-A with origin
            //at A
            Vector2D LocalPos = Transformations.PointToLocalSpace(pos, toBNorm, toBNorm.Perp, A);

            bool ipFound = false;

            //if the local position + the radius is negative then the circle lays behind
            //point A so there is no intersection possible. If the local x pos minus the
            //radius is greater than length A-B then the circle cannot intersect the
            //line segment
            if ((LocalPos.X + radius >= 0) &&
                ((LocalPos.X - radius) * (LocalPos.X - radius) <= Vector2D.Vec2DDistanceSq(B, A)))
            {
                //if the distance from the x axis to the object's position is less
                //than its radius then there is a potential intersection.
                if (Math.Sqrt(LocalPos.Y) < radius)
                {
                    //now to do a line/circle intersection test. The center of the
                    //circle is represented by A, B. The intersection points are
                    //given by the formulae x = A +/-sqrt(r^2-B^2), y=0. We only
                    //need to look at the smallest positive value of x.
                    double a = LocalPos.X;
                    double b = LocalPos.Y;

                    double ip = a - Math.Sqrt(radius * radius - b * b);

                    if (ip <= 0)
                    {
                        ip = a + Math.Sqrt(radius * radius - b * b);
                    }

                    ipFound = true;

                    IntersectionPoint = A + toBNorm * ip;
                }
            }

            return(ipFound);
        }
Пример #7
0
        /// <summary>
        /// sets _playerClosestToBall to the player closest to the ball
        /// </summary>
        public void CalculateClosestPlayerToBall()
        {
            double ClosestSoFar = double.MaxValue;

            for (int playerIndex = 0; playerIndex < _players.Count; playerIndex++)
            {
                //calculate the dist. Use the squared value to avoid sqrt
                double dist = Vector2D.Vec2DDistanceSq(_players[playerIndex].Position, Pitch.Ball.Position);

                //keep a record of this value for each player
                _players[playerIndex].DistanceToBallSquared = dist;

                if (dist < ClosestSoFar)
                {
                    ClosestSoFar = dist;

                    _playerClosestToBall = _players[playerIndex];
                }
            }

            _distSqToBallOfClosestPlayer = ClosestSoFar;
        }
Пример #8
0
        /// <summary>
        /// Tests to see if the ball has collided with a ball and reflects
        /// the ball's velocity accordingly
        /// </summary>
        /// <param name="walls"></param>
        public void TestCollisionWithWalls(List <Wall2D> walls)
        {
            //test ball against each wall, find out which is closest
            int closestIndex = -1;

            Vector2D normalVector = Vector2D.Vec2DNormalize(Velocity);

            Vector2D intersectionPoint = new Vector2D(), collisionPoint = new Vector2D();

            double distToIntersection = double.MaxValue;

            ////iterate through each wall and calculate if the ball intersects.
            ////If it does then store the index into the closest intersecting wall
            for (int wallIndex = 0; wallIndex < walls.Count; wallIndex++)
            {
                //assuming a collision if the ball continued on its current heading
                //calculate the point on the ball that would hit the wall. This is
                //simply the wall's normal(inversed) multiplied by the ball's radius
                //and added to the balls center (its position)
                Vector2D thisCollisionPoint = Position - (walls[wallIndex].VectorNormal * BoundingRadius);

                //  //calculate exactly where the collision point will hit the plane
                if (Geometry.WhereIsPoint(thisCollisionPoint,
                                          walls[wallIndex].VectorFrom,
                                          walls[wallIndex].VectorNormal) == Geometry.PlaneLocation.Behind)
                {
                    double distToWall = Geometry.DistanceToRayPlaneIntersection(thisCollisionPoint, walls[wallIndex].VectorNormal, walls[wallIndex].VectorFrom, walls[wallIndex].VectorNormal);
                    intersectionPoint = thisCollisionPoint + (distToWall * walls[wallIndex].VectorNormal);
                }
                else
                {
                    double distToWall = Geometry.DistanceToRayPlaneIntersection(thisCollisionPoint,
                                                                                normalVector,
                                                                                walls[wallIndex].VectorFrom,
                                                                                walls[wallIndex].VectorNormal);

                    intersectionPoint = thisCollisionPoint + (distToWall * normalVector);
                }

                //check to make sure the intersection point is actually on the line
                //segment
                bool onLineSegment = false;

                if (Geometry.LineIntersection2D(walls[wallIndex].VectorFrom,
                                                walls[wallIndex].VectorTo,
                                                thisCollisionPoint - walls[wallIndex].VectorNormal * 20.0,
                                                thisCollisionPoint + walls[wallIndex].VectorNormal * 20.0))
                {
                    onLineSegment = true;
                }

                //Note, there is no test for collision with the end of a line segment
                //now check to see if the collision point is within range of the
                //velocity vector. [work in distance squared to avoid sqrt] and if it
                //is the closest hit found so far.
                //If it is that means the ball will collide with the wall sometime
                //between this time step and the next one.
                double distSq = Vector2D.Vec2DDistanceSq(thisCollisionPoint, intersectionPoint);

                if ((distSq <= Velocity.LengthSquared) && (distSq < distToIntersection) && onLineSegment)
                {
                    distToIntersection = distSq;
                    closestIndex       = wallIndex;
                    collisionPoint     = intersectionPoint;
                }
            } // next wall


            //to prevent having to calculate the exact time of collision we
            //can just check if the velocity is opposite to the wall normal
            //before reflecting it. This prevents the case where there is overshoot
            //and the ball gets reflected back over the line before it has completely
            //reentered the playing area.
            if ((closestIndex >= 0) && normalVector.GetDotProduct(walls[closestIndex].VectorNormal) < 0)
            {
                Velocity.Reflect(walls[closestIndex].VectorNormal);
            }
        }
Пример #9
0
        /// <summary>
        ///  test if a pass from 'from' to 'to' can be intercepted by an opposing player
        ///
        /// </summary>
        /// <param name="from"></param>
        /// <param name="target"></param>
        /// <param name="receiver"></param>
        /// <param name="opp"></param>
        /// <param name="PassingForce"></param>
        /// <returns></returns>
        public bool IsPassSafeFromOpponent(Vector2D from,
                                           Vector2D target,
                                           PlayerBase receiver,
                                           PlayerBase opp,
                                           double PassingForce)
        {
            //move the opponent into local space.
            Vector2D ToTarget           = target - from;
            Vector2D ToTargetNormalized = Vector2D.Vec2DNormalize(ToTarget);

            Vector2D LocalPosOpp = Transformations.PointToLocalSpace(opp.Position,
                                                                     ToTargetNormalized,
                                                                     ToTargetNormalized.Perp,
                                                                     from);

            //if opponent is behind the kicker then pass is considered okay(this is
            //based on the assumption that the ball is going to be kicked with a
            //velocity greater than the opponent's max velocity)
            if (LocalPosOpp.X < 0)
            {
                return(true);
            }

            //if the opponent is further away than the target we need to consider if
            //the opponent can reach the position before the receiver.
            if (Vector2D.Vec2DDistanceSq(from, target) < Vector2D.Vec2DDistanceSq(opp.Position, from))
            {
                if (receiver != null)
                {
                    if (Vector2D.Vec2DDistanceSq(target, opp.Position) >
                        Vector2D.Vec2DDistanceSq(target, receiver.Position))
                    {
                        return(true);
                    }

                    else
                    {
                        return(false);
                    }
                }

                else
                {
                    return(true);
                }
            }

            //calculate how long it takes the ball to cover the distance to the
            //position orthogonal to the opponents position
            double TimeForBall =
                Pitch.Ball.CalucateTimeToCoverDistance(new Vector2D(0, 0),
                                                       new Vector2D(LocalPosOpp.X, 0),
                                                       PassingForce);

            //now calculate how far the opponent can run in this time
            double reach = opp.MaxSpeed * TimeForBall +
                           Pitch.Ball.BoundingRadius +
                           opp.BoundingRadius;

            //if the distance to the opponent's y position is less than his running
            //range plus the radius of the ball and the opponents radius then the
            //ball can be intercepted
            if (Math.Abs(LocalPosOpp.Y) < reach)
            {
                return(false);
            }

            return(true);
        }
Пример #10
0
 public bool TooFarFromGoalMouth()
 {
     return(Vector2D.Vec2DDistanceSq(Position, GetRearInterposeTarget()) >
            ParameterManager.Instance.GoalKeeperInterceptRangeSq);
 }
Пример #11
0
 public bool BallWithinRangeForIntercept()
 {
     return(Vector2D.Vec2DDistanceSq(Team.HomeGoal.GoalLineCenter, Ball.Position) <=
            ParameterManager.Instance.GoalKeeperInterceptRangeSq);
 }