Skip to content

[p5.js 2.0+ Bug Report]: Vector angleBetween() doesn't work for vectors with more than three dimensions #8926

Open

Description

@sidwellr

Most appropriate sub-area of p5.js?

  • Accessibility
  • Color
  • Core/Environment/Rendering
  • Data
  • DOM
  • Events
  • Image
  • IO
  • Math
  • Typography
  • Utilities
  • WebGL
  • WebGPU
  • p5.strands
  • Build process
  • Unit testing
  • Internationalization
  • Friendly errors
  • Other (specify if possible)

p5.js version

2.3.0

Web browser and version

Brave 1.90.122

Operating system

Linux Mint 22.1

Steps to reproduce this

Steps:

  1. Create two four dimensional vectors
  2. Use angleBetween to compute the angle between them
  3. Note that it is incorrect (although no errors were reported)

Snippet:

function setup() {
  let v1 = createVector(1, 0, 0, 0);
  let v2 = createVector(0, 0, 0, 1);
  let theta = v1.angleBetween(v2);
  
  // The correct angle between v1 and v2 is PI/2, but theta is 0
  print(theta);
}

Discussion

The angleBetween() method currently uses cross() to compute the angle. This was fine in p5.js version 1 since vectors were always 3D. But version 2 vectors can have any number of dimensions, so angleBetween() needs to use a more general method. I recommend using the dot product divided by the product of the vector lengths:

angleBetween(v1, v2) = acos(v1.dot(v2) / (v1.mag() * v2.mag()))

This will work for vectors of any dimension (including 2D and 3D vectors).

This issue applies to both the instance and static methods.

Activity

  1. ksen0 commented on Jun 17, 2026

    @ksen0
    Member

    Hi everyone, this is reserved for the CodeDay microinternship. If it is not completed by them, then it can be opened to volunteers. But for now, please do not make PRs or volunteer - thanks for understanding!

    The solution should generalize angleBetween() to N dimensions:

    • add unit tests checking behavior for beyond 3d dimensionalities, as well as for operations between vectors of mismatched dimensions
    • when performing binary operation on vectors of different dimensions, use smallest vector priority: check the implementation of add, sub, div, mult, rem and their behavior on mismatched sized vectors
  2. sidwellr commented on Jun 23, 2026

    @sidwellr
    Author

    The documentation states "The angles returned are signed, which means that v1.angleBetween(v2) === -v2.angleBetween(v1)." The general dot product method will not do this.

    I think a signed angle only makes sense for 2D vectors: it is positive if the second vector is positioned clockwise from the first. There are probably p5 sketches that depend on this, so this 2D behavior needs to be preserved.

    The case for 3D is less clear. A common practice is to take the sign relative to the normal of the plane formed by the two vectors. But angleBetween() doesn't currently work this way. For example, the following code will print positive PI/2 for both directions:

    function setup() {
      let v0 = createVector(0, 1, 0);
      let v1 = createVector(0, 0, 1);
      print(v0.angleBetween(v1));
      print(v1.angleBetween(v0));
    }

    I don't think a signed angle makes any sense for more than three dimensions.

    My thought is to return a signed angle for 2D vectors and an unsigned angle for any other dimension. But please discuss! And be sure to update the documentation to match whatever is implemented.

  3. VEERAJ-mark27 commented on Oct 22, 2026

    @VEERAJ-mark27

    Hi, I'd like to contribute to this issue.

    I'll reproduce the behavior using vectors with more than three dimensions, inspect the angleBetween() implementation, and add regression tests to identify where the calculation fails. I'll check the expected behavior for different vector dimensions and make sure the fix preserves existing 2D and 3D behavior.

    Could you please confirm whether this issue is available and assign it to me if appropriate?

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions