core/vgl/vgl_point_3d.h
Go to the documentation of this file.
00001 // This is core/vgl/vgl_point_3d.h
00002 #ifndef vgl_point_3d_h
00003 #define vgl_point_3d_h
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief a point in 3D nonhomogeneous space
00010 // \author Don Hamilton, Peter Tu
00011 //
00012 // \verbatim
00013 //  Modifications
00014 //   Peter Vanroose -  2 July 2001 - Added constructor from 3 planes
00015 //   Peter Vanroose - 24 Oct. 2002 - Added coplanar()
00016 //   Peter Vanroose - 21 May  2009 - istream operator>> re-implemented
00017 // \endverbatim
00018 
00019 #include <vcl_iosfwd.h>
00020 #include <vgl/vgl_fwd.h> // forward declare vgl_plane_3d
00021 #include <vgl/vgl_vector_3d.h>
00022 #include <vcl_cassert.h>
00023 #include <vcl_vector.h>
00024 
00025 //: Represents a cartesian 3D point
00026 template <class Type>
00027 class vgl_point_3d
00028 {
00029   // the data associated with this point
00030   Type x_;
00031   Type y_;
00032   Type z_;
00033 
00034  public:
00035 
00036   // Constructors/Initializers/Destructor------------------------------------
00037 
00038   //: Default constructor
00039   inline vgl_point_3d () {}
00040 
00041   //: Construct from three Types.
00042   inline vgl_point_3d(Type px, Type py, Type pz) : x_(px), y_(py), z_(pz) {}
00043 
00044   //: Construct from 3-array.
00045   inline vgl_point_3d (const Type v[3]) : x_(v[0]), y_(v[1]), z_(v[2]) {}
00046 
00047   //: Construct from homogeneous point
00048   vgl_point_3d (vgl_homg_point_3d<Type> const& p);
00049 
00050   //: Construct from 3 planes (intersection).
00051   vgl_point_3d (vgl_plane_3d<Type> const& pl1,
00052                 vgl_plane_3d<Type> const& pl2,
00053                 vgl_plane_3d<Type> const& pl3);
00054 
00055 #if 0 // The compiler defaults for these are doing what they should do:
00056   //: Copy constructor
00057   inline vgl_point_3d(vgl_point_3d<Type> const& p) : x_(p.x()), y_(p.y()), z_(p.z()) {}
00058   //: Destructor
00059   inline ~vgl_point_3d () {}
00060   //: Assignment
00061   inline vgl_point_3d<Type>& operator=(vgl_point_3d<Type>const& p)
00062   { set(p.x(),p.y(),p.z()); return *this; }
00063 #endif
00064 
00065   //: Test for equality
00066   bool operator==(const vgl_point_3d<Type> &p) const;
00067   inline bool operator!=(vgl_point_3d<Type>const& p) const { return !operator==(p); }
00068 
00069   // Data Access-------------------------------------------------------------
00070 
00071   inline Type &x() {return x_;}
00072   inline Type &y() {return y_;}
00073   inline Type &z() {return z_;}
00074 
00075   inline Type x() const {return x_;}
00076   inline Type y() const {return y_;}
00077   inline Type z() const {return z_;}
00078 
00079   //: Set \a x, \a y and \a z
00080   //  Note that \a x, \a y, and \a z can also be set individually
00081   inline void set(Type px, Type py, Type pz) { x_ = px; y_ = py; z_ = pz; }
00082 
00083   //: Set \a x, \a y and \a z
00084   //  Note that \a x, \a y, and \a z can also be set individually
00085   inline void set(Type const p[3]) { x_ = p[0]; y_ = p[1]; z_ = p[2]; }
00086 
00087   //: Return true iff the point is at infinity (an ideal point).
00088   //  Always returns false.
00089   inline bool ideal(Type = (Type)0) const { return false; }
00090 
00091   //: Read from stream, possibly with formatting
00092   //  Either just reads three blank-separated numbers,
00093   //  or reads three comma-separated numbers,
00094   //  or reads three numbers in parenthesized form "(123, 321, 567)"
00095   // \relatesalso vgl_point_3d
00096   vcl_istream& read(vcl_istream& is);
00097 };
00098 
00099 //  +-+-+ point_3d simple I/O +-+-+
00100 
00101 //: Write "<vgl_point_3d x,y,z> " to stream
00102 // \relatesalso vgl_point_3d
00103 template <class Type>
00104 vcl_ostream&  operator<<(vcl_ostream& s, vgl_point_3d<Type> const& p);
00105 
00106 //: Read from stream, possibly with formatting
00107 //  Either just reads three blank-separated numbers,
00108 //  or reads three comma-separated numbers,
00109 //  or reads three numbers in parenthesized form "(123, 321, 567)"
00110 // \relatesalso vgl_point_3d
00111 template <class Type>
00112 vcl_istream&  operator>>(vcl_istream& s, vgl_point_3d<Type>& p);
00113 
00114 //  +-+-+ point_3d arithmetic +-+-+
00115 
00116 //: Return true iff the point is at infinity (an ideal point).
00117 //  Always returns false.
00118 template <class Type> inline
00119 bool is_ideal(vgl_point_3d<Type> const&, Type = 0) { return false; }
00120 
00121 //: The difference of two points is the vector from second to first point
00122 // \relatesalso vgl_point_3d
00123 template <class Type> inline
00124 vgl_vector_3d<Type> operator-(vgl_point_3d<Type> const& p1,
00125                               vgl_point_3d<Type> const& p2)
00126 { return vgl_vector_3d<Type>(p1.x()-p2.x(), p1.y()-p2.y(), p1.z()-p2.z()); }
00127 
00128 //: Adding a vector to a point gives a new point at the end of that vector
00129 // Note that vector + point is not defined!  It's always point + vector.
00130 // \relatesalso vgl_point_3d
00131 template <class Type> inline
00132 vgl_point_3d<Type> operator+(vgl_point_3d<Type> const& p,
00133                              vgl_vector_3d<Type> const& v)
00134 { return vgl_point_3d<Type>(p.x()+v.x(), p.y()+v.y(), p.z()+v.z()); }
00135 
00136 //: Adding a vector to a point gives the point at the end of that vector
00137 // \relatesalso vgl_point_3d
00138 template <class Type> inline
00139 vgl_point_3d<Type>& operator+=(vgl_point_3d<Type>& p,
00140                                vgl_vector_3d<Type> const& v)
00141 { p.set(p.x()+v.x(), p.y()+v.y(), p.z()+v.z()); return p; }
00142 
00143 //: Subtracting a vector from a point is the same as adding the inverse vector
00144 // \relatesalso vgl_point_3d
00145 template <class Type> inline
00146 vgl_point_3d<Type> operator-(vgl_point_3d<Type> const& p,
00147                              vgl_vector_3d<Type> const& v)
00148 { return p + (-v); }
00149 
00150 //: Subtracting a vector from a point is the same as adding the inverse vector
00151 // \relatesalso vgl_point_3d
00152 template <class Type> inline
00153 vgl_point_3d<Type>& operator-=(vgl_point_3d<Type>& p,
00154                                vgl_vector_3d<Type> const& v)
00155 { return p += (-v); }
00156 
00157 //  +-+-+ point_3d geometry +-+-+
00158 
00159 //: cross ratio of four collinear points
00160 // This number is projectively invariant, and it is the coordinate of p4
00161 // in the reference frame where p2 is the origin (coordinate 0), p3 is
00162 // the unity (coordinate 1) and p1 is the point at infinity.
00163 // This cross ratio is often denoted as ((p1, p2; p3, p4)) (which also
00164 // equals ((p3, p4; p1, p2)) or ((p2, p1; p4, p3)) or ((p4, p3; p2, p1)) )
00165 // and is calculated as
00166 //  \verbatim
00167 //                      p1 - p3   p2 - p3      (p1-p3)(p2-p4)
00168 //                      ------- : --------  =  --------------
00169 //                      p1 - p4   p2 - p4      (p1-p4)(p2-p3)
00170 // \endverbatim
00171 // If three of the given points coincide, the cross ratio is not defined.
00172 //
00173 // In this implementation, a least-squares result is calculated when the
00174 // points are not exactly collinear.
00175 //
00176 // \relatesalso vgl_point_3d
00177 template <class T>
00178 double cross_ratio(vgl_point_3d<T>const& p1, vgl_point_3d<T>const& p2,
00179                    vgl_point_3d<T>const& p3, vgl_point_3d<T>const& p4);
00180 
00181 //: Are three points collinear, i.e., do they lie on a common line?
00182 // \relatesalso vgl_point_3d
00183 template <class Type> inline
00184 bool collinear(vgl_point_3d<Type> const& p1,
00185                vgl_point_3d<Type> const& p2,
00186                vgl_point_3d<Type> const& p3)
00187 { return parallel(p1-p2, p1-p3); }
00188 
00189 //: Return the relative distance to p1 wrt p1-p2 of p3.
00190 //  The three points should be collinear and p2 should not equal p1.
00191 //  This is the coordinate of p3 in the affine 1D reference frame (p1,p2).
00192 //  If p3=p1, the ratio is 0; if p1=p3, the ratio is 1.
00193 //  The mid point of p1 and p2 has ratio 0.5.
00194 //  Note that the return type is double, not Type, since the ratio of e.g.
00195 //  two vgl_vector_3d<int> need not be an int.
00196 // \relatesalso vgl_point_3d
00197 template <class Type> inline
00198 double ratio(vgl_point_3d<Type> const& p1,
00199              vgl_point_3d<Type> const& p2,
00200              vgl_point_3d<Type> const& p3)
00201 { return (p3-p1)/(p2-p1); }
00202 
00203 //: Return the point at a given ratio wrt two other points.
00204 //  By default, the mid point (ratio=0.5) is returned.
00205 //  Note that the third argument is Type, not double, so the midpoint of e.g.
00206 //  two vgl_point_3d<int> is not a valid concept.  But the reflection point
00207 //  of p2 wrt p1 is: in that case f=-1.
00208 // \relatesalso vgl_point_3d
00209 template <class Type> inline
00210 vgl_point_3d<Type> midpoint(vgl_point_3d<Type> const& p1,
00211                             vgl_point_3d<Type> const& p2,
00212                             Type f = (Type)0.5)
00213 {
00214   return vgl_point_3d<Type>((Type)((1-f)*p1.x() + f*p2.x()),
00215                             (Type)((1-f)*p1.y() + f*p2.y()),
00216                             (Type)((1-f)*p1.z() + f*p2.z()));
00217 }
00218 
00219 
00220 //: Return the point at the centre of gravity of two given points.
00221 // Identical to midpoint(p1,p2).
00222 // \relatesalso vgl_point_3d
00223 template <class Type> inline
00224 vgl_point_3d<Type> centre(vgl_point_3d<Type> const& p1,
00225                           vgl_point_3d<Type> const& p2)
00226 {
00227   return vgl_point_3d<Type>((p1.x() + p2.x())/2 ,
00228                             (p1.y() + p2.y())/2 ,
00229                             (p1.z() + p2.z())/2 );
00230 }
00231 
00232 //: Return the point at the centre of gravity of three given points.
00233 // \relatesalso vgl_point_3d
00234 template <class Type> inline
00235 vgl_point_3d<Type> centre(vgl_point_3d<Type> const& p1,
00236                           vgl_point_3d<Type> const& p2,
00237                           vgl_point_3d<Type> const& p3)
00238 {
00239   return vgl_point_3d<Type>((p1.x() + p2.x() + p3.x())/3 ,
00240                             (p1.y() + p2.y() + p3.y())/3 ,
00241                             (p1.z() + p2.z() + p3.z())/3 );
00242 }
00243 
00244 //: Return the point at the centre of gravity of four given points.
00245 // \relatesalso vgl_point_3d
00246 template <class Type> inline
00247 vgl_point_3d<Type> centre(vgl_point_3d<Type> const& p1,
00248                           vgl_point_3d<Type> const& p2,
00249                           vgl_point_3d<Type> const& p3,
00250                           vgl_point_3d<Type> const& p4)
00251 {
00252   return vgl_point_3d<Type>((p1.x() + p2.x() + p3.x() + p4.x())/4 ,
00253                             (p1.y() + p2.y() + p3.y() + p4.y())/4 ,
00254                             (p1.z() + p2.z() + p3.z() + p4.z())/4 );
00255 }
00256 
00257 //: Return the point at the centre of gravity of a set of given points.
00258 // Beware of possible rounding errors when Type is e.g. int.
00259 // \relatesalso vgl_point_3d
00260 template <class Type> inline
00261 vgl_point_3d<Type> centre(vcl_vector<vgl_point_3d<Type> > const& v)
00262 {
00263   int n = (int)(v.size());
00264   assert(n>0); // it is *not* correct to return the point (0,0) when n==0.
00265   Type x = 0, y = 0, z = 0;
00266   for (int i=0; i<n; ++i) x+=v[i].x(), y+=v[i].y(), z+=v[i].z();
00267   return vgl_point_3d<Type>(x/n,y/n,z/n);
00268 }
00269 
00270 //: Return the "average deviation" of a set of given points from its centre of gravity.
00271 //  "Average" in the sense of the standard deviation (2-norm, i.e., square root
00272 //  of sum of squares) of the distances from that centre of gravity.
00273 // \relatesalso vgl_point_3d
00274 template <class Type>
00275 double stddev(vcl_vector<vgl_point_3d<Type> > const& v);
00276 
00277 //: Return true iff the 4 points are coplanar, i.e., they belong to a common plane
00278 // \relatesalso vgl_point_3d
00279 template <class Type>
00280 bool coplanar(vgl_point_3d<Type> const& p1,
00281               vgl_point_3d<Type> const& p2,
00282               vgl_point_3d<Type> const& p3,
00283               vgl_point_3d<Type> const& p4);
00284 
00285 #define VGL_POINT_3D_INSTANTIATE(T) extern "please include vgl/vgl_point_3d.txx first"
00286 
00287 #endif // vgl_point_3d_h