computeAngle
by Digory Doo
HTML
<div id="result"></div>
JavaScript
g_log = "";
/*
* Computes the angle between the vector (x, y) and the vector (1, 0).
* @return: An angle in Radians between 0..2*Math.PI.
*/
this.computeAngle = function (x, y) {
var a = Math.atan2(y, x);
if (y < 0) a += 2 * Math.PI;
if (a >= 2 * Math.PI) a -= 2 * Math.PI;
return a;
}
/*
* Mathematically correct modulus function.
* @return: <num> (mod <mod>)
*/
this.fmod = function (num, mod) {
return ((num < 0) ? Math.abs(mod) : 0) + (num % mod);
}
/*
* @param how (in): One of: 'towards', 'away', 'orbit'.
* @param steerSpeed (in): Maximum steering in degrees.
* @param targetX, targetY (in): Position to steer towards or away from.
*/
this.steer = function (how, steerSpeed, targetX, targetY) {
// Compute angle between (posX, posY) and (targetX, targetY).
var dx = targetX - this.posX;
var dy = targetY - this.posY;
if (dx == 0 && dy == 0) {
// Direction of target undefined, keep current direction!
return this.angleRad;
}
var a = 360.0 * this.computeAngle(dx, dy) / (2 * Math.PI); // in degrees
g_log += "a is " + a + "<br/>";
switch (how) {
case 'towards': /* a is correct already */ break;
case 'away': a = this.fmod (a + 180, 360); break;
case 'orbit-ccw': a = this.fmod (a + 90, 360); break;
case 'orbit-cw': a = this.fmod (a + 270, 360); break;
default: /* bad parameter 'how' */ return;
}
g_log += "how: " + how + " -> a now is " + a + "<br/>";
// Compute distance between current angle and target angle.
var myAngleDeg = 360.0 * this.angleRad / (2 * Math.PI);
var u = a - myAngleDeg;
var du = Math.abs(u);
var su = Math.sign(u);
var v = ((360 - du) % 360) * -su;
var dv = Math.abs(v);
var sv = Math.sign(v);
var d;
var s;
if (du < dv) {
d = du;
s = su;
} else {
d = dv;
s = sv;
}
// Approach target angle.
if (steerSpeed > d) {
...