diff --git a/include/osg/LineSegment b/include/osg/LineSegment index 83fb69e41..d368cc6e5 100644 --- a/include/osg/LineSegment +++ b/include/osg/LineSegment @@ -52,6 +52,11 @@ class OSG_EXPORT LineSegment : public Referenced */ bool intersect(const BoundingBox& bb,float& r1,float& r2) const; + /** return true if segment intersects BoundingBox + * and return the intersection ratios. + */ + bool intersect(const BoundingBox& bb,double& r1,double& r2) const; + /** return true if segment intersects BoundingSphere. */ bool intersect(const BoundingSphere& bs) const; @@ -60,10 +65,21 @@ class OSG_EXPORT LineSegment : public Referenced */ bool intersect(const BoundingSphere& bs,float& r1,float& r2) const; + /** return true if segment intersects BoundingSphere and return the + * intersection ratio. + */ + bool intersect(const BoundingSphere& bs,double& r1,double& r2) const; + /** return true if segment intersects triangle * and set ratio long segment. */ - bool intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r); + bool intersect(const Vec3f& v1,const Vec3f& v2,const Vec3f& v3,float& r); + + /** return true if segment intersects triangle + * and set ratio long segment. + */ + bool intersect(const Vec3d& v1,const Vec3d& v2,const Vec3d& v3,double& r); + /** post multiply a segment by matrix.*/ inline void mult(const LineSegment& seg,const Matrix& m) { _s = seg._s*m; _e = seg._e*m; } diff --git a/src/osg/LineSegment.cpp b/src/osg/LineSegment.cpp index 25ad713a0..f4408edd1 100644 --- a/src/osg/LineSegment.cpp +++ b/src/osg/LineSegment.cpp @@ -171,6 +171,30 @@ bool LineSegment::intersect(const BoundingBox& bb,float& r1,float& r2) const return result; } +bool LineSegment::intersect(const BoundingBox& bb,double& r1,double& r2) const +{ + if (!bb.valid()) return false; + + vec_type s=_s,e=_e; + bool result = intersectAndClip(s,e,bb); + if (result) + { + double len = (_e-_s).length(); + if (len>0.0) + { + double inv_len = 1.0/len; + r1 = ((s-_s).length()*inv_len); + r2 = ((e-_e).length()*inv_len); + } + else + { + r1 = 0.0; + r2 = 0.0; + } + } + return result; +} + bool LineSegment::intersect(const BoundingSphere& bs,float& r1,float& r2) const { @@ -217,6 +241,52 @@ bool LineSegment::intersect(const BoundingSphere& bs,float& r1,float& r2) const } + +bool LineSegment::intersect(const BoundingSphere& bs,double& r1,double& r2) const +{ + vec_type sm = _s-bs._center; + value_type c = sm.length2()-bs._radius*bs._radius; + + vec_type se = _e-_s; + value_type a = se.length2(); + + + // check for zero length segment. + if (a==0.0) + { + // check if start point outside sphere radius + if (c>0.0) return false; + + // length segment within radius of bounding sphere but zero length + // so return true, and set the ratio so the start point is the one + // to be used. + r1 = 1.0f; + r2 = 0.0f; + return true; + } + + value_type b = sm*se*2.0; + + value_type d = b*b-4.0f*a*c; + + if (d<0.0f) return false; + + d = (value_type)sqrt(d); + + + value_type div = 1.0f/(2.0*a); + + r1 = ((-b-d)*div); + r2 = ((-b+d)*div); + + if (r1<=0.0 && r2<=0.0) return false; + + if (r1>=1.0 && r2>=1.0) return false; + + return true; +} + + bool LineSegment::intersect(const BoundingSphere& bs) const { vec_type sm = _s-bs._center; @@ -247,7 +317,7 @@ bool LineSegment::intersect(const BoundingSphere& bs) const } -bool LineSegment::intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& r) +bool LineSegment::intersect(const Vec3f& v1,const Vec3f& v2,const Vec3f& v3,float& r) { if (v1==v2 || v2==v3 || v1==v3) return false; @@ -257,14 +327,14 @@ bool LineSegment::intersect(const Vec3& v1,const Vec3& v2,const Vec3& v3,float& vec_type n12 = v12^vse; value_type ds12 = (_s-v1)*n12; value_type d312 = (v3-v1)*n12; - if (d312>=0.0f) + if (d312>=0.0) { - if (ds12<0.0f) return false; + if (ds12<0.0) return false; if (ds12>d312) return false; } else // d312 < 0 { - if (ds12>0.0f) return false; + if (ds12>0.0) return false; if (ds12=0.0f) + if (d123>=0.0) { - if (ds23<0.0f) return false; + if (ds23<0.0) return false; if (ds23>d123) return false; } else // d123 < 0 { - if (ds23>0.0f) return false; + if (ds23>0.0) return false; if (ds23=0.0f) + if (d231>=0.0) { - if (ds31<0.0f) return false; + if (ds31<0.0) return false; if (ds31>d231) return false; } else // d231 < 0 { - if (ds31>0.0f) return false; + if (ds31>0.0) return false; if (ds31length) return false; r = (float) d/length; return true; } + +bool LineSegment::intersect(const Vec3d& v1,const Vec3d& v2,const Vec3d& v3,double& r) +{ + if (v1==v2 || v2==v3 || v1==v3) return false; + + vec_type vse = _e-_s; + + vec_type v12 = v2-v1; + vec_type n12 = v12^vse; + value_type ds12 = (_s-v1)*n12; + value_type d312 = (v3-v1)*n12; + if (d312>=0.0) + { + if (ds12<0.0) return false; + if (ds12>d312) return false; + } + else // d312 < 0 + { + if (ds12>0.0) return false; + if (ds12=0.0) + { + if (ds23<0.0) return false; + if (ds23>d123) return false; + } + else // d123 < 0 + { + if (ds23>0.0) return false; + if (ds23=0.0) + { + if (ds31<0.0) return false; + if (ds31>d231) return false; + } + else // d231 < 0 + { + if (ds31>0.0) return false; + if (ds31length) return false; + + r = d/length; + + return true; +}