core/vgl/vgl_point_3d.txx
Go to the documentation of this file.
00001 // This is core/vgl/vgl_point_3d.txx
00002 #ifndef vgl_point_3d_txx_
00003 #define vgl_point_3d_txx_
00004 //:
00005 // \file
00006 
00007 #include "vgl_point_3d.h"
00008 #include <vgl/vgl_homg_point_3d.h>
00009 #include <vgl/vgl_plane_3d.h>
00010 #include <vgl/vgl_homg_plane_3d.h>
00011 #include <vgl/vgl_tolerance.txx>
00012 
00013 #include <vcl_iostream.h>
00014 #include <vcl_iomanip.h>
00015 #include <vcl_cmath.h> // for std::sqrt
00016 
00017 //: Construct from homogeneous point
00018 template <class Type>
00019 vgl_point_3d<Type>::vgl_point_3d(vgl_homg_point_3d<Type> const& p)
00020   : x_(p.x()/p.w()), y_(p.y()/p.w()), z_(p.z()/p.w()) // could be infinite!
00021 {
00022 }
00023 
00024 //: Construct from 3 planes (intersection).
00025 template <class Type>
00026 vgl_point_3d<Type>::vgl_point_3d(vgl_plane_3d<Type> const& pl1,
00027                                  vgl_plane_3d<Type> const& pl2,
00028                                  vgl_plane_3d<Type> const& pl3)
00029 {
00030   vgl_homg_plane_3d<Type> h1(pl1.nx(), pl1.ny(), pl1.nz(), pl1.d());
00031   vgl_homg_plane_3d<Type> h2(pl2.nx(), pl2.ny(), pl2.nz(), pl2.d());
00032   vgl_homg_plane_3d<Type> h3(pl3.nx(), pl3.ny(), pl3.nz(), pl3.d());
00033   vgl_homg_point_3d<Type> p(h1, h2, h3); // do homogeneous intersection
00034   set(p.x()/p.w(), p.y()/p.w(), p.z()/p.w()); // could be infinite!
00035 }
00036 
00037 template <class Type>
00038 bool vgl_point_3d<Type>::operator==(const vgl_point_3d<Type> &p) const
00039 {
00040   return this==&p || (x_>=p.x()-vgl_tolerance<Type>::position && x_<=p.x()+vgl_tolerance<Type>::position &&
00041                       y_>=p.y()-vgl_tolerance<Type>::position && y_<=p.y()+vgl_tolerance<Type>::position &&
00042                       z_>=p.z()-vgl_tolerance<Type>::position && z_<=p.z()+vgl_tolerance<Type>::position );
00043 }
00044 
00045 template <class Type>
00046 bool coplanar(vgl_point_3d<Type> const& p1,
00047               vgl_point_3d<Type> const& p2,
00048               vgl_point_3d<Type> const& p3,
00049               vgl_point_3d<Type> const& p4)
00050 {
00051   Type r = ( (p1.x()*p2.y()-p1.y()*p2.x())*p3.z()
00052             +(p3.x()*p1.y()-p3.y()*p1.x())*p2.z()
00053             +(p2.x()*p3.y()-p2.y()*p3.x())*p1.z()
00054             +(p1.x()*p4.y()-p1.y()*p4.x())*p2.z()
00055             +(p4.x()*p2.y()-p4.y()*p2.x())*p1.z()
00056             +(p2.x()*p1.y()-p2.y()*p1.x())*p4.z()
00057             +(p3.x()*p4.y()-p3.y()*p4.x())*p1.z()
00058             +(p1.x()*p3.y()-p1.y()*p3.x())*p4.z()
00059             +(p4.x()*p1.y()-p4.y()*p1.x())*p3.z()
00060             +(p3.x()*p2.y()-p3.y()*p2.x())*p4.z()
00061             +(p2.x()*p4.y()-p2.y()*p4.x())*p3.z()
00062             +(p4.x()*p3.y()-p4.y()*p3.x())*p2.z() );
00063   return r <= vgl_tolerance<Type>::point_3d_coplanarity && r >= -vgl_tolerance<Type>::point_3d_coplanarity;
00064 }
00065 
00066 template <class T>
00067 double cross_ratio(vgl_point_3d<T>const& p1, vgl_point_3d<T>const& p2,
00068                    vgl_point_3d<T>const& p3, vgl_point_3d<T>const& p4)
00069 {
00070   // least squares solution: (Num_x-CR*Den_x)^2 + (Num_y-CR*Den_y)^2 + (Num_z-CR*Den_z)^2 minimal.
00071   double Num_x = (p1.x()-p3.x())*(p2.x()-p4.x());
00072   double Num_y = (p1.y()-p3.y())*(p2.y()-p4.y());
00073   double Num_z = (p1.z()-p3.z())*(p2.z()-p4.z());
00074   double Den_x = (p1.x()-p4.x())*(p2.x()-p3.x());
00075   double Den_y = (p1.y()-p4.y())*(p2.y()-p3.y());
00076   double Den_z = (p1.z()-p4.z())*(p2.z()-p3.z());
00077   if (Den_x == Den_y && Den_y == Den_z) return (Num_x+Num_y+Num_z)/3/Den_x;
00078   else return (Den_x*Num_x+Den_y*Num_y+Den_z*Num_z)/(Den_x*Den_x+Den_y*Den_y+Den_z*Den_z);
00079 }
00080 
00081 //: Write "<vgl_point_3d x,y,z> " to stream
00082 template <class Type>
00083 vcl_ostream&  operator<<(vcl_ostream& s, vgl_point_3d<Type> const& p)
00084 {
00085   return s << "<vgl_point_3d "<< p.x() << ',' << p.y() << ',' << p.z() << "> ";
00086 }
00087 
00088 //: Read from stream, possibly with formatting
00089 //  Either just reads three blank-separated numbers,
00090 //  or reads three comma-separated numbers,
00091 //  or reads three numbers in parenthesized form "(123, 321, 567)"
00092 // \relatesalso vgl_point_3d
00093 template <class Type>
00094 vcl_istream& vgl_point_3d<Type>::read(vcl_istream& is)
00095 {
00096   if (! is.good()) return is; // (TODO: should throw an exception)
00097   bool paren = false;
00098   Type tx, ty, tz;
00099   is >> vcl_ws; // jump over any leading whitespace
00100   if (is.eof()) return is; // nothing to be set because of EOF (TODO: should throw an exception)
00101   if (is.peek() == '(') { is.ignore(); paren=true; }
00102   is >> vcl_ws >> tx >> vcl_ws;
00103   if (is.eof()) return is;
00104   if (is.peek() == ',') is.ignore();
00105   is >> vcl_ws >> ty >> vcl_ws;
00106   if (is.eof()) return is;
00107   if (is.peek() == ',') is.ignore();
00108   is >> vcl_ws >> tz >> vcl_ws;
00109   if (paren) {
00110     if (is.eof()) return is;
00111     if (is.peek() == ')') is.ignore();
00112     else                  return is; // closing parenthesis is missing (TODO: throw an exception)
00113   }
00114   set(tx,ty,tz);
00115   return is;
00116 }
00117 
00118 //: Read from stream, possibly with formatting
00119 //  Either just reads three blank-separated numbers,
00120 //  or reads three comma-separated numbers,
00121 //  or reads three numbers in parenthesized form "(123, 321, 567)"
00122 // \relatesalso vgl_point_3d
00123 template <class Type>
00124 vcl_istream&  operator>>(vcl_istream& is, vgl_point_3d<Type>& p)
00125 {
00126   return p.read(is);
00127 }
00128 
00129 //: Return the "average deviation" of a set of given points from its centre of gravity.
00130 //  "Average" in the sense of the standard deviation (2-norm, i.e., square root
00131 //  of sum of squares) of the distances from that centre of gravity.
00132 // \relatesalso vgl_point_3d
00133 template <class Type>
00134 double stddev(vcl_vector<vgl_point_3d<Type> > const& v)
00135 {
00136   int n = (int)(v.size());
00137   double d = 0.0;
00138   if (n<=1) return d;
00139   vgl_point_3d<Type> c = centre(v);
00140   Type cx = c.x(), cy = c.y(), cz = c.z();
00141 #define vgl_sqr(x) double((x)*(x))
00142   for (int i=0; i<n; ++i)
00143     d += vgl_sqr(v[i].x()-cx) + vgl_sqr(v[i].y()-cy) + vgl_sqr(v[i].z()-cz);
00144 #undef vgl_sqr
00145   return vcl_sqrt(d);
00146 }
00147 
00148 
00149 #undef VGL_POINT_3D_INSTANTIATE
00150 #define VGL_POINT_3D_INSTANTIATE(T) \
00151 template class vgl_point_3d<T >; \
00152 template double cross_ratio(vgl_point_3d<T >const&, vgl_point_3d<T >const&, \
00153                             vgl_point_3d<T >const&, vgl_point_3d<T >const&); \
00154 template bool coplanar(vgl_point_3d<T > const&, vgl_point_3d<T > const&, \
00155                        vgl_point_3d<T > const&, vgl_point_3d<T > const&); \
00156 template vcl_ostream& operator<<(vcl_ostream&, const vgl_point_3d<T >&); \
00157 template vcl_istream& operator>>(vcl_istream&, vgl_point_3d<T >&); \
00158 template double stddev(vcl_vector<vgl_point_3d<T > > const&)
00159 
00160 #endif // vgl_point_3d_txx_