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) {
      ...