Alexander Herold
Alexander Herold

Reputation: 1147

Get Vector2 that has distance x to two vectors

I want to calculate the Position(s) that have the same distance to PositonA and PositionB.

Example:

PositionA: (3,2)
PositionB: (5,4)
Distance: 5

If I'm not mistaken there are two possibilities, but I don't know how to calculate either mathematically.

Update: Based on mrk's answer, I adapted the question, although it was not clear to me before that it is then a circle in three-dimensional space. Thank you very much for that.

I have added an image to clarify the two-dimensional variant.

The goal is to calculate the best escape route based on the positions of the two attackers. In this example the distance is fixed at 5, but later variable.

Example

Upvotes: 3

Views: 986

Answers (4)

Francesco Baruchelli
Francesco Baruchelli

Reputation: 7468

If your problem is limited to 2D this method does what you're looking for:

private Tuple<PointF, PointF> SameDistancePoints(PointF p1, PointF p2, float distance)
    {
        // Calculate the coefficients for the equation 
        // x^2 + y^2 + a1x + b1y + c = 0
        // which represents the circle of all the points that are at distance d from p1:
        // (x-p1.X)^2 + (y-p1.Y)^2 = distance^2
        // which is
        // x^2 -2p1.X*x + (p1.X)^2 + y^2 -2p1.Y*y + (p1.Y)^2 - distance^2 = 0
        float a1 = -2 * p1.X;
        float b1 = -2 * p1.Y;
        float c1 = (float)Math.Pow(p1.X, 2) + (float)Math.Pow(p1.Y, 2) - (float)Math.Pow(distance, 2);
        // do the same for p2
        float a2 = -2 * p2.X;
        float b2 = -2 * p2.Y;
        float c2 = (float)Math.Pow(p2.X, 2) + (float)Math.Pow(p2.Y, 2) - (float)Math.Pow(distance, 2);
        // Now we have the system with the 2 equations:
        // x^2 + y^2 + a1x + b1y + c1 = 0
        // x^2 + y^2 + a2x + b2y + c2 = 0
        // subtracting the second equation from the first we get
        // (a1-a2)x + (b1-b2)y + c1 - c2 = 0
        // from which 
        // y = (c2-c1)/(b1-b2) - (a1-a2)x/(b1-b2)
        // y = d - ex
        float d = (c2 - c1) / (b1 - b2);
        float e = (a1 - a2) / (b1 - b2);
        // replacing the last equation in the first one of the system:
        // x^2 + (d-ex)^2 + a1x + b1(d-ex) + c1 = 0;
        // x^2 + d^2 - 2dex +(ex)^2 + a1x + b1d - b1ex + c1 = 0
        // (1+e^2)x^2 + (a1-2de-b1e)x + d^2 + b1d + c1 = 0
        // which can be written as 
        // a3x^2 + b3x + c3 = 0
        // where
        float a3 = 1 + (float)Math.Pow(e, 2);
        float b3 = a1 - 2 * d * e - b1 * e;
        float c3 = (float)Math.Pow(d, 2) + b1 * d + c1;
        // now it's simlple
        float delta = (float)Math.Pow(b3, 2) - 4 * a3 * c3;
        if (delta < 0)
            return null;
        float x1 = (-b3 + (float)Math.Sqrt(delta)) / (2 * a3);
        float y1 = d - e * x1;
        float x2 = (-b3 - (float)Math.Sqrt(delta)) / (2 * a3);
        float y2 = d - e * x2;
        return new Tuple<PointF, PointF>(new PointF(x1, y1), new PointF(x2, y2));
    }

Upvotes: 1

Alexander Herold
Alexander Herold

Reputation: 1147

With the help of mrk's answer the result given in the form of C# and less mathematics.

public static Vector2 GetEscapeVector(this float distance, Vector2 one, Vector2 two)
{
  var center = (one + two) / 2;

  // rotate by 90° which equals to 1.5708F radians
  var rotated = Vector2.Transform(center, Matrix3x2.CreateRotation(1.5708F));

  var escapeVector = Vector2.Normalize(rotated) * distance;

  return escapeVector;
}

Is later used like this:

currentPosition + 20F.GetEscapeVector(one, two)

or

currentPosition - 20F.GetEscapeVector(one, two)

Upvotes: 2

mrk
mrk

Reputation: 10396

From your conditions you get three equations with three variables (X, Y, Z) that are the coordinates of the points P for which the conditions hold. Based on your points A (A1, A2, A3) and B (B1, B2, B3).

The first equation reflects the fact, that the Point P has the same distance to both A and B

Math.Pow(X - A1, 2) + Math.Pow(Y - A2, 2) = Math.Pow(X - B1, 2) + Math.Pow(Y - B2, 2)

The second equations reflects the fact, that the Point P has a distance d (= 5) from Point A

Math.Pow(X - A1, 2) + Math.Pow(Y - A2, 2) + Math.Pow(Z, 2) = Math.Pow(d, 2)

The second equations reflects the fact, that the Point P has a distance d (= 5) from Point B

Math.Pow(X - B1, 2) + Math.Pow(Y - B2, 2) + Math.Pow(Z, 2) = Math.Pow(d, 2)

This leaves you with a system of quadratic equations. You can now solve it by either solving equation 1 for X and inserting into equation 2 and solving this equation for Y then inserting the terms for X and Y into equation 3, in this manner you can solve for Z. Now you go the same way back, inserting the solution for Z in equation 2 and solving for Y and finally inserting the solution for Y and Z in equation 1 solving for X. (This might sound confusing at first, here is a more detailed description of the approach with an easier hands-on example)

An example how a system of quadratic equations is solved in C# can be found here.

Note: The distance of 5 can be thought of as a sphere around your points A and B. In 2D this would result in 2 solutions where the circles cross each other. In 3D, as you can see in the picture, this will result in an infinite number of possible solutions, since the 2 spheres overlap, resulting in a circle.

This might help you to choose an appropriate approach to your task, since you will need to add at least one more condition to get the specific coordinates of a point.

https://i.sstatic.net/aI5D6.png

Update:

The task now changed to finding the best escape route, given two attackers. One on either side of our player.

Without caring much about the values of the distances, it is obvious, that we want to escape orthogonal to the connection of Attacker 1 (A) and Attacker 2 (B), to maximize the distance to both:

The vector for the escape route is thus given by the scalar product:

(A1-B1) * (X-0.5*(B1-A1)) + (A2-B2) * (Y-0.5*(B2-A2))  = 0

Since we only care about the direction to escape you can set X or Y as you like and solve for the other variable.

In case you do care, introduce a second equation that includes the condition you care about, such as length of your new vector and solve for both X and Y

Upvotes: 4

Axel Kemper
Axel Kemper

Reputation: 11332

Pythagorean theorem:
The squared distance of a point (x,y,z) to PositionA is

(x-3)² + (y-2)² + z²

Similarly, the squared distance to PositionB is

(x-5)² + (y-4)² + z²

You know that both are equal to

Can you take it from there?

Upvotes: 1

Related Questions