From b9ecec645241947e2d8e03966c16e3b3b129ca1f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 2 Sep 2013 10:56:14 +0000 Subject: [PATCH] Refactored the use of epsilon in the clamping of the start/end points of the LineSegmentIntersector to better handle numerical precision issues. --- include/osgUtil/IntersectionVisitor | 11 +---- src/osgUtil/LineSegmentIntersector.cpp | 61 +++++++++++++------------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/include/osgUtil/IntersectionVisitor b/include/osgUtil/IntersectionVisitor index 28450bafe..b513e525d 100644 --- a/include/osgUtil/IntersectionVisitor +++ b/include/osgUtil/IntersectionVisitor @@ -53,8 +53,7 @@ class Intersector : public osg::Referenced Intersector(CoordinateFrame cf=MODEL): _coordinateFrame(cf), _intersectionLimit(NO_LIMIT), - _disabledCount(0), - _epsilon(1e-4) {} + _disabledCount(0) {} void setCoordinateFrame(CoordinateFrame cf) { _coordinateFrame = cf; } @@ -85,19 +84,11 @@ class Intersector : public osg::Referenced inline bool reachedLimit() { return _intersectionLimit == LIMIT_ONE && containsIntersections(); } - /** Set Epsilon value, where supported is used in numerical comparisons to workaround number precisions issues.*/ - inline void setEpsilon(double epsilon) { _epsilon = epsilon; } - - /** Get Epsilon value.*/ - inline double getEpsilon() const { return _epsilon; } - protected: CoordinateFrame _coordinateFrame; IntersectionLimit _intersectionLimit; unsigned int _disabledCount; - double _epsilon; - }; diff --git a/src/osgUtil/LineSegmentIntersector.cpp b/src/osgUtil/LineSegmentIntersector.cpp index 2553927f8..dd88c25eb 100644 --- a/src/osgUtil/LineSegmentIntersector.cpp +++ b/src/osgUtil/LineSegmentIntersector.cpp @@ -244,7 +244,6 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv) osg::ref_ptr lsi = new LineSegmentIntersector(_start, _end); lsi->_parent = this; lsi->_intersectionLimit = this->_intersectionLimit; - lsi->_epsilon = this->_epsilon; return lsi.release(); } @@ -279,7 +278,6 @@ Intersector* LineSegmentIntersector::clone(osgUtil::IntersectionVisitor& iv) osg::ref_ptr lsi = new LineSegmentIntersector(_start * inverse, _end * inverse); lsi->_parent = this; lsi->_intersectionLimit = this->_intersectionLimit; - lsi->_epsilon = this->_epsilon; return lsi.release(); } @@ -486,18 +484,11 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const osg::Vec3d bb_min(bbInput._min); osg::Vec3d bb_max(bbInput._max); - // expand the extents of the bounding box by the epsilon to prevent numerical errors resulting in misses. - bb_min.x() -= _epsilon; - bb_min.y() -= _epsilon; - bb_min.z() -= _epsilon; - bb_max.x() += _epsilon; - bb_max.y() += _epsilon; - bb_max.z() += _epsilon; + double epsilon = 1e-13; // compate s and e against the xMin to xMax range of bb. if (s.x()<=e.x()) { - // trivial reject of segment wholely outside. if (e.x()bb_max.x()) return false; @@ -505,13 +496,15 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const if (s.x()0.0) s = s + (e-s)*r; } if (e.x()>bb_max.x()) { // clip e to xMax. - e = s+(e-s)*(bb_max.x()-s.x())/(e.x()-s.x()); + double r = (bb_max.x()-s.x())/(e.x()-s.x()) + epsilon; + if (r<1.0) e = s+(e-s)*r; } } else @@ -521,21 +514,22 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const if (e.x()0.0) e = e + (s-e)*r; } if (s.x()>bb_max.x()) { - // clip e to xMax. - s = s+(e-s)*(bb_max.x()-s.x())/(e.x()-s.x()); + // clip s to xMax. + double r = (bb_max.x()-e.x())/(s.x()-e.x()) + epsilon; + if (r<1.0) s = e + (s-e)*r; } } // compate s and e against the yMin to yMax range of bb. if (s.y()<=e.y()) { - // trivial reject of segment wholely outside. if (e.y()bb_max.y()) return false; @@ -543,13 +537,15 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const if (s.y()0.0) s = s + (e-s)*r; } if (e.y()>bb_max.y()) { // clip e to yMax. - e = s+(e-s)*(bb_max.y()-s.y())/(e.y()-s.y()); + double r = (bb_max.y()-s.y())/(e.y()-s.y()) + epsilon; + if (r<1.0) e = s+(e-s)*r; } } else @@ -559,21 +555,22 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const if (e.y()0.0) e = e + (s-e)*r; } if (s.y()>bb_max.y()) { - // clip e to yMax. - s = s+(e-s)*(bb_max.y()-s.y())/(e.y()-s.y()); + // clip s to yMax. + double r = (bb_max.y()-e.y())/(s.y()-e.y()) + epsilon; + if (r<1.0) s = e + (s-e)*r; } } // compate s and e against the zMin to zMax range of bb. if (s.z()<=e.z()) { - // trivial reject of segment wholely outside. if (e.z()bb_max.z()) return false; @@ -581,13 +578,15 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const if (s.z()0.0) s = s + (e-s)*r; } if (e.z()>bb_max.z()) { // clip e to zMax. - e = s+(e-s)*(bb_max.z()-s.z())/(e.z()-s.z()); + double r = (bb_max.z()-s.z())/(e.z()-s.z()) + epsilon; + if (r<1.0) e = s+(e-s)*r; } } else @@ -597,14 +596,16 @@ bool LineSegmentIntersector::intersectAndClip(osg::Vec3d& s, osg::Vec3d& e,const if (e.z()0.0) e = e + (s-e)*r; } if (s.z()>bb_max.z()) { - // clip e to zMax. - s = s+(e-s)*(bb_max.z()-s.z())/(e.z()-s.z()); + // clip s to zMax. + double r = (bb_max.z()-e.z())/(s.z()-e.z()) + epsilon; + if (r<1.0) s = e + (s-e)*r; } }