Hi All,

I have just checked into svn/trunk the following changes to better handle
numerical precisions issues with the clamping of the line segment to the
bounding box in LineSegmentIntersector.cpp.  These changes are compatible
with being merged with the OSG-3.2 branch and hence could be part of the up
coming OSG-3.2.1 stable release, however, as these changes still
experimental I feel that we need to do some more testing against real user
data before I do this merge.  I have also removed the user definable
epsilon from osgUtil::Intersector as if the new code works fine users won't
need to play with adjusting it.

~/OpenSceneGraph$ svn diff
Index: include/osgUtil/IntersectionVisitor
===================================================================
--- include/osgUtil/IntersectionVisitor (revision 13735)
+++ include/osgUtil/IntersectionVisitor (working copy)
@@ -53,8 +53,7 @@
         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 @@

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


Index: src/osgUtil/LineSegmentIntersector.cpp
===================================================================
--- src/osgUtil/LineSegmentIntersector.cpp      (revision 13735)
+++ src/osgUtil/LineSegmentIntersector.cpp      (working copy)
@@ -244,7 +244,6 @@
         osg::ref_ptr<LineSegmentIntersector> lsi = new
LineSegmentIntersector(_start, _end);
         lsi->_parent = this;
         lsi->_intersectionLimit = this->_intersectionLimit;
-        lsi->_epsilon = this->_epsilon;
         return lsi.release();
     }

@@ -279,7 +278,6 @@
     osg::ref_ptr<LineSegmentIntersector> 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 @@
     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_min.x()) return false;
         if (s.x()>bb_max.x()) return false;
@@ -505,13 +496,15 @@
         if (s.x()<bb_min.x())
         {
             // clip s to xMin.
-            s = s+(e-s)*(bb_min.x()-s.x())/(e.x()-s.x());
+            double r = (bb_min.x()-s.x())/(e.x()-s.x()) - epsilon;
+            if (r>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 @@

         if (e.x()<bb_min.x())
         {
-            // clip s to xMin.
-            e = s+(e-s)*(bb_min.x()-s.x())/(e.x()-s.x());
+            // clip e to xMin.
+            double r = (bb_min.x()-e.x())/(s.x()-e.x()) - epsilon;
+            if (r>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_min.y()) return false;
         if (s.y()>bb_max.y()) return false;
@@ -543,13 +537,15 @@
         if (s.y()<bb_min.y())
         {
             // clip s to yMin.
-            s = s+(e-s)*(bb_min.y()-s.y())/(e.y()-s.y());
+            double r = (bb_min.y()-s.y())/(e.y()-s.y()) - epsilon;
+            if (r>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 @@

         if (e.y()<bb_min.y())
         {
-            // clip s to yMin.
-            e = s+(e-s)*(bb_min.y()-s.y())/(e.y()-s.y());
+            // clip e to yMin.
+            double r = (bb_min.y()-e.y())/(s.y()-e.y()) - epsilon;
+            if (r>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_min.z()) return false;
         if (s.z()>bb_max.z()) return false;
@@ -581,13 +578,15 @@
         if (s.z()<bb_min.z())
         {
             // clip s to zMin.
-            s = s+(e-s)*(bb_min.z()-s.z())/(e.z()-s.z());
+            double r = (bb_min.z()-s.z())/(e.z()-s.z()) - epsilon;
+            if (r>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 @@

         if (e.z()<bb_min.z())
         {
-            // clip s to zMin.
-            e = s+(e-s)*(bb_min.z()-s.z())/(e.z()-s.z());
+            // clip e to zMin.
+            double r = (bb_min.z()-e.z())/(s.z()-e.z()) - epsilon;
+            if (r>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;
         }
     }

These changes are now checked into svn/trunk.  I've also attached the
modified LineSegmentIntersector.cpp. Could users please test against the
dataset that they found problems with and let me know how you get on.  We
may need to adjust the value of epsilon of 1e-13 that I used to handle the
scale of precision errors that we might see with large values.  Let me know
how you get on.

Cheers,
Robert.
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to