ezag / pyeuclid

2D and 3D maths module for Python
96 stars 41 forks source link

euclid3 crashes with "math domain error" #22

Open StarsoftAnalysis opened 5 years ago

StarsoftAnalysis commented 5 years ago

I've stumbled upon a bug in the otherwise-wonderful Python euclid library. It initially occurred with the Arch Linux package python-euclid3, and I've just reproduced it with the latest Git-cloned version from here.

Here's the problem reduced to a few lines in the interpreter. I'm not sure if there's anything special about the values 114,96 etc. -- when I tried it with simpler lines in the same directions, the problem went away.

>>> from pyeuclid.euclid import *
>>> seg = LineSegment2(Point2(114,96), Point2(117,93))
>>> vec = Vector2(0.71, -0.71)
>>> vec.angle(seg.v)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/chris/projects/vplotter/hpgl_to_vplot/pyeuclid/euclid.py", line 306, in angle
    return math.acos(self.dot(other) / (self.magnitude()*other.magnitude()))
ValueError: math domain error
>>>
>>> seg = LineSegment2(Point2(0,0), Point2(3,-3))
>>> vec = Vector2(1,-1)
>>> vec.angle(seg.v)
0.0

I'm using Python 3.7.2 on up-to-date 64-bit Arch Linux.

bootchk commented 5 years ago

My initial thoughts, I could be mistaken....

"math domain error" must be from math.acos(), which requires its argument to be in a certain range -1, 1 ? (Read about atan2() and atan(), one is more lenient. Maybe pyeuclid is using too restrictive a function acos().)

Does a line segment define one vector? In other words, are you accessing a private attribute "v" of the line segment "seg" when you use "seg.v". I started by looking at the readme for pyeuclid, and it doesn't describe a method of accessing the vector of a segment. It seems to me that a line segment does NOT uniquely describe a vector.

StarsoftAnalysis commented 5 years ago

Yes, it's an arccos vs. floating point thing: it's trying to evaluate math.acos(1.00000002). I've fixed it by using math.atan2() instead, and could do a patch or pull request if required.