FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

PVector.angleBetween() returns NaN · Issue #231 · processing-js/processing-js · GitHub

This repository was archived by the owner on Dec 5, 2018. It is now read-only.

Repository navigation

This repository was archived by the owner on Dec 5, 2018. It is now read-only.

PVector.angleBetween() returns NaN  #231

Open

Description

See the simple test case at [https://www.khanacademy.org/computer-programming/wat9/3117073701]

Activity

  1. GoToLoop commented on Mar 4, 2016

    Contributor

    Current _PVector_::angleBetween()'s implementation:
    https://github.com/processing-js/processing-js/blob/master/src/Objects/PVector.js#L53

    PVector.angleBetween = function(v1, v2) {
      return Math.acos(v1.dot(v2) / Math.sqrt(v1.magSq() * v2.magSq()));
    };

    Proposed fix for it:
    https://gist.github.com/GoToLoop/acbf106aa784820aff23#file-pvector-js-L64

    PVector.angleBetween = function(v1, v2) {
      if (!v1.x && !v1.y && !v1.z || !v2.x && !v2.y && !v2.z)  return 0;
      const amt = PVector.dot(v1, v2) / Math.sqrt(v1.magSq() * v2.magSq());
      return amt <= -1? Math.PI : amt >= 1? 0 : Math.acos(amt);
    };
  2. GoToLoop commented on Mar 4, 2016

    Contributor

    Indeed I haven't tested it yet. It is based off Processing's original _PVector_::angleBetween()'s: 😕
    https://github.com/processing/processing/blob/master/core/src/processing/core/PVector.java#L987

    static public float angleBetween(PVector v1, PVector v2) {
    
      // We get NaN if we pass in a zero vector which can cause problems
      // Zero seems like a reasonable angle between a (0,0,0) vector and something else
      if (v1.x == 0 && v1.y == 0 && v1.z == 0 ) return 0.0f;
      if (v2.x == 0 && v2.y == 0 && v2.z == 0 ) return 0.0f;
    
      double dot = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
      double v1mag = Math.sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z);
      double v2mag = Math.sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z);
      // This should be a number between -1 and 1, since it's "normalized"
      double amt = dot / (v1mag * v2mag);
      // But if it's not due to rounding error, then we need to fix it
      // http://code.google.com/p/processing/issues/detail?id=340
      // Otherwise if outside the range, acos() will return NaN
      // http://www.cppreference.com/wiki/c/math/acos
      if (amt <= -1) {
        return PConstants.PI;
      } else if (amt >= 1) {
        // http://code.google.com/p/processing/issues/detail?id=435
        return 0;
      }
      return (float) Math.acos(amt);
    }
  3. k4b7 commented on Mar 4, 2016

    Contributor

    Please disregard my previous message. I shouldn't post when I'm feeling under the weather.

  4. GoToLoop commented on Mar 4, 2016

    Contributor

    No problem @kevinbarabash. But just to leave no trace of doubt that my _PVector_::angleBetween() implementation indeed fixes @lgto4's edgy case, paste this half-baked JavaScript Mode sample on http://ProcessingJS.org/tools/processing-helper.html:

    final PVector a = new PVector(1, 0, 0), b = new PVector(0, 1, 0);
    float ang;
    
    void setup() {
      ang = PVector.angleBetween(a, b);
      println(ang); // 1.5707963267948966
    
      ang = angleBetween(a, b);
      println(ang); // 1.5707963267948966
    
      a.set(-1, 1, 0);
      b.set(-1.5, 1.5, 0);
      final PVector c = new PVector(1.5, -1.5);
    
      ang = PVector.angleBetween(b, c);
      println(ang); // NaN
    
      ang = angleBetween(b, c);
      println(ang); // 3.141592653589793
    
      exit();
    }
    
    static final float angleBetween(PVector v1, PVector v2) {
      if (!v1.x && !v1.y && !v1.z || !v2.x && !v2.y && !v2.z)  return 0;
      const amt = PVector.dot(v1, v2) / Math.sqrt(v1.magSq() * v2.magSq());
      return amt <= -1? Math.PI : amt >= 1? 0 : Math.acos(amt);
    }
  5. GoToLoop commented on Mar 4, 2016

    Contributor

    Made a Khan version too at: https://www.KhanAcademy.org/computer-programming/spin-off-of-wat9-anglebetween/3127717618

    It's funny that 1st ang = PVector.angleBetween(a, b); results 90 instead of 1.5707963267948966 O_o

    var angleBetween = function (v1, v2) {
      if (!v1.x && !v1.y && !v1.z || !v2.x && !v2.y && !v2.z)  { return 0; }
      var amt = PVector.dot(v1, v2) / Math.sqrt(v1.magSq() * v2.magSq());
      return amt <= -1? Math.PI : amt >= 1? 0 : Math.acos(amt);
    };
    
    var a = new PVector(1, 0, 0), b = new PVector(0, 1, 0);
    var ang;
    
    ang = PVector.angleBetween(a, b);
    println(ang); // 90?!
    
    ang = angleBetween(a, b);
    println(ang); // 1.5707963267948966
    
    a.set(-1, 1, 0);
    b.set(-1.5, 1.5, 0);
    var c = new PVector(1.5, -1.5);
    
    ang = PVector.angleBetween(b, c);
    println(ang); // NaN
    
    ang = angleBetween(b, c);
    println(ang); // 3.141592653589793
    
    exit();
  6. k4b7 commented on Mar 4, 2016

    Contributor

    @GoToLoop there's an angleMode setting that processing.js supports and we default to degrees on KA. See https://www.khanacademy.org/computer-programming/anglemode-processingjs/2350518561.

  7. GoToLoop commented on Mar 4, 2016

    Contributor

    Ah! I believe it's the same as p5.js' angleMode(): http://p5js.org/reference/#/p5/angleMode
    I don't find it fully usable b/c although math functions return in degrees, we still need to pass values to them in radians, defeating its convenience.

    We can't for example do something like this: cos(sin(PI)) while in degrees mode.
    In the case above, sin() would return a degree value.
    However cos() still demands a radian arg and can't use sin()'s returned degree value.

    Another unintended consequence is that Khan's _PVector_ class becomes depended on the sketch's state due to angleMode. In Processing, Pjs & p5.js, _PVector_ is independent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL