Skip to content

angle_vectors returns 0 for zero-length vectors instead of raising an error #1528

Description

@chenkasirer

This has been discussed in #1462, however, imo, this needs to be fixed in angle_vectors.

angle_vectors returns 0 when either input vector has zero length. But the angle between a vector and a zero-length vector is undefined - there's no direction to compare against. Returning 0 looks like "these vectors point the same way," which is misleading.

To Reproduce

from compas.geometry import angle_vectors

u = [1, 0, 0]
v = [0, 0, 0]  # zero-length vector

angle_vectors(u, v)  # -> 0

Expected behavior
I'd expect a ValueError in such a case. Since this can be considered a braking change we could consider making it an opt-in silent failure line in Blender (see below). Or we wait with this for COMPAS 3.x.

Agreeing with Tom that

the angle between two vectors can't be None.
the function should either return a float or throw an error.

and it should only throw an error if the angle cannot be computed form the input data, not because the result
value is "inconvenient" :)

Our case is the angle cannot be computed from the input data as it results in a division by zero:
https://www.freakinsweetapps.com/Teaching/VectorMatrixMath/angle_between.html

Additional context

Took a look at how this is handled in some other libraries:

Blender

>>> Vector([1, 0, 0]).angle(Vector([0, 0, 0]))
Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
ValueError: Vector.angle(other): zero length vectors have no valid angle

ThreeJS decided to return 90 degrees in such a case, explained here:
mrdoob/three.js#17545 (comment)

SciPy fires a warning.. and then runs it anyways to get a nan ;)

/distance.py:670: RuntimeWarning: invalid value encountered in scalar divide
  dist = 1.0 - uv / math.sqrt(uu * vv)
cosine distance: nan
/Users/chenkasirer/angle_vectors_scipy.py:10: RuntimeWarning: invalid value encountered in scalar divide
  np.clip(np.dot(u, v) / (np.linalg.norm(u) * np.linalg.norm(v)), -1, 1)
manual arccos formula: nan

Rhino Common returns some funky magic number which apparently means Unset:

v1 = rg.Vector3d(1, 0, 0)
v2 = rg.Vector3d(0, 0, 0)

result = rg.Vector3d.VectorAngle(v1, v2)

-1.23432101234321e+308

https://discourse.mcneel.com/t/in-what-kind-of-condition-rhino-geometry-vector3d-vectorangle-return-1-23432101234321e-308/54906

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