core/vgl/vgl_sphere_3d.txx
Go to the documentation of this file.
00001 #ifndef vgl_sphere_3d_txx_
00002 #define vgl_sphere_3d_txx_
00003 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00004 #pragma implementation
00005 #endif
00006 //:
00007 // \file
00008 // \brief a sphere in 3D nonhomogeneous space
00009 // \author Ian Scott
00010 
00011 #include "vgl_sphere_3d.h"
00012 #include <vcl_cmath.h>
00013 #include <vcl_iostream.h>
00014 #include <vgl/vgl_point_3d.h>
00015 #include <vgl/vgl_closest_point.h>
00016 #include <vgl/vgl_line_3d_2_points.h>
00017 
00018 
00019 //: Return true iff the point p is inside (or on) this sphere
00020 template <class T>
00021 bool vgl_sphere_3d<T>::contains(vgl_point_3d<T> const& p) const
00022 {
00023   return r_ >= 0 && (p-c_).sqr_length() <= r_*r_;
00024 }
00025 
00026 
00027 //: Calculate the end points of a line clipped by this sphere.
00028 // \return true if any of the line touches the sphere.
00029 template <class T>
00030 bool vgl_sphere_3d<T>::clip(const vgl_line_3d_2_points<T> & line,
00031                             vgl_point_3d<T> &p1, vgl_point_3d<T> &p2) const
00032 {
00033   // The empty sphere does not intersect anything:
00034   if (r_ < 0) return false;
00035 
00036   vgl_point_3d<T> cp = vgl_closest_point(line, c_);
00037 
00038   T cp_sqr_len = (cp - c_).sqr_length();
00039   if (cp_sqr_len > r_*r_) return false;
00040 
00041   T half_chord_len = vcl_sqrt(r_*r_ - cp_sqr_len);
00042 
00043   vgl_vector_3d<T> linevec = line.direction();
00044   linevec *= half_chord_len / linevec.length();
00045 
00046   p1 = cp - linevec;
00047   p2 = cp + linevec;
00048 
00049   return true;
00050 }
00051 
00052 
00053 //: Writes "<vgl_sphere_3d centre=vgl_point_3d<x,y,z> radius=r)>" to stream
00054 template <class T>
00055 vcl_ostream& vgl_sphere_3d<T>::print(vcl_ostream& os) const
00056 {
00057   return os << "<vgl_sphere_3d centre=" << c_
00058             << "radius=" << r_ << '>';
00059 }
00060 
00061 
00062 //: Read from stream, possibly with formatting.
00063 //  Either just reads 4 blank-separated numbers,
00064 //  or reads 4 comma-separated numbers,
00065 //  or reads 4 numbers in parenthesized form "(123, 321, 567, 890)"
00066 template <class T>
00067 vcl_istream& vgl_sphere_3d<T>::read(vcl_istream& is)
00068 {
00069   if (! is.good()) return is; // (TODO: should throw an exception)
00070   bool paren = false;
00071   T cx, cy, cz, r;
00072   is >> vcl_ws; // jump over any leading whitespace
00073   if (is.eof()) return is; // nothing to be set because of EOF (TODO: should throw an exception)
00074   if (is.peek() == '(') { is.ignore(); paren=true; }
00075   is >> vcl_ws >> cx >> vcl_ws;
00076   if (is.eof()) return is;
00077   if (is.peek() == ',') is.ignore();
00078   is >> vcl_ws >> cy >> vcl_ws;
00079   if (is.eof()) return is;
00080   if (is.peek() == ',') is.ignore();
00081   is >> vcl_ws >> cz >> vcl_ws;
00082   if (is.eof()) return is;
00083   if (is.peek() == ',') is.ignore();
00084   is >> vcl_ws >> r >> vcl_ws;
00085   if (paren) {
00086     if (is.eof()) return is;
00087     if (is.peek() == ')') is.ignore();
00088     else                  return is; // closing parenthesis is missing (TODO: throw an exception)
00089   }
00090   set_centre(vgl_point_3d<T>(cx,cy,cz));
00091   set_radius(r);
00092   return is;
00093 }
00094 
00095 
00096 //: Writes "<vgl_sphere_3d centre=vgl_point_3d<x,y,z> radius=r)>" to stream
00097 template <class T>
00098 vcl_ostream& operator<<(vcl_ostream& os, const vgl_sphere_3d<T>& sph)
00099 {
00100   return sph.print(os);
00101 }
00102 
00103 
00104 //: Read from stream, possibly with formatting.
00105 //  Either just reads 4 blank-separated numbers,
00106 //  or reads 4 comma-separated numbers,
00107 //  or reads 4 numbers in parenthesized form "(123, 321, 567, 890)"
00108 template <class T>
00109 vcl_istream& operator>>(vcl_istream& is, vgl_sphere_3d<T>& sph)
00110 {
00111   return sph.read(is);
00112 }
00113 
00114 
00115 #undef VGL_SPHERE_3D_INSTANTIATE
00116 #define VGL_SPHERE_3D_INSTANTIATE(T) \
00117 template class vgl_sphere_3d<T >; \
00118 template vcl_ostream& operator<<(vcl_ostream&, vgl_sphere_3d<T >const&); \
00119 template vcl_istream& operator>>(vcl_istream&, vgl_sphere_3d<T >&)
00120 
00121 
00122 #endif // vgl_sphere_3d_txx_