/// <summary> /// Determines if a ray interescts a circle /// </summary> /// <param name="rayOrig">The origin of the ray</param> /// <param name="rayDir">The direction of the ray</param> /// <param name="center">The center of the circle</param> /// <param name="r">The radius of the circle</param> /// <returns></returns> public static bool Intersects(Vector2D rayOrig, Vector2D rayDir, Vector2D center, double r) { // ray-circle intersection test // P: hit point // ray: P = O + tV // circle: (P-C)dot(P-C)-r^2 = 0 // substitute to solve for t gives a quadratic equation: // a = VdotV // b = 2(O-C)dotV // c = (O-C)dot(O-C)-r^2 // if the discriminant is negative, miss (no solution for P) // otherwise, if both roots are positive, hit double a = rayDir.Dot(rayDir); double b = ((rayOrig - center) * 2.0).Dot(rayDir); double c = (rayOrig - center).Dot(rayOrig - center) - r * r; // discriminant double disc = b * b - 4.0 * a * c; if (disc < 0.0) { return(false); } // find the signs of the roots // technically we should also divide by 2a // but all we care about is the sign, not the magnitude double root1 = -b + Math.Sqrt(disc); double root2 = -b - Math.Sqrt(disc); return(root1 > 0.0 && root2 > 0.0); }
/// <summary> /// Determines if a beam intersects a circle where: /// the beam is a ray in the context of this method /// the tank is a circle in the context of this method /// </summary> /// <returns></returns> private bool IsBeamTankCollision(Beam beam, Tank tank) { // ray-circle intersection test // P: hit point // ray: P = O + tV // circle: (P-C)dot(P-C)-r^2 = 0 // substitute to solve for t gives a quadratic equation: // a = VdotV // b = 2(O-C)dotV // c = (O-C)dot(O-C)-r^2 // if the discriminant is negative, miss (no solution for P) // otherwise, if both roots are positive, hit Vector2D rayOrig = beam.Origin; Vector2D rayDir = beam.Direction; Vector2D center = tank.Location; double r = gameSettings.TankSize / 2.0; double a = rayDir.Dot(rayDir); double b = ((rayOrig - center) * 2.0).Dot(rayDir); double c = (rayOrig - center).Dot(rayOrig - center) - r * r; // discriminant double disc = b * b - 4.0 * a * c; if (disc < 0.0) { return(false); } // find the signs of the roots // technically we should also divide by 2a // but all we care about is the sign, not the magnitude double root1 = -b + Math.Sqrt(disc); double root2 = -b - Math.Sqrt(disc); return(root1 > 0.0 && root2 > 0.0); }