简体   繁体   中英

How to efficiently calculate the angle between two points?

I am trying to optimize the simulation function in my experiment so I can have more artificial brain-controlled agents running at a time. I profiled my code and found out that the big bottleneck in my code right now is computing the relative angle from every agent to every agent, which is O(n 2 ), minus some small optimizations I have done. Here is the current code snippet I have for computing the angle:

[C++]
double calcAngle(double fromX, double fromY, double fromAngle, double toX, double toY)
{
    double d = 0.0;
    double Ux = 0.0, Uy = 0.0, Vx = 0.0, Vy = 0.0;

    d = sqrt( calcDistanceSquared(fromX, fromY, toX, toY) );

    Ux = (toX - fromX) / d;

    Uy = (toY - fromY) / d;

    Vx = cos(fromAngle * (cPI / 180.0));
    Vy = sin(fromAngle * (cPI / 180.0));

    return atan2(((Ux * Vy) - (Uy * Vx)), ((Ux * Vx) + (Uy * Vy))) * 180.0 / cPI;
}

I have two 2D points (x 1 , y 1 ) and (x 2 , y 2 ) and the facing of the "from" point (x a ). I want to compute the angle that agent x needs to turn (relative to its current facing) to face agent y.

According to the profiler, the most expensive part is the atan2 . I have Googled for hours and the above solution is the best solution I could find. Does anyone know of a more efficient way to compute the angle between two points? I am willing to sacrifice a little accuracy (+/- 1-2 degrees) for speed, if that affects anything.

As has been mentioned in the comments, there are probably high-level approaches to reduce your computational load.

But to the question in hand, you can just use the dot-product relationship :

theta = acos ( a . b / ||a|| ||b|| )

where a and b are your vectors, . denotes "dot product" and || || || || denotes "vector magnitude".

Essentially, this will replace your { sqrt , cos , sin , atan2 } with { sqrt , acos }.

I would also suggest sticking to radians for all internal calculations, only converting to and from degrees for human-readable I/O.

Your comment tells a lot: "I am simulating a 180 degree frontal retina for every agent, so I need the angle". No, you don't. You just need to know whether the angle between the position vector and vision vector is more or less than 90 degrees.

That's very easy: the dot product A·B is >0 if the angle between A and B is less than 90 degrees; 0 if the angle is precisely 90 degrees, and <0 if the angle is more than 90 degrees. Calculating this takes 3 multiplications and 2 additions.

i think it's more a mathematical problem:

try

abs(arctan((y1-yfrom)/(x1-xfrom)) - arctan(1/((y2-yfrom2)/(x2-xfrom2))))

Use the dot product of these two vectors and at worst you need to do an inverse cosine instead:

A = Facing direction. B = Direction of Agent Y from Agent X

Calculating the dot is simple multiplication and addition. From that you have the cosine of the angle.

For starters, you should realize that there are a couple of simplifications that can reduce the calculations a bit:

  1. You need not calculate the angle from an agent to itself,
  2. If you have the angle from agent i to agent j, you already know something about the angle from agent j back to agent i.

I have to ask: what does "agent i turn to face agent j" mean? If the two surfaces are looking right at each other, do you have to do a calculation? What tolerance do you have on "looking right at each other"?

It'd be easier to recommend what to do if you'd stop focusing on the mathematics and describe the problem more fully.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM