diff --git a/src/Base/Vector3D.cpp b/src/Base/Vector3D.cpp index aca56bb9400b..03920ed72d9e 100644 --- a/src/Base/Vector3D.cpp +++ b/src/Base/Vector3D.cpp @@ -22,6 +22,7 @@ #include "PreCompiled.h" +#include #include "Tools.h" #include "Vector3D.h" @@ -418,21 +419,21 @@ Vector3<_Precision> & Vector3<_Precision>::Normalize (void) template _Precision Vector3<_Precision>::GetAngle (const Vector3 &rcVect) const { - _Precision divid, fNum; + _Precision len1 = Length(); + _Precision len2 = rcVect.Length(); + if (len1 <= traits_type::epsilon() || len2 <= traits_type::epsilon()) + return std::numeric_limits<_Precision>::quiet_NaN(); // division by zero - divid = Length() * ((Vector3<_Precision>&)rcVect).Length(); + _Precision dot = Dot(rcVect); + dot /= len1; + dot /= len2; - if ((divid < -1e-10f) || (divid > 1e-10f)) { - fNum = (*this * rcVect) / divid; - if (fNum < -1) - return traits_type::pi(); - else if (fNum > 1) - return 0.0F; - else - return _Precision(acos(fNum)); - } - else - return traits_type::maximum(); // division by zero + if (dot <= -1.0) + return traits_type::pi(); + else if (dot >= 1.0) + return 0.0; + + return _Precision(acos(dot)); } template diff --git a/src/Mod/Test/BaseTests.py b/src/Mod/Test/BaseTests.py index 941efca5b1c1..61a47a1b44af 100644 --- a/src/Mod/Test/BaseTests.py +++ b/src/Mod/Test/BaseTests.py @@ -156,6 +156,18 @@ def testString(self): self.TestPar.RemString("44") self.failUnless(self.TestPar.GetString("44","hallo") == "hallo","Deletion error at String") + def testAngle(self): + v1 = FreeCAD.Vector(0,0,0.000001) + v2 = FreeCAD.Vector(0,0.000001,0) + self.assertAlmostEqual(v1.getAngle(v2), math.pi/2) + self.assertAlmostEqual(v2.getAngle(v1), math.pi/2) + + def testAngleWithNullVector(self): + v1 = FreeCAD.Vector(0,0,0) + v2 = FreeCAD.Vector(0,1,0) + self.assertTrue(math.isnan(v1.getAngle(v2))) + self.assertTrue(math.isnan(v2.getAngle(v1))) + def testMatrix(self): m=FreeCAD.Matrix(4,2,1,0,1,1,1,0,0,0,1,0,0,0,0,1) u=m.multiply(m.inverse())