use a stricter tolerance to check for equal points

add method IsEqual to Vector3 class to support user-defined tolerance
This commit is contained in:
wmayer 2016-08-15 14:09:26 +02:00
parent e2345374ca
commit aea769af3d
9 changed files with 70 additions and 28 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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 <class _Precision>
bool Vector3<_Precision>::IsEqual(const Vector3<_Precision> &rclPnt, _Precision tol) const
{
return Distance(*this, rclPnt) <= tol;
}
template <class _Precision>
Vector3<_Precision>& Vector3<_Precision>::ProjectToPlane (const Vector3<_Precision> &rclBase,

View File

@ -26,8 +26,7 @@
#include <cmath>
#define FLOAT_EPS 1.0e-4f
#include <cfloat>
#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<float> {
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<double> {
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);
/**

View File

@ -81,7 +81,15 @@
</UserDocu>
</Documentation>
</Methode>
<Methode Name="projectToLine">
<Methode Name="isEqual">
<Documentation>
<UserDocu>isEqual(Vector, tolerance) -> Boolean
If the distance to the given point is less or equal to the tolerance
bith points are considered equal.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="projectToLine">
<Documentation>
<UserDocu>projectToLine(Vector pnt,Vector vec)
Projects the point 'pnt' on a line that goes through the origin with the direction vector 'vec'.

View File

@ -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<VectorPy*>(obj);
VectorPy::PointerType this_ptr = reinterpret_cast<VectorPy::PointerType>(_pcTwinPointer);
VectorPy::PointerType vect_ptr = reinterpret_cast<VectorPy::PointerType>(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;

View File

@ -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;

View File

@ -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;

View File

@ -25,6 +25,7 @@
#include <math_Gauss.hxx>
#include <math_Householder.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Precision.hxx>
#include <QFuture>
#include <QFutureWatcher>
@ -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<iIter && fMaxDiff > FLOAT_EPS && fMaxScalar < 0.99);
while(i<iIter && fMaxDiff > Precision::Confusion() && fMaxScalar < 0.99);
}
bool BSplineParameterCorrection::SolveWithoutSmoothing()