From aea769af3d8e3413400a0e06c949d58b06a4bb26 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 15 Aug 2016 14:09:26 +0200 Subject: [PATCH] use a stricter tolerance to check for equal points add method IsEqual to Vector3 class to support user-defined tolerance --- src/Base/CoordinateSystem.cpp | 12 ++++---- src/Base/Rotation.cpp | 6 ++-- src/Base/Vector3D.cpp | 8 ++++- src/Base/Vector3D.h | 29 +++++++++++++------ src/Base/VectorPy.xml | 10 ++++++- src/Base/VectorPyImp.cpp | 16 ++++++++++ src/Gui/InputVector.cpp | 4 +-- src/Gui/InputVector.h | 6 ++-- .../ReverseEngineering/App/ApproxSurface.cpp | 7 +++-- 9 files changed, 70 insertions(+), 28 deletions(-) diff --git a/src/Base/CoordinateSystem.cpp b/src/Base/CoordinateSystem.cpp index afef0d863..8f491f3cb 100644 --- a/src/Base/CoordinateSystem.cpp +++ b/src/Base/CoordinateSystem.cpp @@ -42,10 +42,10 @@ CoordinateSystem::~CoordinateSystem() void CoordinateSystem::setAxes(const Axis& v, const Vector3d& xd) { - if (xd.Sqr() < FLT_EPSILON) + if (xd.Sqr() < Base::Vector3d::epsilon()) throw Base::Exception("Direction is null vector"); Vector3d yd = v.getDirection() % xd; - if (yd.Sqr() < FLT_EPSILON) + if (yd.Sqr() < Base::Vector3d::epsilon()) throw Base::Exception("Direction is parallel to Z direction"); ydir = yd; xdir = ydir % v.getDirection(); @@ -54,10 +54,10 @@ void CoordinateSystem::setAxes(const Axis& v, const Vector3d& xd) void CoordinateSystem::setAxes(const Vector3d& n, const Vector3d& xd) { - if (xd.Sqr() < FLT_EPSILON) + if (xd.Sqr() < Base::Vector3d::epsilon()) throw Base::Exception("Direction is null vector"); Vector3d yd = n % xd; - if (yd.Sqr() < FLT_EPSILON) + if (yd.Sqr() < Base::Vector3d::epsilon()) throw Base::Exception("Direction is parallel to Z direction"); ydir = yd; xdir = ydir % n; @@ -72,7 +72,7 @@ void CoordinateSystem::setAxis(const Axis& v) void CoordinateSystem::setXDirection(const Vector3d& dir) { Vector3d yd = axis.getDirection() % dir; - if (yd.Sqr() < FLT_EPSILON) + if (yd.Sqr() < Base::Vector3d::epsilon()) throw Base::Exception("Direction is parallel to Z direction"); ydir = yd; xdir = ydir % axis.getDirection(); @@ -81,7 +81,7 @@ void CoordinateSystem::setXDirection(const Vector3d& dir) void CoordinateSystem::setYDirection(const Vector3d& dir) { Vector3d xd = dir & axis.getDirection(); - if (xd.Sqr() < FLT_EPSILON) + if (xd.Sqr() < Base::Vector3d::epsilon()) throw Base::Exception("Direction is parallel to Z direction"); xdir = xd; ydir = axis.getDirection() % xdir; diff --git a/src/Base/Rotation.cpp b/src/Base/Rotation.cpp index db71026ea..77dc8f4a6 100644 --- a/src/Base/Rotation.cpp +++ b/src/Base/Rotation.cpp @@ -225,7 +225,7 @@ void Rotation::setValue(const Vector3d & rotateFrom, const Vector3d & rotateTo) else { // We can use any axis perpendicular to u (and v) Vector3d t = u % Vector3d(1.0, 0.0, 0.0); - if(t.Length() < FLT_EPSILON) + if(t.Length() < Base::Vector3d::epsilon()) t = u % Vector3d(0.0, 1.0, 0.0); this->setValue(t.x, t.y, t.z, 0.0); } @@ -361,11 +361,11 @@ Rotation Rotation::slerp(const Rotation & q0, const Rotation & q1, double t) neg = true; } - if ((1.0 - dot) > FLT_EPSILON) { + if ((1.0 - dot) > Base::Vector3d::epsilon()) { double angle = (double)acos(dot); double sinangle = (double)sin(angle); // If possible calculate spherical interpolation, otherwise use linear interpolation - if (sinangle > FLT_EPSILON) { + if (sinangle > Base::Vector3d::epsilon()) { scale0 = double(sin((1.0 - t) * angle)) / sinangle; scale1 = double(sin(t * angle)) / sinangle; } diff --git a/src/Base/Vector3D.cpp b/src/Base/Vector3D.cpp index e22fc58f2..782ee4a44 100644 --- a/src/Base/Vector3D.cpp +++ b/src/Base/Vector3D.cpp @@ -204,7 +204,13 @@ bool Vector3<_Precision>::operator == (const Vector3<_Precision>& rcVct) const return (fabs (x - rcVct.x) <= traits_type::epsilon()) && (fabs (y - rcVct.y) <= traits_type::epsilon()) && (fabs (z - rcVct.z) <= traits_type::epsilon()); -} +} + +template +bool Vector3<_Precision>::IsEqual(const Vector3<_Precision> &rclPnt, _Precision tol) const +{ + return Distance(*this, rclPnt) <= tol; +} template Vector3<_Precision>& Vector3<_Precision>::ProjectToPlane (const Vector3<_Precision> &rclBase, diff --git a/src/Base/Vector3D.h b/src/Base/Vector3D.h index e8de88663..da39a80af 100644 --- a/src/Base/Vector3D.h +++ b/src/Base/Vector3D.h @@ -26,8 +26,7 @@ #include - -#define FLOAT_EPS 1.0e-4f +#include #ifndef F_PI # define F_PI 3.1415926f @@ -36,9 +35,13 @@ #ifndef D_PI # define D_PI 3.141592653589793 #endif - + #ifndef FLOAT_MAX -# define FLOAT_MAX 1e30f +# define FLOAT_MAX 3.402823466E+38F +#endif + +#ifndef FLOAT_MIN +# define FLOAT_MIN 1.175494351E-38F #endif #ifndef DOUBLE_MAX @@ -58,16 +61,16 @@ template <> struct float_traits { typedef float float_type; static inline float_type pi() { return F_PI; } - static inline float_type epsilon() { return FLOAT_EPS; } - static inline float_type maximum() { return FLOAT_MAX; } + static inline float_type epsilon() { return FLT_EPSILON; } + static inline float_type maximum() { return FLT_MAX; } }; template <> struct float_traits { typedef double float_type; static inline float_type pi() { return D_PI; } - static inline float_type epsilon() { return FLOAT_EPS; } - static inline float_type maximum() { return FLOAT_MAX; } + static inline float_type epsilon() { return FLT_EPSILON; } + static inline float_type maximum() { return DBL_MAX; } }; /** The Vector Base class. */ @@ -161,7 +164,15 @@ public: * \note \a rclDirX must be perpendicular to \a rclDirY, i.e. \a rclDirX * \a rclDirY = 0.. */ void TransformToCoordinateSystem (const Vector3 &rclBase, const Vector3 &rclDirX, const Vector3 &rclDirY); - //bool Equal(const Vector3 &rclVect) const; + /** + * @brief IsEqual + * @param rclPnt + * @param tol + * @return true or false + * If the distance to point \a rclPnt is within the tolerance \a tol both points are considered + * equal. + */ + bool IsEqual(const Vector3 &rclPnt, _Precision tol) const; /// Projects this point onto the plane given by the base \a rclBase and the normal \a rclNorm. Vector3 & ProjectToPlane (const Vector3 &rclBase, const Vector3 &rclNorm); /** diff --git a/src/Base/VectorPy.xml b/src/Base/VectorPy.xml index 34f37b065..c4954a85f 100644 --- a/src/Base/VectorPy.xml +++ b/src/Base/VectorPy.xml @@ -81,7 +81,15 @@ - + + + isEqual(Vector, tolerance) -> Boolean + If the distance to the given point is less or equal to the tolerance + bith points are considered equal. + + + + projectToLine(Vector pnt,Vector vec) Projects the point 'pnt' on a line that goes through the origin with the direction vector 'vec'. diff --git a/src/Base/VectorPyImp.cpp b/src/Base/VectorPyImp.cpp index b8be1da7f..9189aca3a 100644 --- a/src/Base/VectorPyImp.cpp +++ b/src/Base/VectorPyImp.cpp @@ -261,6 +261,22 @@ PyObject* VectorPy::richCompare(PyObject *v, PyObject *w, int op) } } +PyObject* VectorPy::isEqual(PyObject *args) +{ + PyObject *obj; + double tolerance=0; + if (!PyArg_ParseTuple(args, "O!d", &(VectorPy::Type), &obj, &tolerance)) + return 0; + + VectorPy* vec = static_cast(obj); + + VectorPy::PointerType this_ptr = reinterpret_cast(_pcTwinPointer); + VectorPy::PointerType vect_ptr = reinterpret_cast(vec->_pcTwinPointer); + + Py::Boolean eq((*this_ptr).IsEqual(*vect_ptr, tolerance)); + return Py::new_reference_to(eq); +} + PyObject* VectorPy::scale(PyObject *args) { double factorX, factorY, factorZ; diff --git a/src/Gui/InputVector.cpp b/src/Gui/InputVector.cpp index a555fb2ce..491169838 100644 --- a/src/Gui/InputVector.cpp +++ b/src/Gui/InputVector.cpp @@ -141,7 +141,7 @@ void LocationWidget::setPosition(const Base::Vector3d& v) void LocationWidget::setDirection(const Base::Vector3d& dir) { - if (dir.Length() < FLT_EPSILON) { + if (dir.Length() < Base::Vector3d::epsilon()) { return; } @@ -207,7 +207,7 @@ void LocationWidget::on_direction_activated(int index) bool ok; Base::Vector3d dir = this->getUserDirection(&ok); if (ok) { - if (dir.Length() < FLT_EPSILON) { + if (dir.Length() < Base::Vector3d::epsilon()) { QMessageBox::critical(this, LocationDialog::tr("Wrong direction"), LocationDialog::tr("Direction must not be the null vector")); return; diff --git a/src/Gui/InputVector.h b/src/Gui/InputVector.h index 080f0babb..de5009ded 100644 --- a/src/Gui/InputVector.h +++ b/src/Gui/InputVector.h @@ -191,7 +191,7 @@ private: bool ok; Base::Vector3d dir = this->getUserDirection(&ok); if (ok) { - if (dir.Length() < FLT_EPSILON) { + if (dir.Length() < Base::Vector3d::epsilon()) { QMessageBox::critical(this, LocationDialog::tr("Wrong direction"), LocationDialog::tr("Direction must not be the null vector")); return; @@ -304,7 +304,7 @@ public: public: void setDirection(const Base::Vector3d& dir) { - if (dir.Length() < FLT_EPSILON) { + if (dir.Length() < Base::Vector3d::epsilon()) { return; } @@ -336,7 +336,7 @@ public: bool ok; Base::Vector3d dir = dlg->getUserDirection(&ok); if (ok) { - if (dir.Length() < FLT_EPSILON) { + if (dir.Length() < Base::Vector3d::epsilon()) { QMessageBox::critical(dlg, LocationDialog::tr("Wrong direction"), LocationDialog::tr("Direction must not be the null vector")); return false; diff --git a/src/Mod/ReverseEngineering/App/ApproxSurface.cpp b/src/Mod/ReverseEngineering/App/ApproxSurface.cpp index e3c595644..8dd2dd490 100644 --- a/src/Mod/ReverseEngineering/App/ApproxSurface.cpp +++ b/src/Mod/ReverseEngineering/App/ApproxSurface.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -887,10 +888,10 @@ void BSplineParameterCorrection::DoParameterCorrection(int iIter) } fDeltaU = ( (P-X) * Xu ) / ( (P-X)*Xuu - Xu*Xu ); - if (fabs(fDeltaU) < FLOAT_EPS) + if (fabs(fDeltaU) < Precision::Confusion()) fDeltaU = 0.0; fDeltaV = ( (P-X) * Xv ) / ( (P-X)*Xvv - Xv*Xv ); - if (fabs(fDeltaV) < FLOAT_EPS) + if (fabs(fDeltaV) < Precision::Confusion()) fDeltaV = 0.0; //Ersetze die alten u/v-Werte durch die neuen @@ -917,7 +918,7 @@ void BSplineParameterCorrection::DoParameterCorrection(int iIter) i++; } - while(i FLOAT_EPS && fMaxScalar < 0.99); + while(i Precision::Confusion() && fMaxScalar < 0.99); } bool BSplineParameterCorrection::SolveWithoutSmoothing()