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