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

Generated on Mon Mar 8 05:07:51 2010 for core/vgl by  doxygen 1.5.1